Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to figure out the simplest way to take control over the 404 Not Found handler of a basic Spring Boot RESTful service such as the example provided by Spring:

https://spring.io/guides/gs/rest-service/

Rather than have it return the default Json output:

{
  "timestamp":1432047177086,
  "status":404,
  "error":"Not Found",
  "exception":"org.springframework.web.servlet.NoHandlerFoundException",
  "message":"No handler found for GET /aaa, ..."
}

I'd like to provide my own Json output.

By taking control of the DispatcherServlet and using DispatcherServlet#setThrowExceptionIfNoHandlerFound(true), I was able to make it throw an exception in case of a 404 but I can't handle that exception through a @ExceptionHandler, like I would for a MissingServletRequestParameterException. Any idea why?

Or is there a better approach than having a NoHandlerFoundException thrown and handled?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.1k views
Welcome To Ask or Share your Answers For Others

1 Answer

It works perfectly Fine.

When you are using SpringBoot, it does not handle (404 Not Found) explicitly; it uses WebMvc error response. If your Spring Boot should handle that exception, then you should do some hack around Spring Boot. For 404, the exception class is NoHandlerFoundException; if you want to handle that exception in your @RestControllerAdvice class, you must add @EnableWebMvc annotation in your Application class and set setThrowExceptionIfNoHandlerFound(true); in DispatcherServlet. Please refer to the following code:

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

After this you can handle NoHandlerException in your @RestControllerAdvice class

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

I have created ApiError class to return customized error response

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...
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...