一网打尽 @ExceptionHandler、HandlerExceptionResolver、@controlleradvice 三兄弟!
把 @ExceptionHandler、HandlerExceptionResolver、@controlleradvice 三兄弟放在一起来写更有比较性。这三个东西都是用来处理异常的,但是它们使用的场景都不一样。看本文给你详细的讲解,再也不怕面试被问到了!
这三个注解都是来自于 SpringMVC 的,都能进行异常处理。
Java 程序员都非常的痛恨异常,很多人讨厌 Java 就是因为它的异常处理机制。到处的 try-catch-finally,再不是就是到处抛出异常。
所以 Spring 深知 Java 的疼点,推出了:@ExceptionHandler、HandlerExceptionResolver、@controlleradvice 来方便我们处理一些异常!
@ExceptionHandler 注解
用于局部方法捕获,与抛出异常的方法处于同一个 Controller 类。源码如下:
|
1
2
3
4
5
6
|
@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ExceptionHandler { Class<? extends Throwable>[] value() default {};} |
从源码中可以看出,@ExceptionHandler 注解只能作用为对象的方法上,并且在运行时有效,value() 可以指定异常类。由该注解注释的方法可以具有灵活的输入参数。
异常参数可以包括一般的异常或特定的异常(即自定义异常),如果注解没有指定异常类,会默认进行映射。
用法代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Controllerpublic class XttblogController { @ExceptionHandler({NullPointerException.class}) public String exception(NullPointerException e) { System.out.println(e.getMessage()); e.printStackTrace(); return "null pointer exception"; } @RequestMapping("test") public void test() { throw new NullPointerException("出错了!"); }} |
上面这段代码只会捕获 XttblogController 类中的 NullPointerException 异常。
HandlerExceptionResolver 接口
HandlerExceptionResolver 是 Spring 提供的一个接口。它可以用来处理全局异常!
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Componentpublic class GlobalExceptionResolver implements HandlerExceptionResolver{ private ObjectMapper objectMapper; public CustomMvcExceptionHandler() { objectMapper = new ObjectMapper(); } @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,Object o, Exception ex) { response.setStatus(200); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); response.setHeader("Cache-Control", "no-cache, must-revalidate"); Map<String, Object> map = new HashMap<>(); if (ex instanceof NullPointerException) { map.put("code", ResponseCode.NP_EXCEPTION); } else if (ex instanceof IndexOutOfBoundsException) { map.put("code", ResponseCode.INDEX_OUT_OF_BOUNDS_EXCEPTION); } else { map.put("code", ResponseCode.CATCH_EXCEPTION); } try { map.put("data", ex.getMessage()); response.getWriter().write(objectMapper.writeValueAsString(map)); } catch (Exception e) { e.printStackTrace(); } return new ModelAndView(); }} |
在 Spring 源码中,我们可以看出它会获取一个实现了 HandlerExceptionResolver 接口的列表
List<HandlerExceptionResolver> resolvers; 如果这个列表不为空,则循环处理其中的异常。
HandlerExceptionResolve 虽然能够处理全局异常,但是 Spring 官方不推荐使用它。
@controlleradvice 注解
另外一个能够处理全局异常的就是 @controlleradvice 注解了。
@controlleradvice 注解根据它的源码,我们知道它也只能作用在类上,并且作用于运行时。下面我们来看一个例子。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@ControllerAdvicepublic class ExceptionController { @ExceptionHandler(RuntimeException.class) public ModelAndView handlerRuntimeException(RuntimeException ex) { if (ex instanceof MaxUploadSizeExceededException) { return new ModelAndView("error").addObject("msg", "文件太大!"); } return new ModelAndView("error").addObject("msg", "未知错误:" + ex); } @ExceptionHandler(Exception.class) public ModelAndView handlerMaxUploadSizeExceededException(Exception ex) { if (ex != null) { return new ModelAndView("error").addObject("msg", ex); } return new ModelAndView("error").addObject("msg", "未知错误:" + ex); }} |
需要注意的是,@ControllerAdvice 一般是和 @ExceptionHandler 组合在一起使用的。官方也推荐用这种方式处理统一全局异常。
一网打尽 @ExceptionHandler、HandlerExceptionResolver、@controlleradvice 三兄弟!的更多相关文章
- Nancy之Pipelines三兄弟(Before After OnError)
一.简单描述 Before:如果返回null,拦截器将主动权转给路由:如果返回Response对象,则路由不起作用. After : 没有返回值,可以在这里修改或替换当前的Response. OnEr ...
- 好用的排名函数~ROW_NUMBER(),RANK(),DENSE_RANK() 三兄弟
排名函数三兄弟,一看名字就知道,都是为了排名而生!但是各自有各自的特色!以下一个例子说明问题!(以下栗子没有使用Partition By 的关键字,整个结果集进行排序) RANK 每个值一个排名,同样 ...
- sql语句中----删除表数据的"三兄弟"
说到删除表数据的关键字,大家记得最多的可能就是delete了 然而我们做数据库开发,读取数据库数据.对另外的两兄弟用得就比较少了 现在来介绍另外两个兄弟,都是删除表数据的,其实也是很容易理解的 老大- ...
- @ExceptionHandler和@ControllerAdvice统一处理异常
//@ExceptionHandler和@ControllerAdvice统一处理异常//统一处理异常的controller需要放在和普通controller同级的包下,或者在ComponentSca ...
- Promise的三兄弟:all(), race()以及allSettled()
摘要: 玩转Promise. 原文:Promise 中的三兄弟 .all(), .race(), .allSettled() 译者:前端小智 Fundebug经授权转载,版权归原作者所有. 从ES6 ...
- 设计模式系列之工厂模式三兄弟(Factory Pattern)
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- Mysql 中写操作时保驾护航的三兄弟!
这期的文章主要是讲述写操作过程中涉及到的三个日志文件,看过前几期的话可能你或多或少已经有些了解了(或者从别的地方也了解过).比如整个写操作过程中用到的两阶段提交,又或者是操作过程中涉及到的日志文件,但 ...
- 站长管理服务器必读:Ftp、Ftps与Sftp三兄弟的不同与区别以及部署全指引
文章标题: 站长管理服务器必读:Ftp.Ftps与Sftp三兄弟的不同与区别以及部署全指引 关键字 : ftp,sftp,freesshd,ftps 文章分类: 教程 创建时间: 2020年3月23日 ...
- SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-005- 异常处理@ResponseStatus、@ExceptionHandler、@ControllerAdvice
No matter what happens, good or bad, the outcome of a servlet request is a servlet response. If an e ...
随机推荐
- Java 根据银行卡号获取银行名称以及图标
转 https://blog.csdn.net/N_007/article/details/78835526 参考 CNBankCard 中国各大银行卡号查询 一.支付宝接口获取名称 根据 卡号 获取 ...
- Flask 之装饰器有关
- 先记住一句话:自定义python装饰器时一定要记住使用@functools.wraps(func)修饰wrapper - 在Flask中使用装饰器遇到AssertionError: View fu ...
- w = tf.Variable(<initial-value>, name=<optional-name>)
w = tf.Variable(<initial-value>, name=<optional-name>)
- vue中怎么使用vuex
做一个简单的vuex如何使用的介绍: 先安装: npm i vuex --save-dev 新建一个store文件夹, 在store文件夹中建一个index.js文件,在该文件中: i ...
- 3 Base64编码主要应用在那些场合?
,电子邮件数据也好,经常要用到Base64编码,那么为什么要作一下这样的编码呢? 我们知道在计算机中任何数据都是按ascii码存储的,而ascii码的128-255之间的值是不可见字符.而在网络上交换 ...
- 2017 ICPC HongKong B:Black and White(扫描线+线段树)
题目描述 Consider a square map with N × N cells. We indicate the coordinate of a cell by (i, j), where 1 ...
- web大文件断点续传
1,项目调研 因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 在GoogleCode上面,代码弄下来超级不方便,还是配置hosts才好,把代码重新上传到了github上面. http ...
- Linux负载均衡软件LVS
linux下的开源负载均衡软件LVS的安装.配置和使用.LVS是一个中国人创建和开发的开放源码项目,利用LVS可以构建高可用.高可靠的负载均衡集群,因此,利用Linux+LVS不但可以假设高性能的负载 ...
- xpath定位不到原因浅析
在爬虫中,我们经常使用xpath来对元素进行定位,xpath定位分为两种,一种是绝对定位,/html/body/div[2]/div[1]/div/div[3]/a[7],另外一种是相对定位,比如r' ...
- python数据类
前言 之前有写过一篇python元类的笔记,元类主要作用就是在要创建的类中使用参数metaclass=YourMetaclass调用自定义的元类,这样就可以为所有调用了这个元类的类添加相同的属性了. ...