当前位置: 首页 > 知识库问答 >
问题:

Spring MVC REST通过返回JSON处理坏URL(404)

彭琛
2023-03-14

我正在使用SpringMVC开发一个REST服务,在那里我在类和方法级别有@刚需映射。

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

<error-page>
    <error-code>404</error-code>
    <location>/resourceNotFound</location>
</error-page>

但是,我希望返回自定义JSON,而不是此错误页面。

通过在controller中编写此代码,我能够处理异常并为其他异常返回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);

        }

我试过@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);
    }


}

共有3个答案

石思淼
2023-03-14

如果您使用的是Spring 3.2或更高版本,您可以使用控制器建议(@ControlllerAdtions)来处理映射错误(404)等问题。你可以在这里找到留档。看看第17.11节。例如,您可以使用它来提供更详细的日志记录,说明为什么您的请求绑定没有与特定的网址匹配,或者简单地返回比通用404更具体的响应。

饶滨海
2023-03-14

如果您使用的是Spring Boot,请同时设置以下两个属性:

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<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);
    }

}

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

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

,因为默认情况下Spring将未知URL映射到/**,所以实际上从来没有“找不到处理程序”。

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

spring.resources.add-mappings=false ,

这就是为什么这两个属性一起产生所需的行为。

邓卓
2023-03-14

在挖掘DispatcherServlet和HttpServletBean之后。SpringFramework中的init()我发现它在Spring4中是可能的。

组织。springframework。网状物servlet。调度员服务

/** 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);
    }
}

默认情况下,ThrowExceptionIfNoHandlerFIND为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>

然后,您可以使用此方法在一个带有@ControlllerAdtions注释的类中捕获它。

@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);
}

它允许我返回没有映射存在的坏URL的JSON响应,而不是重定向到JSP页面:)

{"message":"URL does not exist","url":"http://localhost:8080/service/patientssd"}
 类似资料:
  • 我想从一个网页下载大约1000个pdf文件。然后我遇到了这种笨拙的pdf url格式。两个和不适合我。 通常的pdf url如下所示: 但是这个网址就像: 所以它的url中没有. pdf,如果你点击它,你可以下载它,但是使用python的,你会得到损坏的文件。 起初我以为它被重定向到了其他的url。所以我使用了选项,结果与之前相同。。 此代码下载损坏的pdf文件。

  • 本文向大家介绍jQuery通过Ajax返回JSON数据,包括了jQuery通过Ajax返回JSON数据的使用技巧和注意事项,需要的朋友参考一下 服务端PHP读取MYSQL数据,并转换成JSON数据,传递给前端Javascript,并操作JSON数据。本文将通过实例演示了jQuery通过Ajax向PHP服务端发送请求并返回JSON数据。 JSON(JavaScript Object Notation

  • 1.API 返回结构 返回结果(response)分为:状态码(status code)、头部(headers)、消息体(body)。其中算法的结果会以 JSON 格式放在消息体中。 如何从 HTTP 返回中分别获取这三部分信息,请参见所用 HTTP 库的文档。 解析 JSON 格式需要寻找所用语言的 JSON 库,参见 http://www.json.org/ 2.正常结果 状态码为 2xx的为

  • /////////////////////个人控制器///////////////////////////////// ///////////////////个人/////////////////////////////////// ///////////////////PersondaoImpl/////////////////////////// /////////////人(模型)/////

  • 问题内容: 我面临着Java6 / 8的奇怪行为。我尝试通过需要基本用户身份验证的代理进行隧道传输。通过标准的Java身份验证器执行此操作。如果我尝试访问https网址作为第一个网址,则会引发异常: java.io.IOException:无法通过代理隧道。代理返回“需要HTTP / 1.1 407代理身份验证” 但是,如果我先访问http URL,然后再访问https URL,则https访问正

  • 我在postgres数据库中有这样的数据 我想创建rest api来像这样返回嵌套的json ] 目前,我只能为每条记录返回普通json,但我想分组并返回嵌套json,如有任何帮助,将不胜感激 下面是我的代码model.py views.py 序列化程序.py