在Spring 3.2中,新增了@ControllerAdvice、@RestControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping、@PostMapping, @GetMapping注解中。
接下来我将通过代码展示如何使用这些注解,以及处理异常。

1.注解的介绍

先定义一个ControllerAdvice。代码如下

/*** @author Lensen* @desc* @since 2018/10/5 11:01*/
@ControllerAdvice
public class MyExceptionHandler {/*** 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器* @param binder*/@InitBinderpublic void initWebBinder(WebDataBinder binder){//对日期的统一处理binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));//添加对数据的校验//binder.setValidator();}/*** 把值绑定到Model中,使全局@RequestMapping可以获取到该值* @param model*/@ModelAttributepublic void addAttribute(Model model) {model.addAttribute("attribute",  "The Attribute");}/*** 捕获CustomException* @param e* @return json格式类型*/@ResponseBody@ExceptionHandler({CustomException.class}) //指定拦截异常的类型@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定义浏览器返回状态码public Map<String, Object> customExceptionHandler(CustomException e) {Map<String, Object> map = new HashMap<>();map.put("code", e.getCode());map.put("msg", e.getMsg());return map;}/*** 捕获CustomException* @param e* @return 视图*/
//    @ExceptionHandler({CustomException.class})
//    public ModelAndView customModelAndViewExceptionHandler(CustomException e) {
//        Map<String, Object> map = new HashMap<>();
//        map.put("code", e.getCode());
//        map.put("msg", e.getMsg());
//        ModelAndView modelAndView = new ModelAndView();
//        modelAndView.setViewName("error");
//        modelAndView.addObject(map);
//        return modelAndView;
//    }
}

需要注意的是使用@ExceptionHandler注解传入的参数可以一个数组,且使用该注解时,传入的参数不能相同,也就是不能使用两个@ExceptionHandler去处理同一个异常。如果传入参数相同,则初始化ExceptionHandler时会失败。
对于@ControllerAdvice注解,我们来看看源码的定义:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<?>[] assignableTypes() default {};Class<? extends Annotation>[] annotations() default {};
}

我们可以传递basePackage,声明的类(是一个数组)指定的Annotation参数,具体参考:spring framework doc

2.异常的处理

编写自定义异常类

