在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. Tmux 中开启鼠标选择与复制

    在 tmux.conf 中加入下列设置(tmux 2.1 之前的版本): set -g mode-mouse on set -g mouse-resize-pane on set -g mouse-s ...

  2. jsp获取url路径的方法

    如果你请求的URL是  http://localhost:8080/demo/Index.jsp request.getScheme() //输出:http request.getServerName ...

  3. vue中Template 制作模版

    一.直接写在选项里的模板 直接在构造器里的template选项后边编写.这种写法比较直观,但是如果模板html代码太多,不建议这么写. javascript代码: var app=new Vue({ ...

  4. php 安装zip模块

    为php安装zip扩展 wget http://pecl.php.net/get/zip-1.13.5.tgz tar -zvxf zip-1.13.5.tgz cd zip-1.13.5 /home ...

  5. Python--同步锁(互斥锁)、死锁(状态)、递归锁、信号量、Event对象

    同步锁/互斥锁 (Lock) import time import threading def sub(): global num #在每个线程中都获取这个全局变量 #num-=1 temp=num ...

  6. Python基础教程(012)--排查手误错误

    前言 排查由于手误书写错误的方法 内容 手动输入错误的时候,颜色是红色 函数名称写错 1,颜色不一样 2,nameError错误 掌握知识点 学会在写代码的时候排查错误

  7. MySql 5.7.26(MySQL8)安装教程

    近期更换服务器,在此再记录一遍mysql 安装教程 1.下载 https://cdn.mysql.com//Downloads/MySQLInstaller/mysql-installer-commu ...

  8. select into outfile的sql语句

             SELECT INTO…OUTFILE语句把表数据导出到一个文本文件中,并用LOAD DATA …INFILE语句恢复数据.但是这种方法只能导出或导入数据的内容,不包括表的结构,如果 ...

  9. IDEA @Override is not allowed when implementing interface method(转载)

    近期研究idea,在编码过程发现报错:@Override is not allowed when implementing interface method .找到一个老外的回答,感觉挺有用的,记录下 ...

  10. vim 更改注释颜色

    在 ~/.vimrc 添加命令: highlight Comment ctermfg=green