在Spring 3.2中,新增了@ControllerAdvice、@RestControllerAdvice 注解,能够用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到全部@RequestMapping、@PostMapping, @GetMapping注解中。 接下来我将经过代码展现如何使用这些注解,以及处理异常。html
先定义一个ControllerAdvice。代码以下java
/** * @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注解,咱们来看看源码的定义:git
@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 docgithub
###编写自定义异常类web
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类的异常才会进行事务回滚,因此咱们通常自定义异常都继承该异常类。spring
/** * @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中抛出自定义异常json
/** * @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.返回报文为:api
{"msg":"系统发生500异常!The Attribute","code":500}
可见咱们的@InitBinder和@ModelAttribute注解生效。且自定义异常被成功拦截。若是所有异常处理都返回json,那么能够使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就能够不须要添加 @ResponseBody。@RestControllerAdvice在注解上已经添加了@ResponseBody。数组
最后,以上示例代码可在个人github.com中找到。 个人我的公众号:developlee的潇洒人生。 关注了也不必定更新,更新就不得了了。 浏览器