在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
*/
@InitBinder
public void initWebBinder(WebDataBinder binder){
//对日期的统一处理
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
//添加对数据的校验
//binder.setValidator();
} /**
* 把值绑定到Model中,使全局@RequestMapping可以获取到该值
* @param model
*/
@ModelAttribute
public 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
*/
@InitBinder
public void initWebBinder(WebDataBinder binder){ } /**
* 把值绑定到Model中,使全局@RequestMapping可以获取到该值
* @param model
*/
@ModelAttribute
public 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。

精通Spring Boot---使用@ControllerAdvice处理异常的更多相关文章

  1. Spring Boot 系列 @ControllerAdvice 拦截异常并统一处理

    ControllerAdvice用法解析 简介 通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置. 注解了@Controller的类的方法可以使用@Exception ...

  2. spring boot / cloud (十二) 异常统一处理进阶

    spring boot / cloud (十二) 异常统一处理进阶 前言 在spring boot / cloud (二) 规范响应格式以及统一异常处理这篇博客中已经提到了使用@ExceptionHa ...

  3. 精通Spring Boot

    原 精通Spring Boot—— 第二十一篇:Spring Social OAuth 登录简介 1.什么是OAuth OAuth官网介绍是这样的: An open protocol to allow ...

  4. Springboot 系列(七)Spring Boot web 开发之异常错误处理机制剖析

    前言 相信大家在刚开始体验 Springboot 的时候一定会经常碰到这个页面,也就是访问一个不存在的页面的默认返回页面. 如果是其他客户端请求,如接口测试工具,会默认返回JSON数据. { &quo ...

  5. spring boot如何处理异步请求异常

    springboot自定义错误页面 原创 2017年05月19日 13:26:46 标签: spring-boot   方法一:Spring Boot 将所有的错误默认映射到/error, 实现Err ...

  6. spring boot中@ControllerAdvice的用法

    @ControllerAdvice ,这是一个增强的 Controller.使用这个 Controller ,可以实现三个方面的功能: 全局异常处理 全局数据绑定 全局数据预处理 灵活使用这三个功能, ...

  7. 二、spring boot 1.5.4 异常控制

    spring boot 已经做了统一的异常处理,下面看看如何自定义处理异常 1.错误码页面映射 1.1静态页面 必须配置在 resources/static/error文件夹下,以错误码命名 下面是4 ...

  8. Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class

    [背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...

  9. Spring boot 文件路径读取异常

    在开发代码中,有一段需要获取resources目录下的一个配置文件(这里写作test.xml). 这段代码在ide中没有任何问题,但是一打成jar包发布到线上,这段代码就会报找不到对应文件的错误. 按 ...

随机推荐

  1. 牛客网Java刷题知识点之全局变量(又称成员变量,分为类变量和实例变量)、局部变量、静态变量(又称为类变量)

    不多说,直接上干货! 定义类其实就是在定义类中的成员.成员:成员变量<-->属性,成员函数<-->行为. 局部变量在方法内部声明,并且只能在方法内部使用,在外层的方法被调用时被 ...

  2. 几种复杂度的斐波那契数列的Java实现

    一:斐波那契数列问题的起源 13世纪初期,意大利数论家Leonardo Fibonacci在他的著作Liber Abaci中提出了兔子的繁殖问题: 如果一开始有一对刚出生的兔子,兔子的长大需要一个月, ...

  3. .net 向新页面跳转的语句

    1. href='##' onclick=\"window.open('../DataSplit/DrugInfo_ManualVersionViewNew.aspx?id=" + ...

  4. 关于IE的一些hack

    TIPS:对于完全放弃IE的幸福开发者,以下内容全是废话,建议跳转到 博客园 着页,寻找更优质的文章. 对于前端开发来说IE一直是心里的痛,不管你觉得做的多好的网页,放到它上面总会有一些意想不到的问题 ...

  5. contenttype组件、Django缓存机制以及跨域请求

    1 昨日回顾 版本控制 *** (1)url=127.0.0.1/course/?version=v100000 1 versioning_class=QueryParameterVersioning ...

  6. CF1136D Nastya Is Buying Lunch

    思路: 1. 最终答案不超过能与Nastya“直接交换”的人数. 2. 对于排在j前面的i,如果i和i-j之间(包括j)的每个人都能“直接交换”,j才能前进一步. 实现: #include <b ...

  7. Android应用瘦身

    转:https://zhuanlan.zhihu.com/p/25465537 瘦身的目的 从目的导向来看,我们是不会无缘无故去做一件事情的,那我们对应用瘦身的目的是为了什么?答案是:提高下载转化率. ...

  8. 创建1M-1T的虚拟磁盘(内存盘)——使用破解版 Primo Ramdisk Server Edition v5.6.0

    破解版 Primo Ramdisk Server Edition v5.6.0下载: https://pan.lanzou.com/i0sgcne 步骤: 下载并解压后安装“Primo.Ramdisk ...

  9. java Vamei快速教程04 封装和接口

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 总结之前的内容,对象(object)指代某一事物,类(class)指代象的类型.对 ...

  10. linux 命令——40 wc (转)

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...