简体   繁体   English

Spring Boot - 处理 NoHandlerFoundException

[英]Spring Boot - Handling NoHandlerFoundException

Read the Spring Reference Guide on how to handle NoHandlerFoundException and found that Spring sets, by default, throwExceptionIfNoHandlerFound to false .阅读关于如何处理NoHandlerFoundException春参考指南,发现弹簧套,默认情况下, throwExceptionIfNoHandlerFoundfalse

Knowing that, I thought it was a good idea to set this parameter to true .知道这一点后,我认为将此参数设置为true是个好主意。

I'm using Spring Boot.我正在使用 Spring Boot。

Did so:这样做了:

MyConfig.java配置文件

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

@SpringBootApplication
public class MyConfig {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(MyConfig.class, args);
        context.getBean(DispatcherServlet.class).setThrowExceptionIfNoHandlerFound(true);

        // ...
    }
}

Alright, now throwExceptionIfNoHandlerFound is equals true .好的,现在throwExceptionIfNoHandlerFound等于true However, that didn't worked as expected.然而,这并没有像预期的那样奏效。 The DispatcherServlet continued not throwing the NoHandlerFoundException . DispatcherServlet继续不抛出NoHandlerFoundException This way, I was unable to handle it.这样一来,我就无法处理了。

CustomExceptionHandler.java (this didn't worked) CustomExceptionHandler.java (这不起作用)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

After a bit of search, found that adding @EnableWebMvc should work.经过一番搜索,发现添加@EnableWebMvc应该可以。 Then, I did add this annotation to my CustomExceptionHandler然后,我确实将此注释添加到我的CustomExceptionHandler

CustomExceptionHandler.java (this did worked) CustomExceptionHandler.java (这确实有效)

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@EnableWebMvc
@ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // do my own handle ...

        // then, return ...
    }

}

This way, the handle works.这样,手柄就起作用了。 However, I'm using Spring Boot.但是,我正在使用 Spring Boot。 The Spring Boot docs suggests that if I insert @EnableWebMvc , I would lose some Spring Boot MVC Auto-configuration features, since I would take complete controll of Spring MVC. Spring Boot 文档表明,如果我插入@EnableWebMvc ,我将失去一些 Spring Boot MVC 自动配置功能,因为我将完全控制 Spring MVC。 ( See here ). 见这里)。

"If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc." “如果你想完全控制 Spring MVC,你可以添加你自己的 @Configuration 用 @EnableWebMvc 注释。”

Would I lose Spring MVC Auto-configuration?我会丢失 Spring MVC 自动配置吗? I mean, the @EnableWebMvc , in my case, it's not in a @Configuration class.我的意思是, @EnableWebMvc ,就我而言,它不在@Configuration类中。

My question is based on the fact that I'm not sure how this code above works, and I want to know if there's another way of doing this without losing the Spring MVC Auto-configuration.我的问题是基于这样一个事实,即我不确定上面的代码是如何工作的,我想知道是否有另一种方法可以在不丢失 Spring MVC 自动配置的情况下执行此操作。 Could someone explain?有人能解释一下吗?

Spring Boot auto-configuration will automatically add a ResourceHttpRequestHandler to deal with serving static resource. Spring Boot 自动配置会自动添加一个ResourceHttpRequestHandler来处理服务静态资源。 By default this handler is mapped against /** and is the last item in the handler chain.默认情况下,此处理程序映射到/**并且是处理程序链中的最后一项。

What this means is the DispatcherServlet won't throw a NoHandlerFoundException because it found the resource handler.这意味着DispatcherServlet不会抛出NoHandlerFoundException因为它找到了资源处理程序。 The resource handler processes the request and calls response.sendError(HttpServletResponse.SC_NOT_FOUND) to return a 404.资源处理程序处理请求并调用response.sendError(HttpServletResponse.SC_NOT_FOUND)以返回 404。

If you don't want this behavior, you can add the following to your application.properties :如果您不想要这种行为,您可以将以下内容添加到您的application.properties

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

The will configure the dispatcher servlet to throw the exception and also tell Spring Boot not to register the resource handler.将配置调度程序 servlet 以抛出异常告诉 Spring Boot 不要注册资源处理程序。

Before you go too far down that route, you might want to look at this section of the reference docs to see if it wouldn't be better to handle those errors in a different way.在沿着这条路线走得太远之前,您可能需要查看参考文档的这一部分,看看以不同的方式处理这些错误是否更好。 It's not totally clear from your question what you're actually trying to do in your error handler, but if it's just dealing with 404s then there's probably a better way.从您的问题中并不完全清楚您在错误处理程序中实际尝试做什么,但如果它只是处理 404,那么可能有更好的方法。

import java.util.Date;


import org.apache.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;


@ControllerAdvice
public class ExceptionController extends ResponseEntityExceptionHandler {
    static Logger logger = Logger.getLogger(ExceptionController.class.getName());

    @ExceptionHandler(Exception.class)
    public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
        ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
                request.getDescription(false));
        return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }
    @Override
    protected ResponseEntity <Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
                request.getDescription(false));
        
            logger.error(request);
        return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM