背景
- 使用resttemplate请求特定接口,并根据获取的http状态码进行具体业务操作。
@restcontroller
public class restfulcontroller {
private resttemplate resttemplate = new resttemplate();
@getmapping("/test1")
public void test1(httpservletresponse response) {
response.setstatus(403);
}
@getmapping("/test2")
public void test2() {
responseentity responseentity = resttemplate.exchange("http://127.0.0.1:8080/test1", httpmethod.get, new httpentity<string>(null, new httpheaders()), string.class);
int code = responseentity.getstatuscodevalue();
// 具体业务操作...
}
}
报错
org.springframework.web.client.httpclienterrorexception$forbidden: 403 null
解决
- 如果想要使用responseentity.getstatuscodevalue()等,需要先为resttemplate对象设置responseerrorhandler。
- 需要注意代码并不符合平常的开发规范,只是为了实现效果。
@restcontroller
public class restfulcontroller {
private resttemplate resttemplate = new resttemplate();
@getmapping("/test1")
public void test1(httpservletresponse response) {
response.setstatus(403);
}
@getmapping("/test2")
public void test2() {
resttemplate.seterrorhandler(new restfulcontroller.errorhandler());
responseentity responseentity = resttemplate.exchange("http://127.0.0.1:8080/test1", httpmethod.get, new httpentity<string>(null, new httpheaders()), string.class);
int code = responseentity.getstatuscodevalue();
// 业务处理...
}
static class errorhandler implements responseerrorhandler {
@override
public boolean haserror(clienthttpresponse clienthttpresponse) throws ioexception {
if (200 == clienthttpresponse.getrawstatuscode()) {
return false;
}
return true;
}
@override
public void handleerror(clienthttpresponse clienthttpresponse) throws ioexception {
// 处理error...
}
}
}
原因
- resttemplate
public class resttemplate extends interceptinghttpaccessor implements restoperations {
...
private responseerrorhandler errorhandler;
...
public resttemplate() {
...
// 默认的responseerrorhandler
this.errorhandler = new defaultresponseerrorhandler();
...
}
...
@nullable
protected <t> t doexecute(uri url, @nullable httpmethod method, @nullable requestcallback requestcallback, @nullable responseextractor<t> responseextractor) throws restclientexception {
assert.notnull(url, "uri is required");
assert.notnull(method, "httpmethod is required");
clienthttpresponse response = null;
object var14;
try {
clienthttprequest request = this.createrequest(url, method);
if (requestcallback != null) {
requestcallback.dowithrequest(request);
}
response = request.execute();
// 处理response, 这里如果抛出异常,就不会返回responseentity对象
this.handleresponse(url, method, response);
var14 = responseextractor != null ? responseextractor.extractdata(response) : null;
} catch (ioexception var12) {
string resource = url.tostring();
string query = url.getrawquery();
resource = query != null ? resource.substring(0, resource.indexof(63)) : resource;
throw new resourceaccessexception("i/o error on " + method.name() + " request for \"" + resource + "\": " + var12.getmessage(), var12);
} finally {
if (response != null) {
response.close();
}
}
return var14;
}
protected void handleresponse(uri url, httpmethod method, clienthttpresponse response) throws ioexception {
responseerrorhandler errorhandler = this.geterrorhandler();
boolean haserror = errorhandler.haserror(response);
if (this.logger.isdebugenabled()) {
try {
int code = response.getrawstatuscode();
httpstatus status = httpstatus.resolve(code);
this.logger.debug("response " + (status != null ? status : code));
} catch (ioexception var8) {
}
}
if (haserror) {
// 处理http错误码
errorhandler.handleerror(url, method, response);
}
}
...
}
- defaultresponseerrorhandler
public class defaultresponseerrorhandler implements responseerrorhandler {
public defaultresponseerrorhandler() {
}
public boolean haserror(clienthttpresponse response) throws ioexception {
int rawstatuscode = response.getrawstatuscode();
httpstatus statuscode = httpstatus.resolve(rawstatuscode);
return statuscode != null ? this.haserror(statuscode) : this.haserror(rawstatuscode);
}
protected boolean haserror(httpstatus statuscode) {
return statuscode.iserror();
}
protected boolean haserror(int unknownstatuscode) {
series series = series.resolve(unknownstatuscode);
return series == series.client_error || series == series.server_error;
}
public void handleerror(clienthttpresponse response) throws ioexception {
httpstatus statuscode = httpstatus.resolve(response.getrawstatuscode());
if (statuscode == null) {
throw new unknownhttpstatuscodeexception(response.getrawstatuscode(), response.getstatustext(), response.getheaders(), this.getresponsebody(response), this.getcharset(response));
} else {
this.handleerror(response, statuscode);
}
}
protected void handleerror(clienthttpresponse response, httpstatus statuscode) throws ioexception {
string statustext = response.getstatustext();
httpheaders headers = response.getheaders();
byte[] body = this.getresponsebody(response);
charset charset = this.getcharset(response);
switch(statuscode.series()) {
case client_error:
throw httpclienterrorexception.create(statuscode, statustext, headers, body, charset);
case server_error:
throw httpservererrorexception.create(statuscode, statustext, headers, body, charset);
default:
throw new unknownhttpstatuscodeexception(statuscode.value(), statustext, headers, body, charset);
}
}
...
}
- resttemplate中的getforentity(…)、 getforobject(…)、exchange(…)和delete(…)等方法最终都是调用doexecute(uri url, @nullable httpmethod method, @nullable requestcallback requestcallback, @nullable responseextractor responseextractor)方法。
- 从源代码可以看出来默认的处理器defaultresponseerrorhandler,最后会抛出三种异常:httpclienterrorexception、httpservererrorexception、unknownhttpstatuscodeexception。所以在得到responseentity返回值之前,就有异常抛出。
- 可以自定义错误处理器,自定义的处理器并没有抛出异常,所以也就可以返回responseentity对象,并通过该对象的getstatuscodevalue()方法获取http状态码。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论