zoukankan      html  css  js  c++  java
  • SpringBoot

    在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

  • 相关阅读:
    选择合适的数据存储(SSCE,Access,XML等)
    [翻译]SQL Server 工作集消息
    [翻译]使用SQL Server 优化提示
    [翻译]玩转 Locked Pages,AWE,Task Manager和Working Set
    关于XML数据库与普通数据库(概述)
    去除某SQL Server数据库中所有约束,索引,触发器,统计的代码
    SQL 存储过程读取视图数据
    C# list<>数据填充到Dataset里
    ASP.NET 截取固定长度字符串显示在页面,多余部分显示为省略号
    Office 安装程序找不到office.zhcn\*.文件
  • 原文地址:https://www.cnblogs.com/frankcui/p/12040551.html
Copyright © 2011-2022 走看看