首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在Spring中有两种处理静态资源的方法(addResourceHandlers和容器的默认Servlet")?

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

Stack Overflow用户
提问于 2015-12-15 01:44:05
回答 1查看 2.6K关注 0票数 7

我是春天的新手。我注意到,在处理静态资源时,有两个可用的选项:

选项1:

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

代码语言:javascript
运行
复制
@Override
protected String[] getServletMappings() {
    return new String[]{"/"};
}

然后,我们仍然可以启用容器的“默认Servlet”来处理那些其URL模式未被Spring映射覆盖(覆盖WebMvcConfigurerAdapter类)的静态资源:

代码语言:javascript
运行
复制
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}

这基本上使用servlet容器的“默认Servlet”作为catch- all 来处理DispatcherServlet遗漏的所有静态资源。

备选方案2:

(重写WebMvcConfigurerAdapter类)

代码语言:javascript
运行
复制
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    super.addResourceHandlers(registry);
    registry.addResourceHandler("*.efi").addResourceLocations("/");
}
  • 为什么有两种选择?
  • 这些方法的主要区别是什么?
  • 还有其他选择吗?

我通常选择第2种选择,因为我想坚持使用Spring,但我知道这不是一个很好的理由。

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

添加1

选项2似乎为资源映射提供了更大的灵活性。甚至可以映射WEB-INF文件夹中的资源。

EN

回答 1

Stack Overflow用户

发布于 2016-11-12 14:27:59

以下是回到“默认”Servlet以服务于资源不适用的具体示例。

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

代码语言:javascript
运行
复制
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
    configurer.enable();
    return;
}

但是,当前处理Spring 4中404错误的最佳实践似乎是使用setThrowExceptionIfNoHandlerFound

代码语言:javascript
运行
复制
@Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext)
{
    DispatcherServlet dispatcherServlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
    return dispatcherServlet;
}

不幸的是,根据DispatcherServlet的文档

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

事实上,情况就是这样。将上述两种方法结合在一起并不会触发NoHandlerFoundException,这反过来又会阻止我的404自定义错误页解析。现在,如果我要注释掉我的configureDefaultServletHandling方法,就会抛出NoHandlerFoundException,并且我的错误处理(通过@ControllerAdvice (如链接的答案中所示)解析为我的自定义'notFoundPage‘。

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

代码语言:javascript
运行
复制
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方法。

使用方法的好处包括:

  • ...serve来自web应用程序根以外位置的静态资源,包括类路径上的位置。
  • 缓存期间属性可用于设置远未来的过期标头,以便客户端更有效地使用它们。
  • 处理程序还正确地评估最后修改的标头(如果存在的话),以便适当地返回304状态代码,从而避免了客户端已经缓存的资源的不必要开销。

另外,请参阅这个答案中一个更复杂的示例,说明使用默认servlet处理静态资源会导致不必要的副作用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34279705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档