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