我是 Spring 的新手。我注意到在处理静态资源时,有两个选项可用:
选项 1:
如果 Spring 的 DispatcherServlet
被映射到 /
并使用下面的代码,这使它成为“默认 Servlet ",可以使用 RequestMapping
注释将某些静态资源映射到 Spring 处理程序(覆盖 AbstractAnnotationConfigDispatcherServletInitializer
类):
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
然后我们仍然可以启用容器的“默认 Servlet”来处理那些 URL 模式未被 Spring 请求映射覆盖的静态资源(覆盖 WebMvcConfigurerAdapter
类):
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
这基本上使用 servlet 容器的“默认 Servlet”作为catch-all 来处理所有遗漏的静态资源/strong> 由 Spring 的 DispatcherServlet
实现。
选项 2:
(重写 WebMvcConfigurerAdapter
类)
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("*.efi").addResourceLocations("/");
}
- 为什么有两个选项?
- 这些方法之间的主要区别是什么?
- 还有其他选择吗?
我通常会选择选项 2,因为我想坚持使用 Spring,但我知道这不是一个强有力的理由。
一些与静态资源处理相关的引用:
- > Serve Static Resources with Spring
- > Spring Framework 4.1 - handling static web resources
- > Spring MVC – How to include JS or CSS files in a JSP page
添加 1
似乎选项 2 在资源映射方面提供了更大的灵 active 。甚至可以映射 WEB-INF
文件夹中的资源。
最佳答案
这是一个具体的例子,当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 的文档:
Note that if
DefaultServletHttpRequestHandler
is used, then requests will always be forwarded to the default servlet and aNoHandlerFoundException
would never be thrown in that case.
的确如此。结合上述两种方法不会导致触发 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 属性可用于设置远期到期 header ,以便客户端更有效地利用它们。
- 处理程序还会正确评估 Last-Modified header (如果存在),以便适本地返回 304 状态代码,避免对已由客户端缓存的资源产生不必要的开销。
另见 this answer有关使用默认 servlet 处理静态资源如何导致不需要的副作用的更复杂示例。
关于java - 为什么在 Spring 中有 2 种处理静态资源的方式(addResourceHandlers 和容器的 Default Servlet")?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34279705/