maven打包后pom.properties中的注释问题

探讨Maven打包过程中生成的pom.properties文件内时间戳导致的问题,及如何通过代码改进来解决此问题,确保同一源码生成相同包。

使用maven打包后,在META-INF目录下会生成pom.properties文件(当然可以使其不生成)。这个文件包含了包的Id信息,此外它最开始有两行注释,看起来是这样的

#Generated by Maven
#Sat Jun 25 09:40:37 CST 2016

 第一行 是固定的,第二行是打包时候的时间戳。

第二行的存在有一个严重的问题,就是我们完全不修改代码,然后两次打包由于时间戳不一样,导致生成的两个包不一样。如果你不在乎可能觉得没有什么,但是对于大型项目,代码没变包却不同导致不能进行增量部署。

这个代码的出现是由于java.util.Properties类的store(Writer writer, String comments)方法中有一行

bw.write("#" + new Date().toString());

 这个问题在困扰大家的同时,也困扰着Maven的开发者。与之相关的有两个issue:

MSHARED-494

MSHARED-505

maven人员郁闷的说

Oracle's implementation of store() does write the stupid new Date().toString()

 由于大家需求强烈,目前该特性据说已被修正。

在今年5月21号提交的代码中,时间这一行注释被移除了:移除方法是把生成后的文件对行迭代,看到是注释就删除。

Stupid hack: write the properties to a StringWriter, 
iterate with a BufferedReader and drop all comments, 
finall write real content to the target file.

 我们看一下中心库中的版本和时间:



 3.0.x版本最晚是4月份提交的,所以它不包含这个改动。3.1.x最早是6月份提交的,现在已经有两个小版本了,但是引用次数还是0.

我们对比一下3.0和3.1中的代码。首先是3.0.2中的:

75 	    private void createPropertiesFile( MavenSession session, Properties properties, File outputFile,
76 	                                       boolean forceCreation )
77 	        throws IOException
78 	    {
79 	        File outputDir = outputFile.getParentFile();
80 	        if ( outputDir != null && !outputDir.isDirectory() && !outputDir.mkdirs() )
81 	        {
82 	            throw new IOException( "Failed to create directory: " + outputDir );
83 	        }
84 	        if ( !forceCreation && sameContents( properties, outputFile ) )
85 	        {
86 	            return;
87 	        }
88 	        OutputStream os = new FileOutputStream( outputFile );
89 	        try
90 	        {
91 	            String createdBy = CREATED_BY_MAVEN;
92 	            if ( session != null ) // can be null due to API backwards compatibility
93 	            {
94 	                String mavenVersion = session.getSystemProperties().getProperty( "maven.version" );
95 	                if ( mavenVersion != null )
96 	                {
97 	                    createdBy += " " + mavenVersion;
98 	                }
99 	            }
100 	
101 	            properties.store( os, createdBy );
102 	            os.close(); // stream is flushed but not closed by Properties.store()
103 	            os = null;
104 	        }
105 	        finally
106 	        {
107 	            IOUtil.close( os );
108 	        }
109 	    }

 

 下面是3.1.1的(左边是在文件内的行号):

77          private void createPropertiesFile( MavenSession session, Properties properties, File outputFile,
78 	                                       boolean forceCreation )
79 	        throws IOException
80 	    {
81 	        File outputDir = outputFile.getParentFile();
82 	        if ( outputDir != null && !outputDir.isDirectory() && !outputDir.mkdirs() )
83 	        {
84 	            throw new IOException( "Failed to create directory: " + outputDir );
85 	        }
86 	        if ( !forceCreation && sameContents( properties, outputFile ) )
87 	        {
88 	            return;
89 	        }
90 	        PrintWriter pw = new PrintWriter( outputFile, "ISO-8859-1" );
91 	        try
92 	        {
93 	            String createdBy = CREATED_BY_MAVEN;
94 	            if ( session != null ) // can be null due to API backwards compatibility
95 	            {
96 	                String mavenVersion = session.getSystemProperties().getProperty( "maven.version" );
97 	                if ( mavenVersion != null )
98 	                {
99 	                    createdBy += " " + mavenVersion;
100 	                }
101 	            }
102 	
103 	            StringWriter sw = new StringWriter();
104 	            properties.store( sw, null );
105 	
106 	            BufferedReader r = new BufferedReader( new StringReader( sw.toString() ) );
107 	
108 	            pw.println( "#" + createdBy );
109 	            String line;
110 	            while ( ( line = r.readLine() ) != null )
111 	            {
112 	                if ( !line.startsWith( "#" ) )
113 	                {
114 	                    pw.println( line );
115 	                }
116 	            }
117 	
118 	            r.close();
119 	            r = null;
120 	            sw.close();
121 	            sw = null;
122 	            pw.close();
123 	            pw = null;
124 	        }
125 	        finally
126 	        {
127 	            IOUtil.close( pw );
128 	        }
129 	    }

 这里主要是对注释的处理,正文内容的处理在方法public void createPomProperties()中。

