Spring Boot - 掌控404 Not Found

9 浏览
0 Comments

Spring Boot - 掌控404 Not Found

我正在尝试找出一种最简单的方法来控制基本的Spring Boot RESTful服务的404 Not Found处理程序,例如Spring提供的示例:https://spring.io/guides/gs/rest-service/。而不是返回默认的Json输出:{

"timestamp":1432047177086,

"status":404,

"error":"Not Found",

"exception":"org.springframework.web.servlet.NoHandlerFoundException",

"message":"No handler found for GET /aaa, ..."

}

。我想提供自己的Json输出。通过控制DispatcherServlet并使用DispatcherServlet#setThrowExceptionIfNoHandlerFound(true),我能够使其在404的情况下抛出异常,但是我无法通过@ExceptionHandler来处理该异常,就像处理MissingServletRequestParameterException一样。有什么想法吗?或者有没有比抛出和处理NoHandlerFoundException更好的方法?

0
0 Comments

Spring Boot是一个非常方便的框架,但是它在处理404 Not Found错误时并没有明确的处理方式,而是使用了WebMvc的错误响应。如果你希望Spring Boot能够处理这个异常,那么你需要对Spring Boot进行一些修改。对于404错误,异常类是NoHandlerFoundException;如果你想在你的类中处理这个异常,你必须在你的Application类中添加以下注解,并在DispatcherServlet中设置setThrowExceptionIfNoHandlerFound(true)。请参考以下代码:

public class Application {  
    private DispatcherServlet servlet;
    public static void main(String[] args) throws FileNotFoundException, IOException {
        SpringApplication.run(Application.class, args);
    }
    public CommandLineRunner getCommandLineRunner(ApplicationContext context) {
        servlet.setThrowExceptionIfNoHandlerFound(true);
        return args -> {};
    }
}

在这之后,你就可以在你的类中处理NoHandlerException了。

public class AppException {
    @ExceptionHandler(value={NoHandlerFoundException.class})
    @ResponseStatus(code=HttpStatus.BAD_REQUEST)
    public ApiError badRequest(Exception e, HttpServletRequest request, HttpServletResponse response) {
        e.printStackTrace();
        return new ApiError(400, HttpStatus.BAD_REQUEST.getReasonPhrase());
    }
}   

我创建了一个ApiError类来返回自定义的错误响应。

public class ApiError {
    private int code;
    private String message;
    public ApiError(int code, String message) {
        this.code = code;
        this.message = message;
    }
    public ApiError() {
    }   
    //getter & setter methods...
}

添加@EnableWebMvc注解将完全关闭Spring Boot对Spring MVC的自动配置,因此所有spring.mvc.*配置属性将被忽略。详细信息请参考参考文档[docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc-auto-configuration](docs.spring.io/spring-boot/docs/current/reference/html/…)。

0
0 Comments

根据Spring文档附录A,有一个名为"spring.mvc.throw-exception-if-no-handler-found"的布尔属性,可以用来启用抛出"NoHandlerFoundException"异常。然后你可以像处理其他异常一样创建异常处理程序。

class MyExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(MyExceptionHandler.class);
    
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handleNoHandlerFoundException(NoHandlerFoundException ex) {
        log.error("404 situation detected.",ex);
        return "Specified path not found on this server";
    }
}

不能使用没有控制器的`@ControllerAdvice`本身,因为它只与其控制器绑定。

0
0 Comments

在Spring Boot中,当出现404 Not Found错误时,实际上是由容器抛出的NoHandlerFoundException异常,而不是由应用程序内部抛出的。因此,容器无法了解到你的应用程序中的@RequestMapping注解,因为这是Spring的特性,而不是容器的特性。

解决这个问题的方法是使用HandlerExceptionResolver。我之前也遇到了和你一样的问题,你可以查看我在这个链接中的解决方案:How to intercept "global" 404s on embedded Tomcats in spring-boot

0