Spring MVC REST通过返回JSON来处理Bad Url(404)

 爱情de眷恋_558 发布于 2023-01-20 11:42

我正在使用SpringMVC开发一个REST服务,我在类和方法级别有@RequestMapping.

此应用程序当前配置为返回在web.xml中配置的错误页面jsp.


    404
    /resourceNotFound

但是我想返回自定义JSON而不是此错误页面.

我可以通过在控制器中编写这个来处理异常并返回json以获取其他异常,但是当url根本不存在时,不知道如何以及在何处编写逻辑以返回JSON.

    @ExceptionHandler(TypeMismatchException.class)
        @ResponseStatus(value=HttpStatus.NOT_FOUND)
        @ResponseBody
        public ResponseEntity 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(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 ResponseEntity 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(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 ResponseEntity 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(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> unhandledPath(final NoHandlerFoundException e) {
        Map 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>(errorInfo, HttpStatus.NOT_FOUND);
    }

}

注意仅仅指定此属性是不够的:

spring.mvc.throw-exception-if-no-handler-found=true

,默认情况下Spring将未知的URL映射到/**,所以真的永远不会"找不到处理程序".

要禁用未知的URL映射到/**,您需要

spring.resources.add-mappings=false ,

这就是为什么两个属性共同产生所需的行为.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有