学习笔记:Maven构造版本号的方法解决浏览器缓存问题

需要解决的问题

  在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js、css、图片之类)缓存。但也正因为这个问题导致一个问题,就是资源的缓存逻辑有时出现问题后服务器的最新版本文件无法更新客户端的缓存。

  这个问题会给用户产生许多的困扰,当然首先是测试人员会很头痛,一些看起来没有修复的bug为什么开发要说做好了?这种时候我会无奈的说:ctrl+f5刷新一下。但这毕竟不是解决问题的方法。

思路与方法考虑

思路

  之前没有着手处理过这样的问题,只是知道缓存可以通过时间戳、版本戳的方式来解决。说白了就是让link的url不一样浏览器自然会下载最新版本,想想这不是挺容易的事情嘛。项目紧也就没当回事,等有时间了再来解决这个问题。

  好了,最近有时间了开始解决。找了许多的方法,发现这确实是简单的加一个版本号/时间戳就能解决:

<link rel="stylesheet" type="text/css" href="/css/common.css?ver=${sysVersion}" />

上面代码中在资源后面加了一个?ver=${sysVersion}

注:项目中使用的是velocity,所以${sysVersion}是指velocity中的变量。

新的问题

  但一个新问题产生,我们是使用hudsun+maven来进行构造并自动发布及部署到web服务器上。那么我们如何在maven构造时打上一个版本戳呢?

方法

  1. 通过某种方法生成一个版本号写入到文件,系统启动时加载此版本号,这样velocity就能够使用这个版本号从而解决缓存更新的问题。这种就是单一的统一版本号方法。
  2. 通过前端的编译工具,grunt、F.I.S这类工具来完成,特别是F.I.S可以实现md5戳的模式,直接针对单个资源进行版本更新,这样就比较精确也最大化了缓存的作用。

最后还是选择了第一种方法,因为集成前端编译工具的方法我没有搞定T_T,原因:

1、F.I.S需要基于Node.js,这个又要配置许多东西,有点麻烦,当我自己搭建环境就反复了许多天,后来发现是网络墙原因。

2、另外由于项目做的不是很规范,所以F.I.S生成时需要改动比较多的代码,这个是我这种懒人不太愿意做的

于是先用简单的方法解决之,最后经过1天的配置也确实完成了。

采用最简单的单一版本号

单一的版本号一下子就简化了解决问题的难度,只要想办法在发布时生成一个版本号即可,那就不管是时间、数字或者其他什么,所有的资源都引用此版本号即可。找到了一个maven的插件:maven-svn-revision-number-plugin,这个插件可以获取svn的版本号用作build号,这样的好处就是只要有代码提交就会有新版本产生。插件的代码如下:

          <plugin>
              <groupId>com.google.code.maven-svn-revision-number-plugin</groupId>
              <artifactId>maven-svn-revision-number-plugin</artifactId>
              <version>1.7</version>
              <configuration>
                  <verbose>true</verbose>
                  <entries>
                      <entry>
                          <prefix>prefix</prefix><!-- 版本戳的前缀-->
                          <depth>empty</depth>
                      </entry>
                  </entries>
              </configuration>
              <executions>
                  <execution>
                      <phase>validate</phase><!-- 生命周期阶段-->
                      <goals>
                          <goal>revision</goal>
                      </goals>
                  </execution>
              </executions>
              <dependencies>
                  <dependency>
                    <groupId>org.tmatesoft.svnkit</groupId><!-- 由于使用的是svn1.8版本,所以需要依赖这个插件-->
                    <artifactId>svnkit</artifactId>
                    <version>1.8.9</version>
                  </dependency>
              </dependencies>
          </plugin>  

这个插件的作用是在maven构造时获取最新的svn版本号,然后利用maven的resources的filtering来在各个配置文件中作用变量使用。这样就实现了构造时将版本号写入文件。

resources的代码:

      <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**.properties</include><!-- 只对properties文件进行处理-->
            </includes>
            <filtering>true</filtering><!-- 表示开启变量嵌入 -->
        </resource>
        <resource>
            <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**.properties</exclude>
                </excludes>
            <filtering>false</filtering>
        </resource>
      </resources>

因为使用properties文件作为载体,所以上述的设置目的就是找到properties文件然后写入版本号,我建了一个build_version.properties文件,里面写了一个设置项:

build.version=${prefix.committedRevision}
${prefix.committedRevision}就可以获取maven-svn-revision-number-plugin插件生成的版本号。

这样设置好了后,使用Maven install就可以看到效果了,构造后在target目录找到build_version.properties文件查看内容:
build.version=114912

此时就变成了一个数字。

在此看一看maven-svn-revision-number-plugin插件中会产生哪些变量:

[INFO] --- maven-svn-revision-number-plugin:1.7:revision (default) @ zrtc ---
[INFO] inspecting E:\workspace\web
[INFO]   prefix = prefix
[INFO]   depth = empty
[INFO]   report unversioned = true
[INFO]   report ignored = false
[INFO]   report out-of-date = false
[INFO]  collecting status information
[INFO]       114969 114912 E:\workspace\web
[INFO]  setting properties
[INFO]   prefix.repository =
[INFO]   prefix.path =
[INFO]   prefix.revision = 114969
[INFO]   prefix.mixedRevisions = false
[INFO]   prefix.committedRevision = 114912
[INFO]   prefix.committedDate = 2015-10-23 09:03:39 +0800 (Fri, 23 Oct 2015)
[INFO]   prefix.status =
[INFO]   prefix.specialStatus = 

