为什么有两种方法可以处理Spring中的静态资源(addResourceHandlers和容器的默认Servlet")?

时间:2015-12-15 01:44:06

标签: java spring spring-mvc configuration

我是Spring的新手。我注意到在处理静态资源时,有两种选择:

选项1:

如果 Spring DispatcherServlet使用以下代码映射到/,这使其成为"默认Servlet",可以使用RequestMapping注释(覆盖AbstractAnnotationConfigDispatcherServletInitializer类)将某些静态资源映射到Spring处理程序:

@Override
protected String[] getServletMappings() {
    return new String[]{"/"};
}

然后我们仍然可以启用容器"默认Servlet"处理Spring模式未覆盖的静态资源(覆盖WebMvcConfigurerAdapter类):

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

这基本上使用了servlet容器"默认Servlet"作为 catch-all 来处理Spring的所有静态资源 错过 {{1} }。

选项2:

(覆盖DispatcherServlet类)

WebMvcConfigurerAdapter
  • 为什么有两种选择?
  • 这些方法之间的主要区别是什么?
  • 还有其他选择吗?

我通常选择2,因为我想坚持使用Spring,但我知道这不是一个强有力的理由。

有关静态资源处理的一些参考:

添加1

似乎选项2在资源映射方面提供了更大的灵活性。甚至可以映射@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("*.efi").addResourceLocations("/"); } 文件夹中的资源。

1 个答案:

答案 0 :(得分:2)

以下是Falling Back On the "Default" Servlet To Serve Resources不适用的具体示例。

这是上述方法的典型实现:

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
    configurer.enable();
    return;
}

但是,目前处理Spring 4 中404错误的最佳做法要使用setThrowExceptionIfNoHandlerFound

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

不幸的是,根据DispatcherServlet的文档:

  

请注意,如果使用DefaultServletHttpRequestHandler,则请求   将始终转发到默认的servlet和a   在这种情况下永远不会抛出NoHandlerFoundException

实际上,情况确实如此。结合上述两种方法不会导致NoHandlerFoundException被触发,这反过来又会阻止我的404自定义错误页面解析。现在,如果我要评论我的configureDefaultServletHandling方法,则会抛出NoHandlerFoundException并且我的错误处理(通过链接答案中显示的@ControllerAdvice)解析为我的自定义'notFoundPage'。

不幸的是,现在这意味着我的静态资源(即'default.css')未得到解决:

DEBUG org.springframework.web.servlet.DispatcherServlet - Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'notFoundPage'; model is {}
org.springframework.web.servlet.NoHandlerFoundException: No handler found for GET /webapp-test/style/default.css

我认为没有办法调和这两种方法,这样它们就不会相互干扰。我的结论是,在这种情况下,“默认Servlet”方法不适合提供静态资源,这使我们得到了addResourceHandlers方法。

使用addResourceHandlers method的好处包括:

  • ...从Web应用程序根目录以外的位置提供静态资源,包括类路径上的位置
  • cache-period属性可用于设置远期的过期标头,以便客户端更有效地使用它们。
  • 处理程序还正确评估Last-Modified标头(如果存在),以便在适当时返回304状态代码,从而避免客户端缓存的资源产生不必要的开销。

另请参阅this answer以获取更复杂的示例,了解如何使用默认servlet处理静态资源会导致不必要的副作用。