自定义resttemplate的ErrorHandler
结论:
resttemplate有默认的ErrorHandler,resttemplate发起http请求,一旦server抛异常,默认的只能打印status,无法打印message,自定义ErrorHandler,能打印status和message
server
@RestController
public class HelloController {@GetMapping("/hello")public String hello() {int i = 1 / 0;return "hello world";}
}
client
postman
用postman请求,返回如下,能解析异常信息,"message": "/ by zero",
restTemplate
但为啥restTemplate请求只能看到状态码,看不到详细信息呢,光看到500肯定是不够的,原因是resttemplate没有自定义ErrorHandler
2019-12-14 12:42:07.207 ERROR [hyg,,,] 10144 --- [ main] c.h.d.r.ResponseErrorHandlerTest : 请求失败,url http://localhost:8000/helloorg.springframework.web.client.HttpServerErrorException$InternalServerError: 500 nullat org.springframework.web.client.HttpServerErrorException.create(HttpServerErrorException.java:79) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
restTemplate code
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class ResponseErrorHandlerTest {@Autowiredprivate RestTemplate restTemplate;@Testpublic void responseErrorHandlerTest() {String url = "http://localhost:8000/hello";try {String hello = restTemplate.getForObject(url, String.class);assertThat(hello).contains(hello);} catch (Exception e) {log.error("请求失败,url {}", url, e);}}
}
自定义ErrorHandler能打印出来
自定义ErrorHandler,是不是能看到了
2019-12-14 12:50:20.302 ERROR [hyg,,,] 8044 --- [ main] c.h.d.r.ResponseErrorHandlerTest : 请求HelloException失败,异常信息 {"timestamp":"2019-12-14 12:50:20","status":500,"error":"Internal Server Error","message":"/ by zero","path":"/hello"}
2019-12-14 12:50:20.318 ERROR [hyg,,,] 8044 --- [ main] c.h.d.r.ResponseErrorHandlerTest : 请求失败,url http://localhost:8000/hellocom.hyg.demo.spring.resttemplate.HelloException: {"timestamp":"2019-12-14 12:50:20","status":500,"error":"Internal Server Error","message":"/ by zero","path":"/hello"}at com.hyg.demo.resttemplate.ResponseErrorHandlerTest.responseErrorHandlerTest(ResponseErrorHandlerTest.java:37) ~[test-classes/:na]
如何自定义resttemplate的ErrorHandler
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class ResponseErrorHandlerTest {@Autowiredprivate RestTemplate restTemplate;@Testpublic void responseErrorHandlerTest() {this.restTemplate = new RestTemplate();restTemplate.setErrorHandler(responseErrorHandler(new HelloException()));String url = "http://localhost:8000/hello";try {String hello = restTemplate.getForObject(url, String.class);assertThat(hello).contains(hello);} catch (Exception e) {log.error("请求失败,url {}", url, e);}}private ResponseErrorHandler responseErrorHandler(HelloException helloException) {return new ResponseErrorHandler() {@Overridepublic boolean hasError(ClientHttpResponse response) throws IOException {return (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR ||response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);}@Overridepublic void handleError(ClientHttpResponse response) throws IOException {String body = org.apache.commons.io.IOUtils.toString(response.getBody(), StandardCharsets.UTF_8);log.error("请求{}失败,异常信息 {}", helloException.getClass().getSimpleName(), body);try {helloException.setStatus(response.getStatusCode().value());helloException.setMessage(body);helloException.setServerSide(response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);helloException.setRetryAble(response.getStatusCode().series() != HttpStatus.Series.CLIENT_ERROR);throw helloException;} catch (Exception e) {helloException.setStatus(response.getStatusCode().value());helloException.setMessage(body);throw helloException;}}};}
}
服务端异常:一般以服务端名称+Exception命名
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString(callSuper = true)
@Builder
public class HelloException extends RuntimeException{private int status; //http状态码private boolean isServerSide; //是不是server异常private boolean retryAble; // 是否重试,如果不是client_error就会重试private String code;private String message; //异常信息的bodyprivate Map<String,String> detail;
}
DefaultResponseErrorHandler
resttemplate的私有成员变量
private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();
DefaultResponseErrorHandlerd的handleError方法
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {String statusText = response.getStatusText();HttpHeaders headers = response.getHeaders();byte[] body = getResponseBody(response);Charset charset = getCharset(response);switch (statusCode.series()) {case CLIENT_ERROR: throw HttpClientErrorException.create(statusCode, statusText, headers, body, charset);case SERVER_ERROR: //body是详细信息,但没把body赋值给messagethrow HttpServerErrorException.create(statusCode, statusText, headers, body, charset);default:throw new UnknownHttpStatusCodeException(statusCode.value(), statusText, headers, body, charset);}}// 把statusCode.value() + " " + statusText当做maeeage,传给RestClientResponseExceptionorg.springframework.web.client.RestClientResponseException#RestClientResponseException
super(statusCode.value() + " " + statusText, statusCode.value(), statusText,responseHeaders, responseBody, responseCharset);public RestClientResponseException(String message, int statusCode, String statusText,@Nullable HttpHeaders responseHeaders, @Nullable byte[] responseBody, @Nullable Charset responseCharset) {super(message);this.rawStatusCode = statusCode;this.statusText = statusText;this.responseHeaders = responseHeaders;this.responseBody = (responseBody != null ? responseBody : new byte[0]);this.responseCharset = (responseCharset != null ? responseCharset.name() : null);}
自定义resttemplate的ErrorHandler相关推荐
- SpringBoot系列: RestTemplate 快速入门
==================================== 相关的文章 ==================================== SpringBoot系列: 与Sprin ...
- 关注点分离之RestTemplate的错误处理
作者:JackieTang 来源:生活点亮技术 1. 概览 在这个简短的教程中,将讨论如何实现一个自定义ResponseErrorHandler类并将其注入到RestTemplate实例中去,这样我们 ...
- RestTemplate实践
一.RestTemplate是什么 环境约束: spring-web-4.3.9.RELEASE Spring文档: https://docs.spring.io/spring/docs/4.3.9. ...
- 服务启动报错:Consider defining a bean of type ‘.RestTemplate‘ in your configuration
Spring Boot <= 1.3 No need to define one, Spring Boot automatically defines one for you. (springb ...
- RestTemplate结合OkHttp3通用Rest Client客户端
RestTemplate结合OkHttp3通用Rest Client客户端 文章目录 RestTemplate结合OkHttp3通用Rest Client客户端 一.OkHttp3 Authentic ...
- flask中的flask_uploads上传文件
文章目录 1.测试结果: 2.主文件main.py: 3.显示错误页面404.html文件: 4.文件上传界面upload_Files.html: 1.测试结果: 如果上传的文件格式不符合要求的,则显 ...
- python中关于sqlite3数据库更新数据的使用
1.文件结构: 其中html文件放置的文件名必须是templates,图片放置的文件名必须是static: 2.使用的数据库可视化工具DB Browser for sqlite下载: http://w ...
- python中关于sqlite3数据库删除数据的使用
1.文件结构: 2.使用的数据库可视化工具DB Browser for sqlite下载: http://www.sqlitebrowser.org/ 3.使用DB Browser for sqlit ...
- python中使用html前端页面显示图像预测结果(改进)
改进之处主要是代码,页面都没有发送改变: 现在使用文件类选择文件和上传文件: 以上框出来的地方就是改进之处: 1.训练的权重文件: 自己训练的权重文件,其中数据集来自身边收集,只训练的5个类别: 分别 ...
最新文章
- 整理对应_JSP第二版课后习题答案【侵权联系我删除】
- A Survey on Techniques in NLP--阅读笔记
- 【很详细】JDK安装与环境变量配置
- python中curve fit_在python中拟合多变量curve_fit
- ES6-2 块级作用域与嵌套、let、暂行性死区
- 解决: VUE 项目中表单提交中文乱码、接口请求参数中文乱码
- (推荐)jQuery性能优化指南
- input里面check 状态检测
- weight和weightSum的区别
- 解决IEM被禁用的问提
- 【关于PTA平台中出现的问题】warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result
- php表格整体怎么移动,超级表格新版移动端操作指南
- linux中负载值为多少正常_Linux系统Load average负载详细解释
- python优惠券机器人_python实现机器人卡牌
- 妈蛋!! 居然是打广告的
- Eyenuk宣布FDA核准EyeArt自主AI系统用于糖尿病视网膜病变筛查
- selenium驱动Firefox安装和环境配置
- 一文读懂蒙特卡洛方法:谷歌围棋机器人科普
- 海思Hi3559AV100移植Qt5.9.1
- 从拼多多优惠券事件看到的一些反思