更新时间:2021-12-09 12:07:18 来源:极悦 浏览1210次
由于早期的Spring MVC对静态资源的处理不好,DispatCherServlet的请求映射是在Web.xml中配置的,经常在*.do,*. Xhtml。这就决定了请求的 URL 必须是后缀 URL,不能使用真正的 REST 风格的 URL。
如果将 DispatcherServlet 请求映射配置为“”,则 Spring MVC 会捕获 Web 容器的所有请求,包括静态资源,Spring MVC 会将它们视为正常的请求过程,从而导致相应处理器的错误。
如何让Spring框架捕获所有的URL请求,同时从Web容器中传输静态资源,前提是DispatcherServlet的请求映射为“/”。由于REST是Spring的重要特性之一,因此Spring团队非常接近静态资源来处理这个任务,给出了两个经典的解决方案。
在学习这两个场景之前,调整Web.xml中DispatcherServlet的配置,使其能够捕获所有请求。
< servlet >
< servlet-name > smart </ servlet-name >
< servlet-class > org.springframework.web.servlet.DispatcherServlet </ servlet-class >
< load-on-startup > 1 </ load-on-startup >
</小服务程序>
< servlet-mapping >
< servlet-name > smart </ servlet-name >
< url-pattern > / </ url-pattern >
</ servlet-mapping >
所有的URL请求都会通过<url-pattern> / </ url-pattern>的配置被Spring MVC的DispatcherServlet拦截。
在 smart-servlet.xml 中配置 <mvc: default-servlet-handler /> 后,您将在 Spring MVC 上下文中定义一个 org.springframework.web.servlet.resource.defaultservlettpRequestHandler,它将充当检查员的角色,输入用于筛选的 DispatcherServlet 的 URL。如果发现是静态资源请求,则转由WEB应用服务器默认servlet请求;如果不是静态资源请求,则继续由 DispatcherServlet 处理。
一般的web应用服务器(包括Tomcat、Jetty、GlassFish、JBoss、Resin、WebLogic和WebSphere)默认的servlet名称是default,所以defaultservlettpRequestHandler可以找到。如果用户使用的Web应用服务器的默认servlet名称不是default,则需要通过default-servlet-name属性明确指定。
< mvc:default-servlet-handler default—serv1et—name ="yourServerDefaultServlet Name" />
<mvc: default-servlet-handler />通过 Spring MVC 框架返回一个静态资源给 web 应用服务器。而 <mvc:resources /> 进一步由 Spring MVC 框架处理静态资源,并添加了一些有用的附加功能。
首先,<mvc:resources />允许静态资源放置在任何地方,比如web-inflicity、classpath等,甚至JavaScript等静态文件都可以打包到JAR包中。静态资源的位置由Location属性指定,由于location属性是资源类型,资源前缀指定资源前缀,如“ClassPath:”。传统Web容器的静态资源只能放在Web容器的根路径下,完全打破了这个限制。
其次,<mvc:resources /> 提供基于当前浏览器优化原则如Page Speed、YSLOW 的静态资源优化。可以指定一个cacheseconds属性来指定浏览器端的缓存时间,一般设置为一年,以充分利用浏览器端。输出静态资源时,应根据配置设置文本的 expires 和 cache-control 值。
当接收到静态资源获取请求时,检查请求头的Last-Modified值。如果静态资源没有变化,直接返回303响应状态码,表示客户端使用浏览器缓存的数据,而不是将静态资源的内容输出给客户端到足够的带宽,提高程序性能。
在 smart-servlet.xml 中添加以下配置:
< mvc:resources mapping ="/resources/**" location ="/,classpath:/META—INF/publicResources/" />
以上配置将web根路径“/”和类路径/meta-inf/publicresources/映射到/resources路径下。假设web根路径下有Images和JS两个资源目录,可以通过下图的方式来引用静态资源。
假设classpread/meta-inf/publicresources/下Images/Bg1.gif和JS/Test1.js也可以通过/resources/iImages/bg1.gif和/resources/js/test1.js在网页中进行引用,如以下代码所示。
< script src ="<c:url value=" / resources / js / test.js" /> " type= " text / javascript">< / script >
由于<mvc:resources />可以将多个物理路径映射到一个逻辑路径,所以一个逻辑路径所代表的资源存在于多个物理路径中。对于这个问题,<mvc:resources />的处理机制是只要找到匹配的资源,查找的顺序和Location中的物理路径按照Location的location中配置的顺序一致在物理路径下。
聪明的读者可能会问:既然网页根路径“/”映射了“/resources/**”,那么是否可以通过“/resources/web-inf/web.xml”访问网页中的这个敏感文件?答案是否定的。Spring MVC 在处理地图的静态资源时,会看到引用路径中是否包含Web-INF 或META-INF。如果包含,直接返回NULL值,保护安全文件不泄露。当然,如果/web-INF/Settings在location属性中,则可以通过/resources/web.xml的URL查看Web.xml。
< mvc:resources mapping ="/resources/**" location ="/WEB-INF/" />
所以在使用<mvc:resources />时要特别注意,不要在意,你不在意,你不要期望暴露的资源。
静态资源的缓存有效时间可以通过<mvc:resources />的cache-period属性在客户端浏览器中设置。
< mvc:resources mapping ="/resources/**" location ="/,classpath:/META—INF/publicResources/" cache-period ="31536000" />
一般情况下,将cache-period 设置为一年,以充分利用客户端的缓存数据。
在发布新版本的app时,即使服务器端的JavaScript、CSS等静态资源文件发生了变化,但由于客户端浏览器本身的问题,客户端并没有从服务器端下载新的静态资源。一个好的解决办法是在Page的path中添加应用版本号,这个版本号被新的部署版本改变了,导致这些静态资源由于新的部署版本而变成这些静态资源。“新资源”,客户端浏览器下载这个“新资源”而不使用缓存中的数据。对于这个方案,可以通过<mvc:resources/>的静态资源逻辑路径给出一个通用的方案。
发布版本号包含在的静态资源逻辑路径中。首先创建一个servletContextaWare实现类,如下代码所示。
导入javax.servlet.ServletContext;
导入org.springframework.web.context.ServletContextAware;
公共 类ResourcePathExposer实现ServletContextAware {
private ServletContext servletContext;
私有字符串资源根;
公共 无效初始化(){
字符串版本= "1.2.1"; // 1 在实际应用中,可以将应用的发布版本号保存在外部属性文件或数据库中,这里可以获取。这里只有一个模拟值。
resourceRoot = "/resources-" + 版本;// 2 发布资源逻辑路径上应用的版本号
getServletContext().setAttribute("resourceRoot" ,
getServletContext().getContextPath() +resourceRoot); // 3 在servletContext的属性列表的资源逻辑路径列表中
}
public void setServletContext(ServletContext servletContext) {
this .servletContext = servletContext;
}
公共字符串 getResourceRoot() {
返回资源根;
}
公共ServletContext getServletContext() {
返回servletContext;
}
}
在ResourcePatHexposer中获取应用的发布版本号,生成带有版本号的静态资源路径,将其值发布到servletContext,servletContext可以通过${resourceeroot}引用其值。
接下来,您要调整配置以使用静态资源逻辑路径的版本。
< bean id ="rpe" class ="com.smart.web.ResourcePathExposer" init-method ="init" />
< mvc:resources mapping ="#{rpe.resourceRoot}/**" location ="/"缓存-期间="31536000" />
将ResourcePatHexposer配置为1,并在init()中指定其初始化方法,以便在容器启动时初始化ResourceRoot的值。由于它实现了 servletContextaWare 接口,因此 Spring 将在 bean 的初始化中注入 servletContext 引用。
2处,通过Spring EL表达式引用resourceRootHexposer的resourceerOot属性值,生成动态静态资源逻辑路径。
最后调整在网页中引用静态资源的方式,如下代码所示。
< script src ="<c:url value=" ${resourceRoot}/js/test.js" /> " type= " text / javascript">< / script >
由于引用的resourceroot值和#{rpe.resourceroot}引用的<mvc:resources />,可以正确访问物理静态资源。这样,每次发布新版本后,客户端会自动下载新的静态资源,发布版本号发生变化。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习