zoukankan      html  css  js  c++  java
  • Spring3.2新注解@ControllerAdvice

    @ControllerAdvice,是spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强。让我们先看看@ControllerAdvice的实现:

    @Target(ElementType.TYPE)  
    @Retention(RetentionPolicy.RUNTIME)  
    @Documented  
    @Component  
    public @interface ControllerAdvice {  
      
    }

    使用 @ControllerAdvice,不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。

     没什么特别之处,该注解使用@Component注解,这样的话当我们使用<context:component-scan>扫描时也能扫描到。

    其javadoc定义是:

    写道
    /**
    * Indicates the annotated class assists a "Controller".
    *
    * <p>Serves as a specialization of {@link Component @Component}, allowing for
    * implementation classes to be autodetected through classpath scanning.
    *
    * <p>It is typically used to define {@link ExceptionHandler @ExceptionHandler},
    * {@link InitBinder @InitBinder}, and {@link ModelAttribute @ModelAttribute}
    * methods that apply to all {@link RequestMapping @RequestMapping} methods.
    *
    * @author Rossen Stoyanchev
    * @since 3.2
    */
    • @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。

    • Spring4之前,@ControllerAdvice在同一调度的Servlet中协助所有控制器。Spring4已经改变:@ControllerAdvice支持配置控制器的子集,而默认的行为仍然可以利用。

    • 在Spring4中, @ControllerAdvice通过annotations(), basePackageClasses(), basePackages() 方法定制用于选择控制器子集。

    即把@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。非常简单,不过只有当使用@ExceptionHandler最有用,另外两个用处不大。

     先看一个示例:

    定义一个业务异常,这个异常交给@ControllerAdvice中的@ExceptionHandler处理。

    package com.dxz.web.controller.excepion;
    
    /**
     * 业务异常
     */
    public class BusinessException extends Exception {
    
        private static final long serialVersionUID = 1L;
    
        // 业务类型
        private String bizType;
        // 业务代码
        private int bizCode;
        // 错误信息
        private String message;
    
        public BusinessException(String bizType, int bizCode, String message) {
            super(message);
            this.bizType = bizType;
            this.bizCode = bizCode;
            this.message = message;
        }
    
        public BusinessException(String message) {
            super(message);
            this.bizType = "";
            this.bizCode = -1;
            this.message = message;
        }
    
        public BusinessException(String bizType, String message) {
            super(message);
            this.bizType = bizType;
            this.bizCode = -1;
            this.message = message;
        }
    
        public BusinessException(int bizCode, String message) {
            super(message);
            this.bizType = "";
            this.bizCode = bizCode;
            this.message = message;
        }
    
        public String getBizType() {
            return bizType;
        }
    
        public void setBizType(String bizType) {
            this.bizType = bizType;
        }
    
        public int getBizCode() {
            return bizCode;
        }
    
        public void setBizCode(int bizCode) {
            this.bizCode = bizCode;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
    }

    用@ControllerAdvice为@RequestMapping注解的方法的提供@ExceptionHandler、@InitBinder、@ModelAttribute的功能。

    package com.dxz.web.controller.excepion;
    
    import java.beans.PropertyEditor;
    import java.sql.SQLException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.beans.propertyeditors.CustomDateEditor;
    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 com.dxz.web.model.User;
    
    /**
     * @ModelAttribute用于属性注入
     * @InitBinder用于参数的统一处理
     * @ExceptionHandler用于捕获异常统一处理
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        private final static String EXPTION_MSG_KEY = "message";
    
        @ModelAttribute  
        public User newUser() {  
            System.out.println("============应用到所有@RequestMapping注解方法,在其执行之前把返回值放入Model");  
            return new User();  
        } 
        
        @InitBinder
        public void dataBinder(WebDataBinder binder) {
            DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            PropertyEditor propertyEditor = new CustomDateEditor(dateFormat, true); // 第二个参数表示是否允许为空
            binder.registerCustomEditor(Date.class, propertyEditor);
        }
    
        @ExceptionHandler(BusinessException.class)
        @ResponseBody
        public void handleBizExp(HttpServletRequest request, Exception ex) {
            System.out.println("Business exception handler  " + ex.getMessage());
            request.getSession(true).setAttribute(EXPTION_MSG_KEY, ex.getMessage());
        }
    
        @ExceptionHandler(SQLException.class)
        public ModelAndView handSql(Exception ex) {
            System.out.println("SQL Exception " + ex.getMessage());
            ModelAndView mv = new ModelAndView();
            mv.addObject("message", ex.getMessage());
            mv.setViewName("sql_error");
            return mv;
        }
    
    }

    测试的controller:

    package com.dxz.web.controller;
    
    import java.io.IOException;
    import java.io.Writer;
    import java.sql.SQLException;
    import java.util.Date;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import com.dxz.web.controller.excepion.BusinessException;
    
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("login")
        public String login() {
            return "login";
        }
    
        @RequestMapping("login2")
        public String login2() throws Exception {
            throw new SQLException("数据库出错");
        }
    
        @RequestMapping("login3")
        public String login3() throws Exception {
            throw new BusinessException("业务执行异常");
        }
    
        @RequestMapping("dataBinder/{date}")
        public void testDate(@PathVariable Date date, Writer writer) throws IOException {
            System.out.println("date:" + date);
            writer.write(String.valueOf(date.getTime()));
        }
    
        // 此方法抛出的异常不是由GlobalExceptionHandler处理
        // 而是在catch块处理
        @RequestMapping("login4")
        public String login4() {
            try {
                throw new BusinessException("业务执行异常");
            } catch (BusinessException e) {
                System.out.println("自己消化异常");
            }
            return "login";
        }
    
    }

    @ExceptionHandler演示,分别访问:

    http://localhost:8080/SpringWebTraining/user/login4.do

    http://localhost:8080/SpringWebTraining/user/login3.do

    http://localhost:8080/SpringWebTraining/user/login2.do

    测试结果:

     @InitBinder演示,分别访问:

    http://localhost:8080/SpringWebTraining/user/dataBinder/20171023

    1、@ModelAttribute注解的方法作用请参考SpringMVC Controller 介绍

    2、@InitBinder注解的方法作用请参考SpringMVC Controller 介绍

    3、@ExceptionHandler,异常处理器,此注解的作用是当出现其定义的异常时进行处理的方法,其可以使用springmvc提供的数据绑定,比如注入HttpServletRequest等,还可以接受一个当前抛出的Throwable对象。可以参考javadoc或snowolf的Spring 注解学习手札(八)补遗——@ExceptionHandler

    该注解非常简单,大多数时候其实只@ExceptionHandler比较有用,其他两个用到的场景非常少,这样可以把异常处理器应用到所有控制器,而不是@Controller注解的单个控制器。

  • 相关阅读:
    spring mvc中的@PathVariable
    JSP禁用缓存的方式 response.setHeader( "Pragma", "no-cache" ); setDateHeader("Expires", 0);
    request.getSession(true)和request.getSession(false)的区别
    Spring Mvc中DispatcherServlet和Servlet的区别小结
    web.xml中load-on-startup的作用
    Spring MVC过滤器-字符集过滤器(CharacterEncodingFilter)
    web.xml配置中的log4jRefreshInterval
    web.xml中webAppRootKey
    关于tolua的使用
    关于#pragma pack
  • 原文地址:https://www.cnblogs.com/duanxz/p/3753687.html
Copyright © 2011-2022 走看看