springboot 统一异常处理(包含统一数据校验)
1、统一异常处理的优势
在开发中,我们是否遇到过如下两种奇葩现象:
(1)只要没有成功,不管什么原因,前端界面给出提示:服务端错误/异常。哪怕是数据校验不过,也这样提示(嗯,反正先把锅甩出去再说,具体什么原因我才不在乎呢,老子就是这么聪明);
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:787707172,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
(2)前端不做任何提示,一切提示信息都来自后端,成功的时候自然没什么,失败的时候,比如将Exception的描述信息(e.getMessage)返回。
现象(1)没什么好说的,直接拖出去枪毙吧;现象(2)先把产品经理宰了再说吧,看起来好像很专业的样子,出了什么问题直接看response返回的结果就知道个大概,研发测试都很方便,只是,大家想过没有,研发测试运维的问题,凭什么要用户买单,你见过淘宝京东有时候出了问题给你类似于“out of memory”的异常提示吗?
那么异常统一处理有什么好处呢?
提高用户体验;
业务逻辑和异常处理逻辑解耦;
对异常进行分类统一处理,减少冗余代码;
便于代码风格统一,并且更优雅(比如参数校验的时候,得写很多if else,并且不同的人写法不一致);
2、统一异常处理的实现
2.1 springboot的默认异常处理
Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容。
比如:
@RestController
public class Test {
@RequestMapping(value = {"/test"},method = RequestMethod.GET)
public String test(@RequestParam("id")Integer id){
return "id:"+id;
}
}
运行后访问结果如下:
springboot 统一异常处理(包含统一数据校验)
这种直接返回错误页面,对于用户而言,显然是太不友好了哈!
2.2 统一异常处理
java异常详解
首先,定义自己的异常类,随便起个名字哈,MyException.java
@Data
public class MyException extends Exception{
private Integer code;
private String Message;
public MyException(Integer code,String Message) {
this.code = code;
this.Message = Message;
}
}
然后定义自己的异常处理类,ExceptionHandle.java
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:787707172,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
如果返回的对象是JSON的话,可以用@RestControllerAdvice
@ControllerAdvice
public class ExceptionHandle {
private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e) {
if (e instanceof MyException) {
MyException myException = (MyException) e;
return ResultUtil.error(boyException.getCode(), boyException.getMessage());
}else {
logger.error("【系统异常】{}", e);
return new Result(-1, "未知错误");
}
}
}
3、统一异常处理源码解析
3.1 注解源码解析
java注解详解
@ControllerAdvice
@ExceptionHandler
@RestControllerAdvice与@ExceptionHandler注解是sprngmvc中与异常捕获与处理相关的注解,它的入口也是DispatcherServlet中的doDispatcher()方法中,如下:
this.processDispatchResult(processedRequest,
response, mappedHandler, mv, (Exception)dispatchException);
后面会进入HandlerExceptionResolverComposite的resolveException方法,这个ExceptionHandlerResolverComposite包含三个ExcpetionHandlerResolver,是在springmvc中生成的,在springboot中其生成代码如下:
@Bean public HandlerExceptionResolver handlerExceptionResolver() { List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>(); configureHandlerExceptionResolvers(exceptionResolvers); if (exceptionResolvers.isEmpty()) { addDefaultHandlerExceptionResolvers(exceptionResolvers); } extendHandlerExceptionResolvers(exceptionResolvers); HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite(); composite.setOrder(0); composite.setExceptionResolvers(exceptionResolvers); return composite; }
后面他会进入ExceptionHandlerExceptionResolver类的方法:
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod,
Exception exception) {
ServletInvocableHandlerMethod exceptionHandlerMethod =
getExceptionHandlerMethod(handlerMethod, exception);
}
在这个方法中的第一行,getExceptionHandlerMethod方法,其进行了查找对应的带有@ControllerAdvice注解的类型和对应匹配的方法,然后在doResolverHandlerMethod方法中进行了处理,这就是整个流程。
@ControllerAdvice的加载过程:
首先在springboot扫描的时候,会把@ControllerAdvice的bean放入到beanFactory里面去,此时只要从beanFactory中获取到需要的bean即可,处理方式在ExceptionHandlerExceptionResolver类中:
@Override public void afterPropertiesSet() { // Do this first, it may add ResponseBodyAdvice beans initExceptionHandlerAdviceCache(); private void initExceptionHandlerAdviceCache() { if (getApplicationContext() == null) { return; } if (logger.isDebugEnabled()) { logger.debug("Looking for exception mappings: " + getApplicationContext()); } List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());
封装好后,获取带有@Exceptionhandler的注解方法,即根据异常类型进行调用了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
.net基础学java系列(三)徘徊反思
.net基础学java系列(三)徘徊反思一、准备被分配到子公司子公司不是弹性上下班,上班必须准点,晚上随便你加班!每天需要提前一个小时起床,挤地铁,这生物钟没那么快调整得过来。工作内容需要整理,遗留的疑难杂症需要给交代。二、观望.net的工作,捡回.net基本知识,面试.NET面试题解析,看完还是感觉有很多遗忘的!值类型与引用类型拆箱与装箱string与字符操作类型、方法与继承常量、字段、属性、特性与委托GC与内存管理多线程编程与线程同步代码调试与异常处理CLR、程序集与反射OO原则与设计模式SQL语言基础及数据库基本原理.NET其他面试点,囫囵吞枣看了部分,有点烧脑了C# 新特性:https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-version-historyNetFrameWork新特性:https://docs.microsoft.com/zh-cn/dotnet/framework/whats-new/index数据结构与算法:http://www.cnblogs.com/skywang12345/p...
- 下一篇
【内容安全】虚拟化及云环境下数据库审计优缺点分析
原标题:虚拟化及云环境下数据库审计技术探讨随着越来越多的企业用户将传统的业务系统迁移至虚拟化环境或是云服务商提供的云平台,数据的泄露及篡改风险变的越发严峻,针对数据安全的防护以及事后审计追溯也变得越来越困难。究其原因,主要是传统的数据库审计解决方案是通过旁路分析目标被审计数据库镜像的流量,而虚拟化环境或者云平台由于内部的虚拟交换机(Vswitch)流量很难镜像或者无法镜像,因此传统的数据库审计解决方案不足以应对虚拟化和云平台的数据库审计需求。 首先我们对虚拟化及云平台环境中,传统的数据库审计解决方案在典型的几种场景下的优缺点进行解析: 场景一:应用和数据库的虚拟主机不在同一台物理机器上 如下图所示这种情况下的应用和数据库虚拟主机不在同一台物理机器上,对传统数据库审计来说,可以采用传统方式直接镜像数据库服务器所在的物理宿主主机(物理机器4)网卡的流量,完成对目标数据库的审计,缺点是需要将虚拟机流量全部镜像过去,同时可能会导致一些无需审计的主机的数据的泄露,这是这种解决方案最大的一个风险。 场景二:应用和数据库的虚拟主机在同一台物理机器上 针对应用和数据库在同一台物理机器上,应用和数据库的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS6,CentOS7官方镜像安装Oracle11G