Spring REST 接口自定义404不能捕获NoHandlerFoundException问题

发布时间 2023-06-27 11:05:59作者: 稻草人.Net

Spring REST 接口自定义404以及解决不能捕获NoHandlerFoundException问题  

一、自定义404响应内容

版本说明:Spring Boot 2.0.1.RELEASE

REST风格默认PostMan请求的404响应如下:

{
    "timestamp": "2018-06-07T05:23:27.196+0000",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/shopping/123/TEST"
}

 

如果不想返回此内容,可以做如下配置:

步骤一:

application.properties文件中添加如下两句:

#没有绑定的url直接抛出错误
spring.mvc.throw-exception-if-no-handler-found=true
#不为静态文件建立映射
spring.resources.add-mappings=false

添加以上配置后,404时DispatcherServlet会抛出NoHandlerFoundException,注意spring.resources.add-mappings 在当前版本下需要设置为false,否则不会抛出异常。

mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
    noHandlerFound(processedRequest, response);
    return;
}

只有第一句代码找不到对应该请求的处理器时,才会进入下面的noHandler方法去抛出NoHandlerFoundException异常。通过测试发现,springboot的WebMvcAutoConfiguration会默认配置如下资源映射:

/映射到/static(或/public、/resources、/META-INF/resources) /webjars/ 映射到classpath:/META-INF/resources/webjars/ /**/favicon.ico映射favicon.ico文件.

配置如下属性,NoHandlerFoundException异常就能被@ControllerAdvice捕获了

#不存在的url直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#不添加静态资源映射
spring.resources.add-mappings=false
#指定静态资源路径
spring.mvc.static-path-pattern=/statics/**
#浏览器访问时Remove Whitelabel Error Page
server.error.whitelabel.enabled=false

步骤二:

全局异常捕获通过@ExceptionHandler(NoHandlerFoundException.class)

@RestControllerAdvice
public class ExceptionResolver {

    @ExceptionHandler(Exception.class)
    public HashMap<String, String> handleException(HttpServletRequest request, Exception e) {
        HashMap<String, String> response = new HashMap<>();
        response.put("message", e.getMessage());
        return response;
    }

    @ExceptionHandler(MissingPathVariableException.class)
    public HashMap<String, String> handleMissingPathVariableException(HttpServletRequest request, MissingPathVariableException e) {
        HashMap<String, String> response = new HashMap<>();
        response.put("message", "Required path variable is missing in this request. Please add it to your request.");
        return response;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public HashMap<String, String> handleNotFoundResourceException(HttpServletRequest request, NoHandlerFoundException e) {
        HashMap<String, String> response = new HashMap<>();
        response.put("message", "Requested resource wasn't found on the server");
        return response;
    }
}

 

二、注意事项

网上搜基本上都是说只需设置spring.mvc.throw-exception-if-no-handler-found=true即可,但设置后依然无效!

或者是需要设置spring.resources.add-mappings=false,但设置后依然无效!

通过看DispatcherServlet源码才发现,Srpingboot的版本不同spring.resources.add-mappings配置存在差异。

高版本比如Srping boot 2.7 要使用spring.web.resources.add-mappings=false才能生效。

另外全局异常类上要注意@RestControllerAdvice(basePackages ) 不要指定basePackages

 

参考文档:https://skryvets.com/blog/2018/12/27/enhance-exception-handling-when-building-restful-api-with-spring-boot/