Spring MVC无法从Resource Handler处理404?

时间:2018-03-15 14:30:47

标签: java spring spring-mvc

我正在使用Spring MVC 4.3.11.RELEASE并为静态资源提供了一个vanilla资源处理程序。对于存在的资源,它工作得很好。但是,如果没有,它似乎返回404 DispatcherServlet,它对该响应感到满意,因为它找到了一个处理程序。我有NoHandlerFoundException的ControllerAdvice,它适用于控制器但不适合处理这种情况。所以Spring MVC完全放弃了,我得到了令人讨厌的Tomcat 404响应。我找不到为这种情况配置处理的方法,所以我可以返回一个正确的响应。

为Spring启用TRACE后,您会看到以下内容:

2018-03-15T14:22:05,361 TRACE [] DispatcherServlet          - Bound request context to thread: org.apache.catalina.connector.RequestFacade@597aa896
2018-03-15T14:22:05,361 DEBUG [] DispatcherServlet          - DispatcherServlet with name 'dispatcher' processing GET request for [/creditcard/static/doh]
2018-03-15T14:22:05,361 TRACE [] DispatcherServlet          - Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@4b720a14] in DispatcherServlet with name 'dispatcher'
2018-03-15T14:22:05,361 DEBUG [] questMappingHandlerMapping - Looking up handler method for path /static/doh
2018-03-15T14:22:05,364 DEBUG [] questMappingHandlerMapping - Did not find handler method for [/static/doh]
2018-03-15T14:22:05,364 TRACE [] DispatcherServlet          - Testing handler map [org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@67db7dde] in DispatcherServlet with name 'dispatcher'
2018-03-15T14:22:05,364 TRACE [] BeanNameUrlHandlerMapping  - No handler mapping found for [/static/doh]
2018-03-15T14:22:05,364 TRACE [] DispatcherServlet          - Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@4698270f] in DispatcherServlet with name 'dispatcher'
2018-03-15T14:22:05,364 DEBUG [] SimpleUrlHandlerMapping    - Matching patterns for request [/static/doh] are [/static//**]
2018-03-15T14:22:05,364 DEBUG [] SimpleUrlHandlerMapping    - URI Template variables for request [/static/doh] are {}
2018-03-15T14:22:05,364 DEBUG [] SimpleUrlHandlerMapping    - Mapping [/static/doh] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/static//]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@20537c7e]]] and 1 interceptor
2018-03-15T14:22:05,364 TRACE [] DispatcherServlet          - Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@442b38d3]
2018-03-15T14:22:05,364 TRACE [] DispatcherServlet          - Testing handler adapter [org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter@3128c8a7]
2018-03-15T14:22:05,364 DEBUG [] DispatcherServlet          - Last-Modified value for [/creditcard/static/doh] is: -1
2018-03-15T14:22:05,364 TRACE [] ResourceHttpRequestHandler - Applying "invalid path" checks to path: doh
2018-03-15T14:22:05,364 TRACE [] PathResourceResolver       - Resolving resource for request path "doh"
2018-03-15T14:22:05,364 TRACE [] PathResourceResolver       - Checking location: ServletContext resource [/static//]
2018-03-15T14:22:05,364 TRACE [] PathResourceResolver       - No match for location: ServletContext resource [/static//]
2018-03-15T14:22:05,364 TRACE [] ResourceHttpRequestHandler - No matching resource found - returning 404
2018-03-15T14:22:05,364 DEBUG [] DispatcherServlet          - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling
2018-03-15T14:22:05,364 TRACE [] DispatcherServlet          - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@597aa896
2018-03-15T14:22:05,364 DEBUG [] DispatcherServlet          - Successfully completed request

思考?谢谢......

2 个答案:

答案 0 :(得分:1)

mrkurtan答案仅适用于春季启动,因为spring.resources.add-mappings=false是春季启动配置

因此通过NoHandlerFoundException重写所需的配置并进行处理。

  1. 创建一个带有GlobalExceptionHandler注释的类@ControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler 
{
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handleNotFoundError(Exception ex) 
    {
        return "redirect:/yourCustom404page";
    }
}
  1. 默认情况下,当页面/资源不存在时,servlet容器将抛出默认的404页面。如果您想要自定义404响应,那么如果找不到任何处理程序,则需要告诉DispatcherServlet引发异常。我们可以通过将throwExceptionIfNoHandlerFound servlet初始化参数设置为true
  2. 来完成此操作。

在基于spring-mvc java的配置中,

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
    ...

    @Override
    protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext) 
    {
        final DispatcherServlet servlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
        servlet.setThrowExceptionIfNoHandlerFound(true);
        return servlet;
    }

}

如果是基于xml的配置,请像这样初始化您的调度程序servlet

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

答案 1 :(得分:0)

我有同样的问题。我的解决方法如下:

  • spring.resources.add-mappings = false(在yaml或application.properties中)
  • 在WebMvcConfigurer'addResourceHandlers'方法的Config中的
  • 添加所有映射,例如:

    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(NoHandlerFoundException.class)
        public String handleNotFoundError(Exception ex) {
            return "redirect:/your404page";
        }
    }
    
  • 必须删除默认的servlet处理程序,因为它将尝试处理并返回状态404,但绝不会抛出NoHandlerFoundException

  • 添加GlobalExceptionHandler控制器建议:

    class A
    {
        public function child1()
        {
            $var1 = 'abc';
        }
    }
    
    class B extends A
    {
        public function child1()
        {
            echo parent::$var1; // Return error undefined class constant 'var1'
        }
    }
    

希望这会有所帮助!对我来说,它运作完美!