匹配根URL和静态资源的服务
我的问题是如何configuration一个Spring MVC应用程序允许在同一时间
- 应用程序应该服务静态资源(CSS,JS,图像…)
- 根url(
http://my.host.org/webb_app/
)应该由Spring控制器提供
我已经阅读了如何在Spring MVC中处理静态内容? , 使用Spring,映射到web.xml中的根目录,找不到 静态资源 , Tomcat为Spring MVC应用程序提供静态资源 。 所有提供的工作解决scheme,直到最近,我用它们作为烹饪食谱,直到应用程序工作或多或less可接受。 所有这些都没有提及,也没有清楚地理解为什么以及如何最终奏效。
所以问题是:为这个需求configuration一个Spring MVC应用程序的不同方式是什么,它们的缺点是什么,它们背后的基本原理是什么。
我将从关于DefaultServlet
如何工作的初步评论开始。 根据Servlet 3.0规范 ,容器通常提供一个默认的servlet,它具有最低的优先级,并提供静态上下文。 mapping /
是默认servlet的隐式映射。
现在解决scheme:
将弹簧控制器映射到子层次结构
这是最简单的解决scheme:例如,将Spring DispatcherServlet
映射到/pages
,或映射到/pages
和/api
。 默认的servlet将会提供所有其他的URL(包括root)。 要为根控制器服务,可以将控制器映射到/home
(例如),并/index.jsp
包含/index.jsp
其中包含<jsp:forward page="/home"/>
– 这是在其他框架中使用扩展如Struts( *.do
for old Struts1)的映射。
缺点:用/pages
说明url不是很好。
将资源映射到子层次结构
该解决scheme在参考页面中被高度使用。 Spring DispatcherServlet
映射到/*
,因此获得所有请求(除非存在更具体的映射)。 为了提供静态资源,你只需声明一个ResourceHttpRequestHandler
,使用XML:
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
或者在javaconfiguration中:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/"); } }
这工作得很好,你可以映射一个Spring控制器到/
直接。
缺点:你不能提供直接在根上下文中的静态资源。
将DispatcherServlet
映射为默认的servlet
将Spring DispatcherServlet
映射到/
实际上是从容器中replace默认的servlet来处理所有尚未处理的URL。 通过这个映射,Spring可以回退到最初的默认servlet,而不是映射到控制器的URL。 为了这个工作,你必须configuration一个DefaultServletHttpRequestHandler
的URL映射"/**"
和最低优先级。 你用XML来做:
<mvc:default-servlet-handler/>
或者在javaconfiguration中:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
这样, DispatcherServlet
通常会调用所有控制器,并使原始的默认servlet为静态(未映射)的资源提供服务。 不幸的是,这不适用于根URL,并且您必须像第一个解决scheme一样使用<jsp:forward page="..."/>
技巧。
缺点 :
- 不能直接映射根URL并需要
index.jsp
<jsp:forward page="..."/>
窍门 - 由于Spring取代了原来的容器默认servlet,它必须通过名称来调用它。 它适用于常见的容器(包括Tomcat,Jetty,GlassFish,JBoss,Resin,WebLogic和WebSphere),或者您也可以将默认servlet的名称作为XMLconfiguration中的一个属性(
<mvc:default-servlet-handler default-servlet-name="customDefaultServlet"/>
)或作为参数,如果Javaconfiguration:configurer.enable("customDefaultServlet");
参考资料: Spring参考手册/ Web MVC框架/服务资源