可以看到插件有几个变量,其中我使用了committedRevision,这个就是项目svn目录最后一次提交的版本。revision 则是svn最新的版本号。在其他文件使用时需要加上prefix.这个前缀,这是在配置文件中定义过的,可以看上面的配置内容。

<prefix>prefix</prefix><!-- 版本戳的前缀-->

这个前缀自己取名就可以了。

自此功能完成,解决了资源版本更新的问题。看看浏览器前端页面源代码:

<link rel="stylesheet" href="/css/h_login.css?ver=114912" type="text/css">

未来的目标

  最近因为解决前端客户端资源更新的问题也看到了一些更好的方法,比如F.I.S这种前端工程构建工具。在了解的过程中知道了一个前端工程化的概念,有些大,但确实是未来的一种发展趋势。在B/S开发越来越深入的阶段,浏览器+服务器的这种开发平台已经证明了其优越性,移动互联网、云计算都已经体现了这种发展趋势。而浏览器是最近10年人们用的最多的软件了吧?而且浏览器已经证明了其无所不能,基于HTML+CSS就可以实现无数美秒的界面,原先常见的商业系统都也搬到了B/S架构下。可见HTML是多么牛逼的开发平台。

  站在这个时代如果还不能做点和时代相关的事情是不是感觉有点过时?所以在未来要思考一下前端系统的模块化,最终实现工程化。

时间: 2024-12-21 13:37:13

学习笔记:Maven构造版本号的方法解决浏览器缓存问题的相关文章

Maven构造版本号的方法解决浏览器缓存问题

需要解决的问题 在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js.css.图片之类)缓存.但也正因为这个问题导致一个问题,就是资源的缓存逻辑有时出现问题后服务器的最新版本文件无法更新客户端的缓存. 这个问题会给用户产生许多的困扰,当然首先是测试人员会很头痛,一些看起来没有修复的bug为什么开发要说做好了?这种时候我会无奈的说:ctrl+f5刷新一下.但这毕竟不是解决问题的方法. 思路与方法考虑 思路 之前没有着手处理过这样的问题

学习笔记——Maven pom.xml配置详解

POM的全称是“ProjectObjectModel(项目对象模型)”. pom.xml详解 声明规范 <projectxmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apach

学习笔记——Maven实战(十)Maven 3,是时候升级了

去年10月份Apache Maven发布了3.0正式版,而在上个月的22号,Eclipse基金会宣布了Eclipse 3.7(Indigo)的发布,该版本Eclipse最大的新特性之一就是集成了Maven.下载Eclipse IDE for Java Developers版本的用户会发现,Eclipse已经能够自动识别Maven项目了.Indigo中内置的Maven版本是3.0.2,这在一定程度上说明Maven 3已经非常稳定了.不过我相信一定还有很多Maven 2用户在犹豫是否升级,本文会介绍

学习笔记——Maven实战(六)Gradle,构建工具的未来?

Maven面临的挑战 软件行业新旧交替的速度之快往往令人咂舌,不用多少时间,你就会发现曾经大红大紫的技术已经成为了昨日黄花,当然,Maven也不会例外.虽然目前它基本上是Java构建的事实标准,但我们也能看到新兴的工具在涌现,比如基于Goovy的Gradle,而去年Hibernate宣布从Maven迁移至Gradle这一事件更是吸引了不少眼球.在此之前,我也听到了不少对Maven的抱怨,包括XML的繁冗,不够灵活,学习曲线陡峭等等.那Gradle是否能够在继承 Maven优点的基础上,克服这些缺

jQuery源码学习笔记:构造jQuery对象

3.1源码结构: (function( window, undefined ) { var jQuery = (function() { // 构建jQuery对象 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); } // jQuery对象原型 jQuery.fn = jQuery.prototype = { constructor:

学习笔记——Maven 如何处理传递性依赖

maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖.但有时候,当传递性依赖造成问题的时候,我们就需要清楚地知道该传递性依赖是从哪条依赖路径引入的. 例如,项目A有这样的依赖关系 : A-->B-->C-->X(1.0).A-->D-->X(2.0),X是A的传递性依赖,但是两条依赖路径上有两个版 本的X,那么哪个X会被maven解析使用呢?两个版本都被解析显然是不

学习笔记——Maven超级POM

Maven有一个超级POM,所有的POM均继承此文件.该文件定义如下:<project>   <modelVersion>4.0.0</modelVersion>   <repositories>     <repository>       <id>central</id>       <name>Central Repository</name>       <url>http://

学习笔记——Maven settings.xml 配置详解

文件存放位置 全局配置: ${M2_HOME}/conf/settings.xml 用户配置: ${user.home}/.m2/settings.xml note:用户配置优先于全局配置.${user.home} 和和所有其他系统属性只能在3.0+版本上使用.请注意windows和Linux使用变量的区别. settings.xml详解 声明规范 <?xml version="1.0" encoding="UTF-8"?> <settings x

学习笔记——Maven实战(九)打包的技巧

“打包“这个词听起来比较土,比较正式的说法应该是”构建项目软件包“,具体说就是将项目中的各种文件,比如源代码.编译生成的字节码.配置文件.文档,按照规范的格式生成归档,最常见的当然就是JAR包和WAR包了,复杂点的例子是Maven官方下载页面的分发包,它有自定义的格式,方便用户直接解压后就在命令行使用.作为一款”打包工具“,Maven自然有义务帮助用户创建各种各样的包,规范的JAR包和WAR包自然不再话下,略微复杂的自定义打包格式也必须支持,本文就介绍一些常用的打包案例以及相关的实现方式,除了前