Spring Boot-控制404未找到

dam*_*end 5 rest spring json http-status-code-404

我试图找出控制基本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, ..."
}
Run Code Online (Sandbox Code Playgroud)

我想提供自己的Json输出。

通过控制DispatcherServlet和使用DispatcherServlet#setThrowExceptionIfNoHandlerFound(true),我能够使它在404的情况下引发异常,但是我无法通过来处理该异常@ExceptionHandler,就像我处理一样MissingServletRequestParameterException。知道为什么吗?

还是有比抛出并处理NoHandlerFoundException更好的方法?

Kou*_*lik 5

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

@RestControllerAdvice
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";
    }
}
Run Code Online (Sandbox Code Playgroud)

@ExceptionHandler没有@ControllerAdvice(或@RestControllerAdvice) 的自身无法使用,因为它仅绑定到其控制器。


vel*_*vel 5

它工作得很好。

当您使用 SpringBoot 时,它不会明确处理(404 Not Found),而是使用WebMvc错误响应。如果您的 Spring Boot 应该处理该异常,那么您应该对 Spring Boot 进行一些修改。对于 404 异常类是NoHandlerFoundException如果你想在你的@RestControllerAdvice 中处理该异常类中必须在应用程序类中添加@EnableWebMvc注释并设置setThrowExceptionIfNoHandlerFound(true); 在 DispatcherServlet 中。请参考代码

@SpringBootApplication
@EnableWebMvc
public class Application {  
    @Autowired
    private DispatcherServlet servlet;

    public static void main(String[] args) throws FileNotFoundException, IOException {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner getCommandLineRunner(ApplicationContext context) {
        servlet.setThrowExceptionIfNoHandlerFound(true);
        return args -> {};
    }
}
Run Code Online (Sandbox Code Playgroud)

在此之后你可以处理 @RestControllerAdvice类中NoHandlerException

@RestControllerAdvice
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());
    }
}   
Run Code Online (Sandbox Code Playgroud)

我创建了 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...
}
Run Code Online (Sandbox Code Playgroud)


小智 2

简而言之,是NoHandlerFoundException从容器中抛出的,而不是从容器内的应用程序中抛出的。因此,您的容器无法了解您的信息,@ExceptionHandler因为这是 Spring 功能,而不是容器中的任何内容。

你想要的是一个HandlerExceptionResolver. 我遇到了和你一样的问题,看看我的解决方案:How to拦截“global”404s onEmbedded Tomcats in spring-boot