一、简介
@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); } }