# spring-boot自定义异常拦截器 **Repository Path**: bojunjiang/exceplain-intercept ## Basic Information - **Project Name**: spring-boot自定义异常拦截器 - **Description**: spring-boot自定义拦截器学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-02-28 - **Last Updated**: 2022-02-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## @ControllerAdvice注解增强类 在`spring 3.2`中,新增了`@ControllerAdvice`注解,可以用于定义`@ExceptionHandler`、`@InitBinder`、`@ModelAttribute`,并应用到所有`@RequestMapping`中 ### 一、介绍 创建`MyControllerAdvice`,并添加 `@ControllerAdvice`注解。 ```java package com.lx.controller; import com.lx.custom.AjaxException; import com.lx.custom.WebException; import org.springframework.ui.Model; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; /** * 增强器 * * @author 段誉 * @create 2019-03-14 20:43 */ @Slf4j @ControllerAdvice public class MyControllerAdvice { /** * 应用到所有RequestMaping注解方法,在其执行之前初始化数据绑定器 * @param binder */ @InitBinder public void initBinder(WebDataBinder binder) { } /** * 把值绑定到Model中,使全局@RequestMapping可以获取到该值 * @param model */ @ModelAttribute public void addAttributes(Model model) { model.addAttribute("author", "Jacob"); } /** * 全局异常拦截,value设置拦截exception异常 * @param ex * * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Map errorHandler(Exception ex) { Map map = new HashMap(); map.put("code", 100); map.put("msg", ex.getMessage()); return map; } } ``` 启动应用后,被`@ExceptionHandler`、`@InitBinder`、`@ModelAttribute`注解的方法,都会被作用在被`@RequestMapping`注解的方法上。 * @ModelAttribute:在Model上设置对应的值,对于所有被`@RequestMapping`注解的方法中,都可以通过`ModelMap`获取,如下: ```java @GetMapping("/home1") @ResponseBody public String home1(ModelMap modelMap) { return modelMap.get("author").toString(); } //或者 通过@ModelAttribute获取 @GetMapping("/home2") @ResponseBody public String home2(@ModelAttribute("author") String author) { return author; } } ``` * @ExceptionHandler 拦截了异常,我们通常可以通过该注解实现自定义异常处理。其中,@ExceptionHandler配置的value指定需要拦截的异常类型,上面拦截了Exception.class这种异常 ### 二、自定义异常处理(全局异常处理) > spring boot 默认情况下会映射到/error 进行异常处理,但是提示并不十分友好,下面自定义异常处理,提供友好提示。 #### 1、编写自定义异常处理类: ```java package com.lx.custom; import lombok.Data; /** * 自定义异常类 * * @author 段誉 * @create 2019-03-19 16:21 */ @Data public class AjaxException extends RuntimeException { private Integer code; private String msg; public AjaxException(Integer code, String msg) { this.code = code; this.msg = msg; } } ``` 注:spring对于RuntimeException异常才会进行事务回滚。 #### 2、编写全局异常处理类 创建`MyControllerAdvice.java`,如下 ```java package com.lx.controller; import com.lx.custom.AjaxException; import com.lx.custom.WebException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.Map; import lombok.extern.slf4j.Slf4j; /** * 增强器 * * @author 段誉 * @create 2019-03-14 20:43 */ @Slf4j @ControllerAdvice public class MyControllerAdvice { /** * 全局异常拦截,value设置拦截exception异常 * @param ex * * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Map errorHandler(Exception ex) { Map map = new HashMap(); map.put("code", 100); map.put("msg", ex.getMessage()); return map; } /** * 自定义异常拦截,拦截AjaxException异常返回json数据 * @param ex * @return */ @ExceptionHandler(value = AjaxException.class) @ResponseBody public Map ajaxErrorHandler(AjaxException ex) { Map map = new HashMap(); map.put("code", ex.getCode()); map.put("msg", ex.getMsg()); return map; } } ``` #### 3、在controller中抛出异常进行测试 ```java @GetMapping("/home1") public String home1() { throw new AjaxException(110, "ajax异常"); } ``` 启动应用,访问:`http://localhost:8080/exception/home1`,正常显示以下json内容,证明自定义异常已经成功被拦截。 ```json { "msg": "ajax异常", "code": 110 } ``` * 如果不需要返回json数据,而要渲染某个页面模板返回给浏览器,那么MyControllerAdvice中可以这么实现: ```java @ExceptionHandler(value = WebException.class) public ModelAndView webErrorHandler(WebException ex) { ModelAndView modelAndView = new ModelAndView(); //设置跳转的页面 modelAndView.setViewName("error"); //设置页面参数 modelAndView.addObject("code", ex.getCode()); modelAndView.addObject("msg", ex.getMsg()); return modelAndView; } ``` 在 templates 目录下,添加 error.ftl(这里使用freemarker) 进行渲染: ```html