给webapp路径里的静态资源加时间戳[JS和CSS],Java自定义标签和Servlet的配置

本文介绍了一种通过在项目启动时扫描webapp路径并记录时间戳的方式,来防止浏览器缓存静态资源如js和css文件。通过自定义jsp标签实现动态引用资源,以及在web.xml中配置自定义标签库,确保每次页面加载时获取最新资源版本。最后通过手动更新时间戳的方法进一步优化资源更新流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        前几日做了一个很小的功能,一般工程启动后,为了能防止浏览器不缓存那些静态资源,比如js和css文件,一般的思路是在引用那些文件的路径后面增加一个时间戳,例如:

本来是下面这样的,

<link type="text/css" rel="stylesheet" href="/common.css">

但,这样的话如果用户不用ctrl+F5强制刷新页面的话可能会看不到最新的网页效果。所以为了解决这个小问题,我采用了很传统效率很低的一种方法[本人菜鸟]:

        1.  在项目启动的时候用servlet初始化的时候把webapp路径扫描一遍,然后存入一个map中,其中key存文件路径,value存时间戳,最后把这个map放入全局上下文ServletContext中。

        2.  自定义jsp标签,用于在jsp页面引用的时候替换上面的样式。

具体实现的办法如下:

       

<servlet>
      <servlet-name>myServlet</servlet-name>
      <servlet-class>com.myServlet</servlet-class>
      <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
      <servlet-name>myServlet</servlet-name>
      <url-pattern>/myPath</url-pattern>
</servlet-mapping>

以上是配置一个servlet,不解释了。

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class myServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = Logger.getLogger(myServlet.class);
	private Map<String, String> map = new HashMap<String, String>();

	@Override
	public void destroy() {
		super.destroy();
	}

	@Override
	public void init() throws ServletException {
		logger.info(this.getClass().getName() + "静态资源装载开始......");
		ServletContext context = getServletContext();
		// 获得时间戳
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String timestamp = "ver=" + sdf.format(new Date());

		String[] strPath = new String[] { "\\css", "\\edm", "\\gmw", "\\js","\\res", "\\script", "\\static", "\\styles", "\\themes" };
		String tempPath = ""; // 遍历strPath数组时用于存放临时的路径
		for (int i = 0; i < strPath.length; i++) {
			tempPath = strPath[i];
			String rootPath = context.getRealPath(tempPath);
			logger.info(this.getClass().getName() + "rootPath:" + rootPath);
			getPath(rootPath, timestamp, tempPath);
		}
		context.setAttribute("staticResource", map);
		logger.info(this.getClass().getName() + "静态资源装载完毕......");
	}

	/**
	 * 
	 * @param strPath
	 *            项目绝对根路径
	 * @param time
	 *            时间戳
	 * @param tempPath
	 *            临时路径
	 */
	private void getPath(String strPath, String time, String tempPath) {
		String contextPath = getServletConfig().getServletContext().getContextPath();
		File dir = new File(strPath);
		File[] files = dir.listFiles();
		if (files == null) {
			return;
		} else {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					getPath(files[i].getAbsolutePath(), time, tempPath);
				} else {
					String strFileName = null;
					strFileName = files[i].getAbsolutePath();
					int loc = 0;
					if (strFileName.indexOf(tempPath) != -1 && (strFileName.endsWith("css") || strFileName.endsWith("js"))) {
						loc = strFileName.indexOf(tempPath);
						strFileName = strFileName.substring(loc);
						strFileName = strFileName.replaceAll("\\\\", "/");
						map.put(strFileName, contextPath + strFileName + "?"+ time);
					} else {
						continue;
					}

				}
			}
		}
		//循环输出静态资源路径,value为时间戳
		for (String path : map.keySet()) {
			System.out.println("path=" + path + " value=" + map.get(path));
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String contextPath = getServletConfig().getServletContext().getContextPath();
		// 获得时间戳
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String timestamp = "ver=" + sdf.format(new Date());

		for (String path : map.keySet()) {
			map.put(path, contextPath + path + "?" + timestamp);
		}
		logger.info(this.getClass().getName() + "手动更新静态资源的时间戳完成......");
		resp.getWriter().write("update ok!");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

上面的代码是具体的遍历操作,都是基础,应该大家也都明白。需要注意的是doGet方法是用于手动更新时间戳的。

        我们继续

       

import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * JS 自定义标签,用于防止浏览器缓存
 * 
 * @author 
 * 
 */
public class JsTag extends TagSupport {
	private static final long serialVersionUID = 1L;

	private String jsSrc = "";// js路径

	public int doEndTaag() {
		return EVAL_PAGE;
	}

	public int doStartTag() throws JspTagException {
		try {
			String a = "<script type=\"text/javascript\" src=\"";
			String b = "\"></script>";
			pageContext.getOut().print(a + jsSrc + b);
		} catch (Exception e) {
			throw new JspTagException(e);
		}
		return SKIP_BODY;
	}

	public String getJsSrc() {
		return jsSrc;
	}

	public void setJsSrc(String jsSrc) {
		this.jsSrc = jsSrc;
	}
}

以上功能是自定义了一个标签。

       

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
                        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
 <tlib-version>1.0</tlib-version>
 <jsp-version>1.2</jsp-version>
 <short-name>/p2p</short-name>
 <uri>tags</uri>
 <display-name>p2p</display-name>
 <description>
     <![CDATA[Display P2P information.]]>
 </description>
 
 <tag>
 	<name>js</name>
 	<tag-class>com.utils.JsTag</tag-class>
 	<bodycontent>empty</bodycontent>
 	<attribute>
      <name>jsSrc</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
 </tag>
 
 <tag>
 	<name>css</name>
 	<tag-class>com.utils.cssTag</tag-class>
 	<bodycontent>empty</bodycontent>
 	<attribute>
      <name>cssHref</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
 </tag>
 
</taglib>

上面的意思我还不太明白,等我懂了再过来更新,只知道这样配置,不好意思。

       

<jsp-config>
    <!-- 自定义 tag -->
	<taglib>
	   <taglib-uri>/tags</taglib-uri>
	   <taglib-location>/WEB-INF/tld/tag.tld</taglib-location>
	</taglib>
</jsp-config>

上头这点东西在web.xml里加上即可。

上面这些就完成了一大半,剩下的工作就是在前台用了。

<script type="text/javascript" src="/res/js/index.js"></script>

原来是上面这种样子。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="js" uri="/tags"%>
<c:set var="staticResource" value="${staticResource}"/>

在jsp中配好自己需要的变量。

<js:js jsSrc="${staticResource['/res/js/index.js']}" />

用以上的代码替换原来的格式,就ok!
效果如下:

<script src="/res/js/index.js?ver=20131218143453" type="text/javascript">

千万别喷我,我第一次写博客,还是胡歌建议的呢~
下班了,如果有不明白的我有空再解释给大家,写的应该不是很明白,呵呵。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值