我正在使用SpringMVC开发一个REST服务,我在类和方法级别有@RequestMapping.
此应用程序当前配置为返回在web.xml中配置的错误页面jsp.
404 /resourceNotFound
但是我想返回自定义JSON而不是此错误页面.
我可以通过在控制器中编写这个来处理异常并返回json以获取其他异常,但是当url根本不存在时,不知道如何以及在何处编写逻辑以返回JSON.
@ExceptionHandler(TypeMismatchException.class) @ResponseStatus(value=HttpStatus.NOT_FOUND) @ResponseBody public ResponseEntityhandleTypeMismatchException(HttpServletRequest req, TypeMismatchException ex) { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json; charset=utf-8"); Locale locale = LocaleContextHolder.getLocale(); String errorMessage = messageSource.getMessage("error.patient.bad.request", null, locale); errorMessage += ex.getValue(); String errorURL = req.getRequestURL().toString(); ErrorInfo errorInfo = new ErrorInfo(errorURL, errorMessage); return new ResponseEntity (errorInfo.toJson(), headers, HttpStatus.BAD_REQUEST); }
我试过@ControllerAdvice,它适用于其他异常场景,但是当映射不可用时,
@ControllerAdvice public class RestExceptionProcessor { @Autowired private MessageSource messageSource; @ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ResponseStatus(value=HttpStatus.NOT_FOUND) @ResponseBody public ResponseEntityrequestMethodNotSupported(HttpServletRequest req, HttpRequestMethodNotSupportedException ex) { Locale locale = LocaleContextHolder.getLocale(); String errorMessage = messageSource.getMessage("error.patient.bad.id", null, locale); String errorURL = req.getRequestURL().toString(); ErrorInfo errorInfo = new ErrorInfo(errorURL, errorMessage); return new ResponseEntity (errorInfo.toJson(), HttpStatus.BAD_REQUEST); } @ExceptionHandler(NoSuchRequestHandlingMethodException.class) @ResponseStatus(value=HttpStatus.NOT_FOUND) @ResponseBody public ResponseEntity requestHandlingMethodNotSupported(HttpServletRequest req, NoSuchRequestHandlingMethodException ex) { Locale locale = LocaleContextHolder.getLocale(); String errorMessage = messageSource.getMessage("error.patient.bad.id", null, locale); String errorURL = req.getRequestURL().toString(); ErrorInfo errorInfo = new ErrorInfo(errorURL, errorMessage); return new ResponseEntity (errorInfo.toJson(), HttpStatus.BAD_REQUEST); } }
Himalay Maju.. 24
在SpringFramework中挖掘DispatcherServlet和HttpServletBean.init()后,我发现它在Spring 4中是可能的.
org.springframework.web.servlet.DispatcherServlet
/** Throw a NoHandlerFoundException if no Handler was found to process this request? **/ private boolean throwExceptionIfNoHandlerFound = false; protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception { if (pageNotFoundLogger.isWarnEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + requestUri + "] in DispatcherServlet with name '" + getServletName() + "'"); } if(throwExceptionIfNoHandlerFound) { ServletServerHttpRequest req = new ServletServerHttpRequest(request); throw new NoHandlerFoundException(req.getMethod().name(), req.getServletRequest().getRequestURI(),req.getHeaders()); } else { response.sendError(HttpServletResponse.SC_NOT_FOUND); } }
throwExceptionIfNoHandlerFound默认为false,我们应该在web.xml中启用它
appServlet org.springframework.web.servlet.DispatcherServlet throwExceptionIfNoHandlerFound true 1 true
然后,您可以使用此方法在使用@ControllerAdvice注释的类中捕获它.
@ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(value=HttpStatus.NOT_FOUND) @ResponseBody public ResponseEntityrequestHandlingNoHandlerFound(HttpServletRequest req, NoHandlerFoundException ex) { Locale locale = LocaleContextHolder.getLocale(); String errorMessage = messageSource.getMessage("error.bad.url", null, locale); String errorURL = req.getRequestURL().toString(); ErrorInfo errorInfo = new ErrorInfo(errorURL, errorMessage); return new ResponseEntity (errorInfo.toJson(), HttpStatus.BAD_REQUEST); }
这允许我返回没有映射的坏URL的JSON响应,而不是重定向到JSP页面:)
{"message":"URL does not exist","url":"http://localhost:8080/service/patientssd"}
优秀的答案,值得注意的是你不能使用[DefaultServletHandlerConfigurer](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/DefaultServletHandlerConfigurer .html)有了这个,因为它会在它到达DispatcherServlet之前使用404 (3认同)
对于基于Java的配置,您需要重写AbstractAnnotationConfigDispatcherServletInitializer的customizeRegistration。请参阅[此答案](http://stackoverflow.com/a/22751886/878514)。 (2认同)
mancini0.. 9
如果您使用的是Spring Boot,请设置以下两个属性的BOTH:
spring.resources.add-mappings=false spring.mvc.throw-exception-if-no-handler-found=true
现在你的@ControllerAdvice注释类可以处理"NoHandlerFoundException",如下所示.
@ControllerAdvice @RequestMapping(produces = "application/json") @ResponseBody public class RestControllerAdvice { @ExceptionHandler(NoHandlerFoundException.class) public ResponseEntity
注意仅仅指定此属性是不够的:
spring.mvc.throw-exception-if-no-handler-found=true
,默认情况下Spring将未知的URL映射到/**,所以真的永远不会"找不到处理程序".
要禁用未知的URL映射到/**,您需要
spring.resources.add-mappings=false ,
这就是为什么两个属性共同产生所需的行为.