下面版本比上面多了一个流程,就是临时变量sw写入后,再逐行读出来,不是注释就写入pw中(迭代前已经把maven信息写好了)。这样就把时间删掉了。

 

 

@ECHO OFF echo ^<?xml version="1.0" encoding="UTF-8"?^> > pom.xml echo ^<project xmlns="http://maven.apache.org/POM/4.0.0" >> pom.xml echo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >> pom.xml echo xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"^> >> pom.xml echo ^<modelVersion^>4.0.0^</modelVersion^> >> pom.xml echo ^<packaging^>pom^</packaging^> >> pom.xml echo ^<groupId^>com.tplink.smb.omada^</groupId^> >> pom.xml echo ^<artifactId^>omada^</artifactId^> >> pom.xml echo ^<version^>5.0.0^</version^> >> pom.xml echo ^<properties^> >> pom.xml echo ^<java.version^>1.8^</java.version^> >> pom.xml echo ^</properties^> >> pom.xml echo ^<modules^> >> pom.xml echo ^<module^>omada_sdn_controller_microservice^</module^>" >> pom.xml echo ^<module^>omada_web^</module^> >> pom.xml echo ^<module^>omada_api_gateway^</module^> >> pom.xml echo ^<module^>omada_client^</module^> >> pom.xml echo ^<module^>omada_components^</module^> >> pom.xml echo ^<module^>omada_device_gateway^</module^> >> pom.xml echo ^<module^>omada_identityaccess^</module^> >> pom.xml echo ^<module^>omada_log^</module^> >> pom.xml echo ^<module^>omada_manager^</module^> >> pom.xml echo ^<module^>omada_monitor^</module^> >> pom.xml echo ^<module^>omada_maintenance^</module^> >> pom.xml echo ^<module^>omada_starter^</module^> >> pom.xml echo ^<module^>omada_insight^</module^> >> pom.xml echo ^</modules^> >> pom.xml echo ^</project^> >> pom.xml SET JAVA_HOME=%java_path% echo %JAVA_HOME% "%JAVA_HOME%\bin\java.exe" -version SET PATH=%JAVA_HOME%/bin;%maven_path%;%PATH% echo %PATH% call mvn -v REM 运行sonarqube分析 REM %maven_path%mvn.cmd clean verify -Plocal-build -Prelease-win -Psmb-nexus -Dmaven.test.skip=true org.sonarsource.scanner.maven:sonar-maven-plugin:3.11.0.3922:sonar -Dsonar.scm.disabled=true -#Dsonar.projectKey=win_%version% -Dsonar.projectName=win_%version% -Dsonar.host.url=http://10.42.20.74 -Dsonar.token=2c0b2622199955495c5e478acac658353bbcaa14 -pl !omada_web REM 强制刷新parent REM cd omada_sdn_controller_microservice REM %maven_path%mvn.cmd install REM cd .. echo Skip_Web=%Skip_Web% IF "%Skip_Web%"=="true" ( %maven_path%mvn.cmd clean install -Plocal-build -Prelease-win -Poversea -Psmb-nexus -Dmaven.test.skip=true -U -T1C -pl !omada_web ) else ( %maven_path%mvn.cmd clean install -Plocal-build -Prelease-win -Poversea -Psmb-nexus -Dmaven.test.skip=true -U -T1C ) REM 拷贝到深圳-美国中转目录中,加速Windows安装包服务器下载 SET PACKAGE_PATH=Z:\windows_packages\omada-standard\%BUILD_NUMBER% MKDIR %PACKAGE_PATH% COPY omada_starter\local-starter\target\*.zip %PACKAGE_PATH% 这段代码什么意思
最新发布
10-28
这段代码是一个 **Windows 批处理脚本(`.bat` 文件)**,用于自动化构建一个基于 MavenJava 项目(很可能是 TP-Link Omada 控制器软件的某个版本)。它主要完成以下任务: 1. 自动生成一个 `pom.xml` 文件(Maven 项目的配置文件) 2. 设置 JavaMaven 环境变量 3. 构建项目(使用 Maven) 4. 可选地跳过 `omada_web` 模块 5. 将构建产物复制到指定共享目录 --- ### ✅ 逐行解释与功能分析 ```bat @ECHO OFF ``` > 关闭命令回显,运行时不显示每条命令本身,只输出 `echo` 显式打印的内容。 --- ```bat echo ^<?xml version="1.0" encoding="UTF-8"?^> > pom.xml ... echo ^</project^> >> pom.xml ``` > 使用 `echo` 命令逐行写入 XML 内容到 `pom.xml` 文件中。 > 因为 `<`, `>`, `&` 是批处理中的特殊字符,需要用 `^` 转义。 > 最终生成的是一个符合 Maven 标准的父级 `pom.xml`,包含: - 项目坐标:`groupId=com.tplink.smb.omada`, `artifactId=omada`, `version=5.0.0` - 打包类型:`pom` - Java 版本属性:`1.8` - 多个子模块(如 `omada_web`, `omada_api_gateway` 等) 📌 这说明这是一个 **多模块 Maven 项目**,所有子模块都在这个根项目下。 --- ```bat SET JAVA_HOME=%java_path% echo %JAVA_HOME% "%JAVA_HOME%\bin\java.exe" -version ``` > 设置 `JAVA_HOME` 环境变量为 `%java_path%`(这个变量应该在外部设置好了)。 > 然后输出并验证 Java 是否可用(打印版本信息)。 ⚠️ 注意:如果 `%java_path%` 没有定义,这一步会失败。 --- ```bat SET PATH=%JAVA_HOME%/bin;%maven_path%;%PATH% echo %PATH% ``` > 将 JavaMaven 的路径加入系统 `PATH`,确保后续能调用 `java` 和 `mvn` 命令。 > `%maven_path%` 应该指向 Maven 的 `bin` 目录(例如 `C:\apache-maven-3.8.6\bin`) --- ```bat call mvn -v ``` > 调用 `mvn -v` 查看 Maven 版本,验证 Maven 安装是否成功,并确认当前使用的 Java 版本。 --- ```bat REM 运行sonarqube分析 REM %maven_path%mvn.cmd clean verify ... ``` > 注释掉的一段 SonarQube 静态代码扫描命令。 > 如果启用,会将代码推送到 SonarQube 服务器进行质量检测。 示例参数含义: - `-Dsonar.host.url=http://10.42.20.74`:SonarQube 地址 - `-Dsonar.token=...`:认证 Token - `-pl !omada_web`:排除 `omada_web` 模块 - `-Dsonar.scm.disabled=true`:禁用 SCM(避免 Git 问题) --- ```bat REM 强制刷新parent REM cd omada_sdn_controller_microservice REM %maven_path%mvn.cmd install REM cd .. ``` > 注释掉的部分表示:进入某个子模块并执行 `mvn install` 来安装本地依赖。 > 通常用于确保父 POM 或某个核心模块已安装到本地仓库。 --- ```bat echo Skip_Web=%Skip_Web% IF "%Skip_Web%"=="true" ( %maven_path%mvn.cmd clean install -Plocal-build -Prelease-win -Poversea -Psmb-nexus -Dmaven.test.skip=true -U -T1C -pl !omada_web ) else ( %maven_path%mvn.cmd clean install -Plocal-build -Prelease-win -Poversea -Psmb-nexus -Dmaven.test.skip=true -U -T1C ) ``` > 判断环境变量 `Skip_Web` 是否为 `"true"`: - 如果是 → 构建时 **排除 `omada_web` 模块** - 否则 → 构建全部模块 📌 Maven 参数详解: | 参数 | 含义 | |------|------| | `clean install` | 清理旧输出并安装到本地仓库 | | `-Pxxx` | 激活指定的 Profile(构建配置)<br>`local-build`: 本地开发<br>`release-win`: Windows 发布<br>`oversea`: 海外版<br>`smb-nexus`: 使用公司 Nexus 私服 | | `-Dmaven.test.skip=true` | 跳过测试(加快构建速度) | | `-U` | 强制更新快照依赖 | | `-T1C` | 并行构建,每核一个线程(提升编译速度) | | `-pl !module` | 排除特定模块 | --- ```bat SET PACKAGE_PATH=Z:\windows_packages\omada-standard\%BUILD_NUMBER% MKDIR %PACKAGE_PATH% COPY omada_starter\local-starter\target\*.zip %PACKAGE_PATH% ``` > 设置打包路径为 `Z:\windows_packages\...\构建编号`,创建目录并将 `omada_starter` 模块生成的 ZIP 包拷贝过去。 📌 这是为了让其他团队或部署服务器可以快速获取最新构建产物(比如用于 CI/CD 或发布)。 --- ## ✅ 总结:这个脚本的作用 这是一个 **CI/CD 自动化构建脚本**,用于: 1. ✅ 动态生成统一的 `pom.xml`(标准化构建入口) 2. ✅ 设置 Java + Maven 环境 3. ✅ 编译整个多模块项目(可选跳过前端 web 模块) 4. ✅ 输出构建结果到网络共享路径(便于分发) 5.注释中)支持 Sonar 扫描和强制安装依赖 常用于 Jenkins、TeamCity 或本地一键构建场景。 --- ## 🔧 改进建议(可选优化) 1. 添加错误处理: ```bat if errorlevel 1 ( echo 构建失败! exit /b 1 ) ``` 2. 检查必要变量是否存在: ```bat if "%java_path%"=="" ( echo 错误:未设置 java_path exit /b 1 ) ``` 3. 使用完整路径调用 `mvn`,避免依赖 PATH: ```bat "%maven_path%\mvn.cmd" ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值