Common global processing can be achieved in the following ways:
- ServletRequestListener: Executed at the beginning and end of a request, Spring's RequestContextListener, etc.
- Filter: Executed at the beginning and end of Servlet, Spring's CharacterEncodingFilter, HiddenHttpMethodFilter, etc.
- HandlerInterceptor: Executed at the beginning and end of the Controller method, Spring's LocaleChangeInterceptor, etc.
- Spring AOP (AspectJ): face-oriented, arbitrary injection processing.
Only the built-in exception handling mechanism of Spring MVC is introduced here:
- @ResponseStatus
- @ExceptionHandler
- @ControllerAdvice
- HandlerExceptionResolver
(1) Exception capture in the Controller
implements exception capture processing by annotating @ExceptionHandler.
@Controller public class FooController { @ExceptionHandler @ResponseStatus(NOT_FOUND) public void notFound(ResourceNotFoundException ex) { // N/A } }
Exception capture can also be achieved by implementing HandlerExceptionResolver.
@Controller public class FooController implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) { // N/A } }
(2) Exceptions marked by the @ResponseStatus annotation
will be automatically handled by ResponseStatusExceptionResolver.
@ResponseStatus(value = NOT_FOUND, reason = "Resource is not found.") public class ResourceNotFoundException extends RuntimeException { // ... }
(3) Global exception capture
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler @RespnseStatus(NOT_FOUND) public void notFound(ResourceNotFoundException ex) { // N/A } } @ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(RuntimeException.class) public ResponseEntity<Error> handle(RuntimeException ex, HttpServletResponse res){ // N/A res.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); } }
When the API and the page coexist, the global exception capture can be forwarded again to return different content.
@ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(Exception.class) public String error(HttpServletRequest req, Exception ex){ // N/A String baseUrl = getBaseUrl (req); return "forward:" + baseUrl + "/error"; } } @Controller public class GeneralErrorHandlerController { @RequestMapping("/admin/error") public String screenError(HttpServletRequest req, Model model) { // N/A return "screen/admin/error"; } @RequestMapping(value = "/api/internal/error") @ResponseBody public ErrorResponse apiError(HttpServletRequest req) { // N/A return ErrorResponse.build(e); } }
***** Cannot automatically set status code, you need to set it yourself
***** Cannot catch all exceptions, such as presentation layer, 404 errors, etc.
@ExceptionHandler, @InitBinder, @ModelAttribute methods in @ControllerAdvice annotations will be applied to all The @RequestMapping annotated method. The above @ExceptionHandler is the most common, and @InitBinder is also used, for example:
1) By default SpringMVC sets the value of empty fields to empty strings instead of nulls. The empty string can be set to null by the following definition, and the string will be automatically trimmed.
You can also pass in the characters to be filtered: StringTrimmerEditor(String charsToDelete, boolean emptyAsNull)
@ControllerAdvice public class NullValidAdvice { @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); } }
2) Set the return parameters of JSONP
@ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { super("callback"); } }
(4) The error-page
part in web.xml is not handled by Spring itself, but is handled by ServletContainer.
Jump all uncaught exceptions to a specified mapping again.
<error-page> <location>/error</location> </error-page>
@Controller class GeneralErrorHandlerController { @RequestMapping("error") public String otherError(HttpServletRequest req, Model model) { // N/A } }
(5) Custom 404 correspondingly
set throwExceptionIfNoHandlerFound to true
<servlet> <servlet-name>rest-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>throwExceptionIfNoHandlerFound</param-name> <param-value>true</param-value> </init-param> </servlet>
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(NoHandlerFoundException.class) public ResponseEntity<Error> handle(NoHandlerFoundException ex){ // N/A } }
(6) Customize the error page
customization to map the exception to the view SimpleMappingExceptionResolver
@Bean public SimpleMappingExceptionResolver exceptionResolver(){ SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver(); Properties exceptions = new Properties(); exceptions.put(ArithmeticException.class, "error"); resolver.setExceptionMappings(exceptions); return resolver; }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Spring MVC Exception Handling</title> </head> <body> <h1>Spring MVC Exception Handling</h1> ${exception.message} </body> </html>
***** The test development environment can print out the exception stack on the page, which is convenient for debugging.
Spring MVC exception handling order:
ExceptionHandlerExceptionResolver: Exception marked by @ExceptionHandler annotation
->
ResponseStatusExceptionResolver: Exception marked by @ResponseStatus annotation
->
DefaultHandlerExceptionResolver: Spring's standard exception handling
->
Custom Resolver
standard exception handling DefaultHandlerExceptionResolver
quote
BindException 400 (Bad Request)
ConversionNotSupportedException 500 (Internal Server Error)
HttpMediaTypeNotAcceptableException 406 (Not Acceptable)
HttpMediaTypeNotSupportedException 415 (Unsupported Media Type)
HttpMessageNotReadableException 400 (Bad Request)
HttpMessageNotWritableException 500 (Internal Server Error)
HttpRequestMethodNotSupportedException 405 (Method Not Allowed)
MethodArgumentNotValidException 400 (Bad Request)
MissingPathVariableException 500 (Internal Server Error)
MissingServletRequestParameterException 400 (Bad Request)
MissingServletRequestPartException 400 (Bad Request)
NoHandlerFoundException 404 (Not Found)
NoSuchRequestHandlingMethodException 404 (Not Found)
TypeMismatchException 400 (Bad Request)
ConversionNotSupportedException 500 (Internal Server Error)
HttpMediaTypeNotAcceptableException 406 (Not Acceptable)
HttpMediaTypeNotSupportedException 415 (Unsupported Media Type)
HttpMessageNotReadableException 400 (Bad Request)
HttpMessageNotWritableException 500 (Internal Server Error)
HttpRequestMethodNotSupportedException 405 (Method Not Allowed)
MethodArgumentNotValidException 400 (Bad Request)
MissingPathVariableException 500 (Internal Server Error)
MissingServletRequestParameterException 400 (Bad Request)
MissingServletRequestPartException 400 (Bad Request)
NoHandlerFoundException 404 (Not Found)
NoSuchRequestHandlingMethodException 404 (Not Found)
TypeMismatchException 400 (Bad Request)
Reference:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers
https://spring.io/blog/2013/11/01/exception -handling-in-spring-mvc
http://memorynotfound.com/spring-mvc-exception-handling/
http://www.journaldev.com/2651/spring-mvc-exception-handling-controlleradvice-exceptionhandler-handlerexceptionresolver
http https://www.roytuts.com/exception-handling-best-practices-in-java/
https://speakerdeck.com/sinsengumi/spring-boot-application-infrastructure
https://github.com/jirutka/spring- rest-exception-handler
http://qiita.com/kazuki43zoo/items/757b557c05f548c6c5db
http://cgs1999.iteye.com/blog/1547197
http://www.cnblogs.com/xinzhao/p/4934247.html