@ControllerAdvice + @ExceptionHandler 使用

一、简介

@ControllerAdvice,是spring3.2提供的新注解,意思是控制器增强。

下面是它的解释。

大致意思是,

1、表示标有这个注解的类是一个Controller。它有一个默认行为:被注解的类会作用到所有已知的Controller上。

2、它通常会和 @ExceptionHandler @InitBinder @ModelAttribute 等注解一起使用

/**
 * 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.
 *
 * <p>One of {@link #annotations()}, {@link #basePackageClasses()},
 * {@link #basePackages()} or its alias {@link #value()}
 * may be specified to define specific subsets of Controllers
 * to assist. When multiple selectors are applied, OR logic is applied -
 * meaning selected Controllers should match at least one selector.
 *
 * <p>The default behavior (i.e. if used without any selector),
 * the {@code @ControllerAdvice} annotated class will
 * assist all known Controllers.
 *
 * <p>Note that those checks are done at runtime, so adding many attributes and using
 * multiple strategies may have negative impacts (complexity, performance).
 *
 * @author Rossen Stoyanchev
 * @author Brian Clozel
 * @author Sam Brannen
 * @since 3.2
 */

 

在项目中与 @ExceptionHandler 一起使用的情况会比较多。

下面是@ExceptionHandler 的解释。

只截取了一部分,大致意思就是@ExceptionHandler标注的类或者方法是一个异常处理类或者方法。

它非常灵活,可以使用value指定具体的异常类。

/**
 * Annotation for handling exceptions in specific handler classes and/or
 * handler methods. Provides consistent style between Servlet and Portlet
 * environments, with the semantics adapting to the concrete environment.
 *
 * <p>Handler methods which are annotated with this annotation are allowed to
 * have very flexible signatures. They may have parameters of the following
 * types, in arbitrary order:
 * <ul>
 * <li>An exception argument: declared as a general Exception or as a more
 * specific exception. This also serves as a mapping hint if the annotation
 * itself does not narrow the exception types through its {@link #value()}.
 * <li>Request and/or response objects (Servlet API or Portlet API).
 * You may choose any specific request/response type, e.g.
 * {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}
 * or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} /
 * {@link javax.portlet.RenderRequest}. Note that in the Portlet case,
 * an explicitly declared action/render argument is also used for mapping
 * specific request types onto a handler method (in case of no other
 * information given that differentiates between action and render requests).
 * <li>Session object (Servlet API or Portlet API): either
 * {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}.
 * An argument of this type will enforce the presence of a corresponding session.
 * As a consequence, such an argument will never be {@code null}.
 * <i>Note that session access may not be thread-safe, in particular in a
 * Servlet environment: Consider switching the
 * {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#setSynchronizeOnSession
 * "synchronizeOnSession"} flag to "true" if multiple requests are allowed to
 * access a session concurrently.</i>
 * <li>{@link org.springframework.web.context.request.WebRequest} or
 * {@link org.springframework.web.context.request.NativeWebRequest}.
 * Allows for generic request parameter access as well as request/session
 * attribute access, without ties to the native Servlet/Portlet API.
 * <li>{@link java.util.Locale} for the current request locale
 * (determined by the most specific locale resolver available,
 * i.e. the configured {@link org.springframework.web.servlet.LocaleResolver}
 * in a Servlet environment and the portal locale in a Portlet environment).
 * <li>{@link java.io.InputStream} / {@link java.io.Reader} for access
 * to the request's content. This will be the raw InputStream/Reader as
 * exposed by the Servlet/Portlet API.
 * <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
 * the response's content. This will be the raw OutputStream/Writer as
 * exposed by the Servlet/Portlet API.
 * <li>{@link org.springframework.ui.Model} as an alternative to returning
 * a model map from the handler method. Note that the provided model is not
 * pre-populated with regular model attributes and therefore always empty,
 * as a convenience for preparing the model for an exception-specific view.
 * </ul>
* ...... *

 

二、实践

下面这段代码是我们项目中使用到的。用于处理业务中抛出自定义的异常ServiceException与通用异常的。

/**
 * 全局的业务异常处理类.
 *
 * @author lkb
 */
@ControllerAdvice
public class GlobalExceptionHandler
{
    
    /** The error code. */
    @Value("${errorCode:ERROR_10001}")
    private String errorCode;
    
    /**
     * 发生自定义业务异常时处理方法.
     *
     * @param req the req
     * @param e the e
     * @return the string
     * @throws Exception 从每个模块control获取,另外JSON格式从定义文档获取
     */
    @ExceptionHandler(value = ServiceException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    @ResponseBody
    public String defaultErrorHandler(HttpServletRequest req, ServiceException e)
        throws Exception
    {
        LogUtil.getInstance().error("+++++++++++++ServiceException Error Info+++++++++++++", e);
        //实例化异常对象
        ErrorInfo errorInfo = new ErrorInfo();
        if (e != null && StringUtils.isNotEmpty(e.getMessage()))
        {
            errorInfo.setErrorCode(e.getMessage());
            errorInfo.setErrorDesc("");
            errorInfo.setErrorInfoUrl("");
        }
        Map<String, Object> resultMap = CommonUtil.getInstance().getErrorData(errorInfo);
        return JSON.toJSONString(resultMap);
    }
    
    /**
     * 发生非业务异常时处理方法.
     *
     * @param req the req
     * @param e the e
     * @return the string
     * @throws Exception 未知异常,在配置文件定义;默认在上面定义接收
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    //@ResponseStatus()
    @ResponseBody
    public String defaultErrorHandler(HttpServletRequest req, Exception e)
        throws Exception
    {
        LogUtil.getInstance().error("+++++++++++++Exception Error Info+++++++++++++", e);
        //实例化异常对象
        ErrorInfo errorInfo = new ErrorInfo();
        errorInfo.setErrorCode(errorCode);
        errorInfo.setErrorDesc("");
        errorInfo.setErrorInfoUrl("");
        Map<String, Object> resultMap = CommonUtil.getInstance().getErrorData(errorInfo);
        return JSON.toJSONString(resultMap);
    }
}

 

posted on 2017-12-25 16:33  猫咪大王  阅读(588)  评论(0编辑  收藏  举报