html关联js缓存版本解决方案

340 阅读1分钟

日常使用hml都知道,浏览器加载完页面后,页面不做任何缓存机制的处理话,会将静态数据缓存,下次打开速度就快很多,但平时涉及页面关联的js服务升级后,有可能关联的内容还是旧版本的,这个时候需要手动清除缓存。

换另一种思路,我们在页面生成的时候,关联的cssjs等资源文件加上一个版本号,则下次升级重启后,页面就会重新渲染新的版本信息,如下

<script src="~/jquery/jquery.cookie.js?v=20210817"></script>
<script src="~/js/base.js?v=20210817"></script>

解决思路

在后台通过过滤器,只过滤 html的资源文件,通过获取文件内容,替换以 css,js结尾的内容,对应的加上版本信息,参考代码如下:


import org.springframework.stereotype.Service;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * 浏览器缓存更新机制,服务每次重启都会动态生成一个版本号
 * 
 */
@Service
public class HttpCacheFilter extends GenericFilterBean {

   private String version = "";
   
   protected void initFilterBean() throws ServletException {
      String path = HttpCacheFilter.class.getClassLoader().getResource("").getPath();
      if(path.indexOf("jar!/BOOT-INF/") > 0){//jar包运行环境
         path = path.split("!/BOOT-INF/")[0];
         path = path.substring(path.indexOf("/") + 1);
         File file = new File(path);
         long modifytime = file.lastModified();
         Date modifydate = new Date(modifytime);
         
         SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmm");
         version = sdf.format(modifydate);
         
      }else{//开发环境直接使用当前时间
         SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmm");
         version = sdf.format(new Date());
      }
   }

   public void destroy() {

   }

   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      HttpServletRequest req = (HttpServletRequest) request;
      HttpServletResponse res = (HttpServletResponse) response;
      
      //通过版本号控制 start
      String HTTP_CACHE_ENABLE = SysConfig.getProperty("CACHE_ENABLE_CACHE_REPLACE", "1");
      if("1".equals(HTTP_CACHE_ENABLE)){
         ResponseWrapper wrapperResponse = new ResponseWrapper(res);//转换成代理类
         chain.doFilter(request, wrapperResponse);
         try{
            String contentType = wrapperResponse.getContentType();
            if(contentType != null && contentType.indexOf("html") > -1){
               String content = wrapperResponse.getContent();//获取返回值
               if(content != null){
                  content = content.replace(".js"", ".js?v="+version+""");
                  content = content.replace(".css"", ".css?v="+version+""");
                  byte outByte[] = content.getBytes(wrapperResponse.getCharacterEncoding());
                  wrapperResponse.setContentLength(outByte.length);
                  ServletOutputStream out = response.getOutputStream();
                     out.write(outByte);
                     out.flush();
               }
            }else{
               
               ServletOutputStream out = response.getOutputStream();
               out.write(wrapperResponse.getOriginalBuffer().toByteArray());
               out.flush();
            }
         }catch(Exception e){
            e.printStackTrace();
         }
      }else{
         chain.doFilter(request, res);
      }
      //通过版本号控制  end
      
   }

}