package com.developlee.errorhandle.exception;/*** @author Lensen* @desc 自定义异常类* @since 2018/10/5 11:04*/
public class CustomException extends RuntimeException {private long code;private String msg;public CustomException(Long code, String msg){this.code = code;this.msg = msg;}public long getCode() {return code;}public void setCode(long code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

Spring 对于 RuntimeException类的异常才会进行事务回滚,所以我们一般自定义异常都继承该异常类。

编写全局异常处理类

/*** @author Lensen* @desc* @since 2018/10/5 11:01*/
@ControllerAdvice("com.developlee.errorhandle")
public class MyExceptionHandler {/*** 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器* @param binder*/@InitBinderpublic void initWebBinder(WebDataBinder binder){}/*** 把值绑定到Model中,使全局@RequestMapping可以获取到该值* @param model*/@ModelAttributepublic void addAttribute(Model model) {model.addAttribute("attribute",  "The Attribute");}/*** 捕获CustomException* @param e* @return json格式类型*/@ResponseBody@ExceptionHandler({CustomException.class}) //指定拦截异常的类型@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定义浏览器返回状态码public Map<String, Object> customExceptionHandler(CustomException e) {Map<String, Object> map = new HashMap<>();map.put("code", e.getCode());map.put("msg", e.getMsg());return map;}/*** 捕获CustomException* @param e* @return 视图*/
//    @ExceptionHandler({CustomException.class})
//    public ModelAndView customModelAndViewExceptionHandler(CustomException e) {
//        Map<String, Object> map = new HashMap<>();
//        map.put("code", e.getCode());
//        map.put("msg", e.getMsg());
//        ModelAndView modelAndView = new ModelAndView();
//        modelAndView.setViewName("error");
//        modelAndView.addObject(map);
//        return modelAndView;
//    }
}

测试

在controller中抛出自定义异常

/*** @author Lensen* @desc* @since 2018/10/5 11:00*/
@Controller
public class DemoController {/*** 关于@ModelAttribute,* 可以使用ModelMap以及@ModelAttribute()来获取参数值。*/    @GetMapping("/one")public String testError(ModelMap modelMap ) {throw new CustomException(500L, "系统发生500异常!" + modelMap.get("attribute"));}@GetMapping("/two")public String testTwo(@ModelAttribute("attribute") String attribute) {throw new CustomException(500L, "系统发生500异常!" + attribute);}
}

启动应用,范围localhost:8080/one.返回报文为:

{"msg":"系统发生500异常!The Attribute","code":500}

可见我们的@InitBinder和@ModelAttribute注解生效。且自定义异常被成功拦截。如果全部异常处理都返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就可以不需要添加 @ResponseBody。@RestControllerAdvice在注解上已经添加了@ResponseBody。

最后,以上示例代码可在我的github.com中找到。
我的个人公众号:developlee的潇洒人生。
关注了也不一定更新,更新就不得了了。

精通Spring Boot —— 第十五篇:使用@ControllerAdvice处理异常相关推荐

  1. spring boot(一):入门篇

    构建微服务:Spring boot 入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

  2. 坚持的力量 第十五篇

    第十五篇        漩涡鸣人 从他身上,我看到了进步和向上的力量,经别人推荐,我发现我渐渐的喜欢上了<火影忍者>. 首先,<火影>中的歌曲很有震撼力和穿透力,产生心灵的共鸣 ...

  3. spring boot实战(第六篇)加载application资源文件源码分析

    前言 在上一篇中了解了spring配置资源的加载过程,本篇在此基础上学习spring boot如何默认加载application.xml等文件信息的. ConfigFileApplicationLis ...

  4. 秒杀多线程第十五篇 关键段,事件,互斥量,信号量的“遗弃”问题

    秒杀多线程第十五篇 关键段,事件,互斥量,信号量的"遗弃"问题 在<秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量>中对经典多线程同步互斥问题进行了回 ...

  5. CCIE理论-第十五篇-IPV6-重分布+ACL+前缀列表

    CCIE理论-第十五篇-IPV6-重分布+ACL+前缀列表 重分布前面讲过,这里再讲一次+实操+效果看看 在ipv6中重分布直连路由是需要加上include-connected的 环境 就这么简单哈, ...

  6. CCIE-LAB-第十五篇-IPV6-BGP+VPN6+RT

    CCIE-LAB-第十五篇-IPV6-BGP+VPN6+RT 实际中,思科只会给你5个小时去做下面的全部配置 这个是CCIE-LAB的拓扑图 问题 翻译: 根据这些要求,将IPV6连接从总部通过SP扩 ...

  7. CCNP-第十五篇-VXLAN(一)

    CCNP-第十五篇-VXLAN(一) 到了这个阶段呢,怎么说呢,简单的NP级别的交换我都跳过去了,但是后期会补, 所以这个衔接可能新手或者不会的看的有的迷茫 但是出自个人原因只好这么干了,VXLAN3 ...

  8. CCNA-第十五篇-DHCP配置+SDN介绍(最后一章)

    CCNA-第十五篇-DHCP配置+SDN介绍 各位好,如果有一直看下来的谢谢支持 这里是CCNA的最后一篇了,如果真的能吸收很多内容,那么普通的东西基本上都没什么大问题了.除非就是工作经验 下一篇就到 ...

  9. Spring Boot:(五)静态资源和拦截器处理

    Spring Boot:(五)静态资源和拦截器处理 前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类WebMvcConfigurerAdapter. 正文 前面章节我们也有 ...

最新文章

  1. python资料书-史上最全Python从入门到资深书籍资料分享!
  2. 036_jQuery Ajax全局回调函数
  3. bootstrap后台模板_免费bootstrap后台管理系统模板源码 网站后台模板_后台管理界面...
  4. [BZOJ4817]树点涂色
  5. 解决django前端使用iframe标签报错127.0.0.1 refused to connect.
  6. hdu 1588 Gauss Fibonacci
  7. RPM + yum 完美完装tomcat
  8. 必备知识:工业相机相关知识(初学者必备)
  9. 使用Sugar制作数据可视化大屏的操作过程
  10. 重装系统后电脑耳机插前面没有声音输出怎么办?
  11. 20亿美金独角兽Notion,和它在中国的“抄袭”者们
  12. Code review是个数学问题:从二向箔说起
  13. zip4j对处理压缩包及压缩包加密处理
  14. python翻译器怎么用_给宝宝用Python写个支持翻译PDF文档的小软件
  15. 秒变黑科技的高效电脑软件,请低调收藏!
  16. JavaWeb项目打包成桌面程序,内嵌浏览器、tomcat、jre、mysql,实现一键安装
  17. Matlab2017b C++编译器配置
  18. 关于提取图片中文字区域的算法和实现方法
  19. Centos 7 安装python 3.8
  20. 合宙Air101 的LCD怎么用Arudino IDE驱动

热门文章

  1. 安装VMWare tools,以及解决安装后/mnt中有hgfs但没共享文件的方法
  2. (转)二叉树系列面试问题
  3. 【VS开发】【智能语音处理】Windows下麦克风语音采集
  4. Oracle自增列创建方法
  5. 推荐阅读的多核编程技术书籍
  6. 如何学习linux编程
  7. objdump查看目标文件构成
  8. Google Test(GTest)使用方法和源码解析——概况
  9. 【Python】深度学习中将数据按比例随机分成随机 训练集 和 测试集的python脚本
  10. android 自定义radiobutton 样式,RadioButton自定义点击时的背景颜色