RestTemplate如何獲取HTTP狀態(tài)碼
背景
- 使用RestTemplate請(qǐng)求特定接口,并根據(jù)獲取的HTTP狀態(tài)碼進(jìn)行具體業(yè)務(wù)操作。
@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();
// 具體業(yè)務(wù)操作...
}
}
報(bào)錯(cuò)
?org.springframework.web.client.HttpClientErrorException$Forbidden: 403 null
解決
- 如果想要使用responseEntity.getStatusCodeValue()等,需要先為RestTemplate對(duì)象設(shè)置ResponseErrorHandler。
- 需要注意代碼并不符合平常的開發(fā)規(guī)范,只是為了實(shí)現(xiàn)效果。
@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();
// 業(yè)務(wù)處理...
}
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() {
...
// 默認(rèn)的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, 這里如果拋出異常,就不會(huì)返回ResponseEntity對(duì)象
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錯(cuò)誤碼
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(…)等方法最終都是調(diào)用doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor responseExtractor)方法。
- 從源代碼可以看出來默認(rèn)的處理器DefaultResponseErrorHandler,最后會(huì)拋出三種異常:HttpClientErrorException、HttpServerErrorException、UnknownHttpStatusCodeException。所以在得到ResponseEntity返回值之前,就有異常拋出。
- 可以自定義錯(cuò)誤處理器,自定義的處理器并沒有拋出異常,所以也就可以返回ResponseEntity對(duì)象,并通過該對(duì)象的getStatusCodeValue()方法獲取HTTP狀態(tài)碼。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot手寫RestTemplate攔截器鏈,掌控HTTP請(qǐng)求實(shí)踐
- SpringBoot使用RestTemplate如何通過http請(qǐng)求將文件下載到本地
- SpringBoot使用RestTemplate發(fā)送http請(qǐng)求的實(shí)操演示
- 如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問題
- SpringBoot使用RestTemplate實(shí)現(xiàn)HTTP請(qǐng)求詳解
- springboot中RestTemplate發(fā)送HTTP請(qǐng)求的實(shí)現(xiàn)示例
- Spring RestTemplate簡(jiǎn)化HTTP通信實(shí)現(xiàn)功能探究
相關(guān)文章
SpringSecurity的@EnableWebSecurity注解詳解
這篇文章主要介紹了SpringSecurity的@EnableWebSecurity注解詳解,@EnableWebSecurity是開啟SpringSecurity的默認(rèn)行為,它的上面有一個(gè)Import注解導(dǎo)入了WebSecurityConfiguration類,就是往IOC容器中注入了WebSecurityConfiguration這個(gè)類,需要的朋友可以參考下2023-11-11
Eclipse+Java+Swing+Mysql實(shí)現(xiàn)工資管理系統(tǒng)
這篇文章主要介紹了Eclipse+Java+Swing+Mysql實(shí)現(xiàn)工資管理系統(tǒng),對(duì)正在工作或者學(xué)習(xí)的你有一定的參考價(jià)值,需要的朋友可以參考一下2022-01-01
Java實(shí)現(xiàn)把excel xls中數(shù)據(jù)轉(zhuǎn)為可直接插入數(shù)據(jù)庫(kù)的sql文件
這篇文章主要介紹了Java實(shí)現(xiàn)把excel xls中數(shù)據(jù)轉(zhuǎn)為可直接插入數(shù)據(jù)庫(kù)的sql文件 的相關(guān)資料,需要的朋友可以參考下2016-03-03
Java中的CyclicBarrier循環(huán)柵欄深入解析
這篇文章主要介紹了Java中的CyclicBarrier循環(huán)柵欄深入解析,CycleBarrier 它就相當(dāng)于是一個(gè)柵欄,所有線程在到達(dá)柵欄后都需要等待其他線程,等所有線程都到達(dá)后,再一起通過,需要的朋友可以參考下2023-12-12
Java使用Tess4J實(shí)現(xiàn)圖像識(shí)別方式
這篇文章主要介紹了Java使用Tess4J實(shí)現(xiàn)圖像識(shí)別方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
經(jīng)典的Java面試題及回答集錦(基礎(chǔ)篇)
本文給大家收藏整理了java面試題及回答,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2018-03-03
java中線程池最實(shí)用的創(chuàng)建與關(guān)閉指南
試中經(jīng)常會(huì)問到,創(chuàng)建一個(gè)線程池需要哪些參數(shù)啊,線程池的工作原理啊,卻很少會(huì)問到線程池如何安全關(guān)閉的,下面這篇文章主要給大家介紹了關(guān)于java中線程池最實(shí)用的創(chuàng)建與關(guān)閉的相關(guān)資料,需要的朋友可以參考下2021-09-09
詳解SpringBoot之訪問靜態(tài)資源(webapp...)
這篇文章主要介紹了詳解SpringBoot之訪問靜態(tài)資源(webapp...),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Mybatis StatementHandler的使用小結(jié)
本文主要介紹了Mybatis StatementHandler的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-03-03

