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

注解的介绍

先定义一个ControllerAdvice。代码如下:

需要注意的是使用@ExceptionHandler注解传入的参数可以一个数组,且使用该注解时,传入的参数不能相同,也就是不能使用两个@ExceptionHandler去处理同一个异常。如果传入参数相同,则初始化ExceptionHandler时会失败。

/**
* @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;
// }
}

对于@ControllerAdvice注解,我们来看看源码的定义:

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

@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 {};
}

异常的处理

编写自定义异常类

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

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;
}
}

编写全局异常处理类

/**
* @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。 

参考

https://yq.aliyun.com/articles/647428

SpringBoot - @ControllerAdvice 处理异常的更多相关文章

  1. Springboot项目中异常拦截设计与处理

    背景: 项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连 ...

  2. @ControllerAdvice 拦截异常并统一处理(转载)

    在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有@Requ ...

  3. (入门SpringBoot)SpringBoot配置全局异常(五)

    Spring的全局异常,用于捕获程序员没有捕获的异常.具体请看下面代码: 1.ControllerAdvice拦截异常,统一处理.通过Spring的AOP来管理. @ControllerAdvicep ...

  4. @ControllerAdvice全局异常拦截

    @ControllerAdvice 拦截异常并统一处理 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder ...

  5. (转)springboot全局处理异常(@ControllerAdvice + @ExceptionHandler)

    1.@ControllerAdvice 1.场景一 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0, "data": ...

  6. 十四、springboot全局处理异常(@ControllerAdvice + @ExceptionHandler)

    1.@ControllerAdvice 1.场景一 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0, "data": ...

  7. [spring-boot] ControllerAdvice异常类

    package com.example.demo.exception; import org.springframework.web.bind.annotation.ControllerAdvice; ...

  8. SpringBoot 之 @ControllerAdvice 拦截异常并统一处理

    在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有@Requ ...

  9. (办公)springboot配置全局异常

    项目用到了springboot,本来很高兴,但是项目里什么东西都没有,验证,全局异常这些都需要自己区配置.最近springboot用的还是蛮多的,我还是做事情,把经验发表一下.全局统一的异常,首先异常 ...

随机推荐

  1. 属性class与:class

    1.官方的案例 我们可以传给 v-bind:class 一个对象,以动态地切换 class <div v-bind:class="{ active: isActive }"& ...

  2. Java 的内置对象

    1.Request对象 该对象封装了用户提交的信息,通过调用该对象相应的方法可以获取封装的信息,即使用该对象可以获取用户提交的信息.    当Request对象获取客户提交的汉字字符时,会出现乱码问题 ...

  3. 页面重置样式reset.css

    我把经常用到的一些页面重置样式归类到了一个.css文件中,这样可以减少代码冗余.当然还有其他的很多用处,比如h1~h5的样式全部统一的话,下面写东西很清晰很多. @charset 'utf-8'; h ...

  4. IDEA2019.1.3最新破解方式

    版本2019.1.3 1.下载破解JAR,放入IDEA的bin文件夹中     链接:https://pan.baidu.com/s/1N1BHeJ0-mmFIWbrh5h4k-g     提取码:g ...

  5. jmeter之--断言json响应&json path espressions的语法

    一.提取所需要断言的内容: 响应数据如下:加入需要提取id为90的值 { , "name" : "python", "url" : &quo ...

  6. MySQL strcmp 函数

    STRCMP(str1, str2) 比较两个字符串,如果这两个字符串相等返回0,如果第一个参数是根据当前的排序小于第二个参数顺序返回-1,否则返回1. mysql> SELECT STRCMP ...

  7. 建站手册-浏览器信息:Internet Explorer 浏览器

    ylbtech-建站手册-浏览器信息:Internet Explorer 浏览器 1.返回顶部 1. http://www.w3school.com.cn/browsers/browsers_inte ...

  8. 数据库SQL调优的几种方式(转)

    原文地址:https://blog.csdn.net/u010520146/article/details/81161762 在项目中,SQL的调优对项目的性能来讲至关重要,所有掌握常见的SQL调优方 ...

  9. 几个比较好的IT站和开发库官网

    1.IT技术.项目类网站 (1)首推CodeProject,一个国外的IT网站,官网地址为:http://www.codeproject.com,这个网站为程序开发者提供了很好的代码示例以及讲解,不过 ...

  10. 正在从 Windows 应用商店下载... 无法从 Windows 应用商店下载。请检查网络连接。

    手贱关掉了一下服务,再打开就是嘛