Spring MVC REST 通过返回 JSON 处理错误的 URL (404)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22157687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring MVC REST Handing Bad Url (404) by returning JSON
提问by Himalay Majumdar
I am developing a REST service using SpringMVC, where I have @RequestMapping at class and method level.
我正在使用 SpringMVC 开发 REST 服务,我在类和方法级别有 @RequestMapping 。
This application is currently configured to return error-page jsp configured in web.xml.
此应用程序当前配置为返回 web.xml 中配置的错误页面 jsp。
<error-page>
<error-code>404</error-code>
<location>/resourceNotFound</location>
</error-page>
I however want to return custom JSON instead of this error page.
但是,我想返回自定义 JSON 而不是此错误页面。
I am able to handle exception and return json for other exceptions, by writing this in controller, but not sure how and where to write the logic to return JSON when the url does not exist at all.
通过在控制器中编写它,我能够处理异常并为其他异常返回 json,但不确定在 url 根本不存在时如何以及在何处编写返回 JSON 的逻辑。
@ExceptionHandler(TypeMismatchException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ResponseEntity<String> handleTypeMismatchException(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<String>(errorInfo.toJson(), headers, HttpStatus.BAD_REQUEST);
}
I tried @ControllerAdvice, it works for other exception scenarios, but not when mapping is not avaialble,
我试过@ControllerAdvice,它适用于其他异常情况,但不适用于映射不可用时,
@ControllerAdvice
public class RestExceptionProcessor {
@Autowired
private MessageSource messageSource;
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ResponseEntity<String> requestMethodNotSupported(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<String>(errorInfo.toJson(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(NoSuchRequestHandlingMethodException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ResponseEntity<String> 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<String>(errorInfo.toJson(), HttpStatus.BAD_REQUEST);
}
}
回答by Himalay Majumdar
After digging around DispatcherServlet and HttpServletBean.init() in SpringFramework I see that its possible in Spring 4.
在 SpringFramework 中挖掘 DispatcherServlet 和 HttpServletBean.init() 之后,我发现它在 Spring 4 中是可能的。
org.springframework.web.servlet.DispatcherServlet
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);
}
}
throwExceptionIfNoHandlerFoundis false by default and we should enable that in web.xml
throwExceptionIfNoHandlerFound默认为 false,我们应该在web.xml 中启用它
<servlet>
<servlet-name>appServlet</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>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
And then you can catch it in a class annotated with @ControllerAdviceusing this method.
然后你可以使用这个方法在用@ControllerAdvice注释的类中捕获它。
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(value=HttpStatus.NOT_FOUND)
@ResponseBody
public ResponseEntity<String> requestHandlingNoHandlerFound(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<String>(errorInfo.toJson(), HttpStatus.BAD_REQUEST);
}
Which allows me to return JSON response for bad URLs for which no mapping exist, instead of redirecting to a JSP page :)
这允许我为不存在映射的错误 URL 返回 JSON 响应,而不是重定向到 JSP 页面:)
{"message":"URL does not exist","url":"http://localhost:8080/service/patientssd"}
回答by mancini0
If you are using Spring Boot, set BOTH of these two properties:
如果您使用的是 Spring Boot,请同时设置这两个属性:
spring.resources.add-mappings=false
spring.mvc.throw-exception-if-no-handler-found=true
Now your @ControllerAdvice annotated class can handle the "NoHandlerFoundException", as below.
现在您的@ControllerAdvice 注释类可以处理“NoHandlerFoundException”,如下所示。
@ControllerAdvice
@RequestMapping(produces = "application/json")
@ResponseBody
public class RestControllerAdvice {
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Map<String, Object>> unhandledPath(final NoHandlerFoundException e) {
Map<String, Object> errorInfo = new LinkedHashMap<>();
errorInfo.put("timestamp", new Date());
errorInfo.put("httpCode", HttpStatus.NOT_FOUND.value());
errorInfo.put("httpStatus", HttpStatus.NOT_FOUND.getReasonPhrase());
errorInfo.put("errorMessage", e.getMessage());
return new ResponseEntity<Map<String, Object>>(errorInfo, HttpStatus.NOT_FOUND);
}
}
note it is not sufficient to only specify this property:
请注意,仅指定此属性是不够的:
spring.mvc.throw-exception-if-no-handler-found=true
, as by default Spring maps unknown urls to /**, so there really never is "no handler found".
,因为默认情况下 Spring 将未知的 url 映射到 /**,所以真的从来没有“没有找到处理程序”。
To disable the unknown url mapping to /**, you need
要禁用到 /** 的未知 url 映射,您需要
spring.resources.add-mappings=false ,
which is why the two properties together produce the desired behavior.
这就是为什么这两个属性一起产生所需的行为。
回答by Software Engineer
If you're using spring 3.2 or later you can use a controller advice (@ControllerAdvice) to deal with, amongst other things, mapping errors (404's). You can find documentation here. Take a look at section 17.11. You can use this, for example, to provide more detailed logging on why your request bindings aren't being matched for specific urls, or to simply return a more specific response than a generic 404.
如果您使用的是 spring 3.2 或更高版本,则可以使用控制器建议 ( @ControllerAdvice) 来处理映射错误(404 错误)等。您可以在此处找到文档。请看第 17.11 节。例如,您可以使用它来提供更详细的日志记录,说明为什么您的请求绑定与特定 url 不匹配,或者简单地返回比通用 404 更具体的响应。
回答by user2807219
you can return json in the location below,that /handle/404.
您可以在下面的位置返回 json,即/handle/404。
<error-page>
<error-code>404</error-code>
<location>/handle/404</location>
</error-page>
after you config this in web.xml,a 404 error will redirect to /handle/404,and you can create a controller with this mapping and return a json result. for example.
在 web.xml 中配置后,404 错误将重定向到/handle/404,您可以使用此映射创建控制器并返回 json 结果。例如。
@RestController
@RequestMapping(value = "handle")
public class HttpErrorController {
@RequestMapping(value = "404")
public String handle404() {
return "404 error";
}
}

