包含内容
- JAVA混淆
- JS、CSS文件压缩
- 项目版本号及相关版本信息自动设置
- 不同环境下配置文件修改
开发环境
项目:基于Spring、SpringMVC和JPA框架搭建。
Proguard:4.9,开源混乱器,支持脚本控制,可以使用GUI界面,重命名a-z A-Z等单个字符名称。字符串不加密,支持 J2ME。
Proguard插件:com.github.wvengen.proguard-maven-plugin.2.0.6
YUICompressor:基于Rhino 对JavaScript源文件进行分析和切词,可以是去掉JavaScript文件和Css文件中冗余的空白字符(空格,换行符,制表符),对于JavaScript文件还可以对其进行混淆,更改局部变量的名称;对于CSS,还有采用优化0值属性值的表示,优化颜色值的方法压缩文件;能够融合多个js或css文件为一个文件。
yuicompressor-maven-plugin:在maven中调用yuicompressor,参考页面:https://github.com/davidB/yuicompressor-maven-plugin。
maven-antrun-plugin:能够在maven中运行ant任务,例如:文件目录操作、文件内容替换等。参考页面:http://maven.apache.org/plugins/maven-antrun-plugin/index.html
参考信息
Maven core :http://maven.apache.org/ref/3.2.3/maven-core/,介绍maven生命周期等核心概念。
Maven中profile基本使用方法:http://lpyyn.iteye.com/blog/2110927
Maven Assembly:maven打包插件,http://maven.apache.org/plugins/maven-assembly-plugin/
Proguard插件资源库地址:http://repository.pentaho.org/artifactory/repo/
ant中任务命令参考:http://ant.apache.org/manual/Tasks/,ant命令分为task和type,task是直接可以运行的命令,而type是在task中属性信息。
混淆过程
在打包前混淆class类及相关依赖类,在打包时使用assembly插件重新打带混淆的war包。
具体实现过程如下:
1. 定义profile,在打包过程中可以根据参数选择正常打包或混淆打包。
2. 配置proguard插件。在package执行proguard目标。
3. 配置assembly插件。在package执行single命令。
4. 调用方式。在根项目路径下执行mvn clean package -Pobfuscate,在子项目的pom中如果存在id=obfuscate的profile,则执行profile中对应的内容,否则不执行。
5. 混淆后的类及内容示例如下。
pom.xml中的profile的内容如下:
<profiles> <profile> <id>obfuscate</id> <activation> <activeByDefault>false</activeByDefault> </activation> <pluginRepositories> <pluginRepository> <id>pentaho-releases2</id> <url>http://repository.pentaho.org/artifactory/repo/</url> </pluginRepository> </pluginRepositories> <build> <plugins> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.0.6</version> <executions> <execution> <phase>package</phase> <goals> <goal>proguard</goal> </goals> </execution> </executions> <configuration> <target>1.7</target> <encoding>UTF-8</encoding> <obfuscate>true</obfuscate> <injar>classes</injar> <outjar>obfuscate-classes</outjar> <proguardInclude>${basedir}/proguard.pro</proguardInclude> <options> <option>-dontshrink</option> <option>-dontoptimize</option> <!-- 保存jar directories --> <option>-keepdirectories</option> <!-- 保留注解 --> <option>-keepattributes **</option> </options> <assembly> <inclusions> <inclusion> <groupId>com.projects.synergy</groupId> <artifactId>synergy-common</artifactId> </inclusion> <inclusion> <groupId>com.projects.synergy</groupId> <artifactId>synergy-system</artifactId> </inclusion> <inclusion> <groupId>com.projects.synergy</groupId> <artifactId>synergy-wfmservice</artifactId> </inclusion> </inclusions> </assembly> <libs> <lib>${java.home}\lib\rt.jar</lib> <lib>${java.home}\lib\jsse.jar</lib> </libs> </configuration> <dependencies> <dependency> <groupId>net.sf.proguard</groupId> <artifactId>proguard</artifactId> <version>4.9</version> <scope>runtime</scope> </dependency> </dependencies> </plugin> <!-- 使用target\${project.build.finalName}文件夹下的内容进行压缩,避免修改源文件--> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>yuicompressor-maven-plugin</artifactId> <version>1.4.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>compress</goal> </goals> </execution> </executions> <configuration> <encoding>UTF-8</encoding> <!-- 不显示js文件中的错误信息 --> <jswarn>false</jswarn> <!-- 不带压缩后缀 --> <nosuffix>true</nosuffix> <!-- 只压缩,不混淆 --> <nomunge>false</nomunge> <!-- js文件的目录,默认为src\main\js --> <sourceDirectory>${project.build.directory}\${project.build.finalName}</sourceDirectory> <!-- 不包括没有被压缩的文件 --> <excludes> <exclude>**/*min.js</exclude> <exclude>**/*min.css</exclude> </excludes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.7</version> <executions> <execution> <id>prepare-package-antrun</id> <phase>prepare-package</phase> <configuration> <!--在控制台提示输入当前的版本号信息,并根据输入的版本号替换jsp页面中相关版本信息--> <target name="get new version"> <input addproperty="new.verion" defaultvalue="1.0.0">please input the new project version,default version is : </input> <!-- 创建临时文件存储输入的版本号信息 --> <propertyfile file="${project.build.directory}\version.properties"> <entry key="new.verion" value="${new.verion}"/> </propertyfile> <!-- 替换掉整个项目中jsp页面中的版本号 --> <replaceregexp match="COMPANY V\d+(\.\d+)*" replace="COMPANY V${new.verion}" flags="g" encoding="utf-8"> <fileset dir="${basedir}" includes="**/*.jsp *.jsp"/> </replaceregexp> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> <execution> <phase>package</phase> <configuration> <!-- 所有的ant任务必须在target中执行 --> <target name="replace js file content and rename aggregate file."> <!-- 替换js文件中使用ajax加载js文件的操作 --> <replaceregexp match="UtilMisc\.loadJS\(\S*\);" replace="" flags="g" encoding="utf-8"> <fileset dir="${project.build.directory}\${project.build.finalName}" includes="**/*.js *.js"/> </replaceregexp> <!-- 合并js文件,删除合并前的js子文件--> <concat destfile="${project.build.directory}\${project.build.finalName}\resources\general\core\adstaffairs\synergy.adstaffairs.js" encoding="utf-8" outputencoding="utf-8" fixlastline="true" append="true"> <fileset dir="${project.build.directory}\${project.build.finalName}\resources\general\core\adstaffairs" includes="**/*.js *.js" excludes="synergy.adstaffairs.js"/> </concat> <delete dir="${project.build.directory}\${project.build.finalName}\resources\general\core\adstaffairs" includeemptydirs="true" includes="**/*.js *.js" excludes="synergy.adstaffairs.js"/> <concat destfile="${project.build.directory}\${project.build.finalName}\resources\general\core\docmanage\synergy.docmanage.js" encoding="utf-8" outputencoding="utf-8" fixlastline="true" append="true"> <fileset dir="${project.build.directory}\${project.build.finalName}\resources\general\core\docmanage" includes="**/*.js *.js" excludes="synergy.docmanage.js"/> </concat> <delete dir="${project.build.directory}\${project.build.finalName}\resources\general\core\docmanage" includeemptydirs="true" includes="**/*.js *.js" excludes="synergy.docmanage.js"/> <!-- 读取版本信息 --> <property file="${project.build.directory}\version.properties"></property> <echo message="war包版本信息->${new.verion}"/> <!-- 替换掉整个项目pom文件中的版本号信息 --> <replaceregexp match="<synergy.version>\d+(\.\d+)*</synergy.version>" replace="<synergy.version>${new.verion}</synergy.version>" flags="g" encoding="utf-8"> <fileset dir="${basedir}\..\" includes="**/pom.xml pom.xml"/> </replaceregexp> <!-- 替换掉target中生成文件中的版本号 --> <move file="${project.build.directory}" todir="" encoding="utf-8" outputencoding="utf-8"> <fileset dir="${project.build.directory}" includes="**/*"> <depth max="1"/> </fileset> <mapper type="glob" from="*-${project.version}.war" to="*-${new.verion}.war"/> </move> <!-- 删除临时文件版本号信息 --> <delete file="${project.build.directory}\version.properties"/> <!-- 删除默认生成的war包,避免和新生成的混淆war包重名 --> <delete file="${project.build.directory}\${project.artifactId}.war"/> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> <!--最终的war包名称不包括版本号信息--> <finalName>${project.artifactId}-obfuscated</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>obfuscate_war.xml</descriptor> </descriptors> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile> <profile> <id>test</id> <activation> <activeByDefault>false</activeByDefault> </activation> <build> <plugins> <plugin> <groupId>com.juvenxu.portable-config-maven-plugin</groupId> <artifactId>portable-config-maven-plugin</artifactId> <version>1.1.5</version> <executions> <execution> <goals> <goal>replace-package</goal> </goals> </execution> </executions> <configuration> <portableConfig>${basedir}/test.xml</portableConfig> </configuration> </plugin> </plugins> <!-- 指定finalName,否则portable-config-maven-plugin会寻找默认带版本号的war包 --> <finalName>${project.artifactId}</finalName> </build> </profile> <profile> <id>production</id> <activation> <activeByDefault>false</activeByDefault> </activation> <build> <plugins> <plugin> <groupId>com.juvenxu.portable-config-maven-plugin</groupId> <artifactId>portable-config-maven-plugin</artifactId> <version>1.1.5</version> <executions> <execution> <goals> <goal>replace-package</goal> </goals> </execution> </executions> <configuration> <portableConfig>${basedir}/production.xml</portableConfig> </configuration> </plugin> </plugins> <!-- 指定finalName,否则portable-config-maven-plugin会寻找默认带版本号的war包 --> <finalName>${project.artifactId}</finalName> </build> </profile> </profiles>
proguard.pro配置信息
-keeppackagenames **.web,**.entity,**.dao,**.generator,**.timertask,**.interceptor,**.tag,**.system,**.wfmservice,**.common -keep class **.web.**{*;} -keep class **.entity.**{*;} -keep class **.dao.**{*;} -keep class **.timertask.**{*;} -keep class **.interceptor.**{*;} -keep class **.generator.**{*;} -keep class **.tag.**{*;} -keep class **.common.**{*;} -keep class **.system.**{*;} -keep class **.wfmservice.**{*;} -keepclassmembers class **.dao.** { <fields>; <methods>; } -keepclassmembers class **.web.** { <fields>; <methods>; } -keepclassmembers class **.entity.** { <fields>; <methods>; } -keepclassmembers class **.timertask.** { <fields>; <methods>; } -keepclassmembers class **.interceptor.** { <fields>; <methods>; } -keepclassmembers class **.generator.** { <fields>; <methods>; } -keepclassmembers class **.tag.** { <fields>; <methods>; } -keepclassmembers class **.system.** { <fields>; <methods>; } -keepclassmembers class **.common.** { <fields>; <methods>; } -keepclassmembers class **.wfmservice.** { <fields>; <methods>; }
-keeppackagenames:需要保留的包列表。
-keep:需要保留的类。
-keepclassmembers:需要保留的类成员信息。
对于当前项目来说,需要保留类包括实体类(保存与数据库的映射)、Dao类(使用JPA,需要按规则定义方法名)、Controller类(@requestParam等注解根据变量名称映射变量值)以及其它在配置文件中显式声明的类。
<?xml version="1.0" encoding="UTF-8"?> <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> <id>package_project</id> <formats> <format>war</format> </formats> <!-- war包中不包括项目根目录名称 --> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <!-- 不包括当前项目已构建的包 --> <useProjectArtifact>false</useProjectArtifact> <!-- 不包括jar包依赖,使用混淆后的依赖 --> <excludes> <exclude>com.projects.synergy:synergy-common</exclude> <exclude>com.projects.synergy:synergy-system</exclude> <exclude>com.projects.synergy:synergy-wfmservice</exclude> </excludes> <outputDirectory>WEB-INF\lib</outputDirectory> </dependencySet> </dependencySets> <fileSets> <!-- 拷贝当前项目中的混淆的class类 --> <fileSet> <directory>\target\obfuscate-classes\</directory> <outputDirectory>WEB-INF\classes</outputDirectory> <excludes> <exclude>*.jar</exclude> </excludes> </fileSet> <!-- 拷贝当前项目混淆后的依赖类 --> <fileSet> <directory>\target\obfuscate-classes\</directory> <outputDirectory>WEB-INF\lib</outputDirectory> <includes> <include>*.jar</include> </includes> </fileSet> <!-- 从\target\${project.build.finalName}中拷贝出来jar包和classes类之外的内容 --> <fileSet> <directory>\target\${project.build.finalName}\</directory> <outputDirectory></outputDirectory> <excludes> <exclude>\WEB-INF\lib\**</exclude> <exclude>\WEB-INF\classes\**</exclude> </excludes> </fileSet> </fileSets> </assembly>
<profile> <id>test</id> <activation> <activeByDefault>false</activeByDefault> </activation> <build> <plugins> <plugin> <groupId>com.juvenxu.portable-config-maven-plugin</groupId> <artifactId>portable-config-maven-plugin</artifactId> <version>1.1.5</version> <executions> <execution> <goals> <goal>replace-package</goal> </goals> </execution> </executions> <configuration> <portableConfig>${basedir}/test.xml</portableConfig> </configuration> </plugin> </plugins> <!-- 指定finalName,否则portable-config-maven-plugin会寻找默认带版本号的war包 --> <finalName>${project.artifactId}</finalName> </build> </profile>在配置过程中遇到问题总结:
-dontshrink -dontoptimize2. 为了能够保存所有Spring的注解,并且能够使Spring能够扫描到jar中的class类,分别加入以下两条命令。
-keepattributes ** -keepdirectories3. 混淆后的Class类虽然位于不同的包下,但是可能会出现重名的情况,而使用Spring注解,id默认和类名相同,就可能会出现id冲突,因此默认id改为类的完整路径,通过在spring扫描时设置name-generator属性实现。
<context:component-scan base-package="com" name-generator="com.projects.synergy.common.generator.AnnotationFullBeanNameGenerator" > </context:component-scan>AnnotationFullBeanNameGenerator继承默认的注解id生成类AnnotationBeanNameGenerator,并覆盖了默认id生成方法buildDefaultBeanName,内容如下:
package com.projects.synergy.common.generator; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.AnnotationBeanNameGenerator; public class AnnotationFullBeanNameGenerator extends AnnotationBeanNameGenerator { @Override protected String buildDefaultBeanName(BeanDefinition definition) { return definition.getBeanClassName(); } }4. com.github.wvengen.proguard-maven-plugin.2.06.jar在maven中央库中不存在,需要从库:http://repository.pentaho.org/artifactory/repo/中下载,因此需要设置插件库地址。
<!--创建properties文件--> <propertyfile file="${project.build.directory}\version.properties"> <entry key="new.verion" value="${new.verion}"/> </propertyfile> <!--读取properties文件--> <property file="${project.build.directory}\version.properties"></property>13. 现在已经将产品配置文件和混淆的过程分开,分别对应不同的profile,既可以在产品中进行混淆也可以在产品中不混淆。但是在pom.xml中必须将产品的profile放到混淆的profile之后,执行命令时也必须首先声明混淆再声明产品,即clean package -Dmaven.test.skip=true -Pobfuscate -Pproduction。
相关推荐
然而,当多个项目或产品之间存在相互依赖时,如果不正确地管理这些依赖,可能会导致各种问题,如资源冲突和版本不一致,这正是"关于项目、产品maven依赖问题"所涉及的关键点。 1. 问题阐述: 在一个典型的多项目...
- **lib**:包含Maven运行所需的各类库文件,包括JARs,这些库支持Maven的内部功能和插件执行。 4. **使用Maven进行项目构建** - `mvn clean`:清除目标目录,删除编译生成的文件。 - `mvn compile`:编译源代码...
Apache Maven 是一个强大的Java项目管理和综合工具,它简化了构建过程,通过标准化项目结构和自动化构建生命周期。在本文中,我们将深入探讨Maven的核心概念、安装步骤以及如何在实际项目中使用它。 **Maven核心...
Maven 使用一种标准化的项目对象模型(Project Object Model,POM),使得构建过程更加规范和可重复。在“apache-maven-3.3.3.zip”这个压缩包中,包含了Maven 3.3.3版本的完整安装文件。 Maven的核心概念之一是POM...
Java项目的自动化构建、打包和部署是现代开发流程中的重要环节,极大地提高了开发效率和产品质量。在本项目中,我们利用Jenkins、Maven、Gitlab和Tomcat这四个工具实现了一个完整的自动化工作流。 首先,让我们来...
2. **构建工具**:Maven提供了统一的构建生命周期,包括清理、编译、测试、打包、集成测试、部署等阶段,使得项目构建过程标准化。 3. **插件系统**:Maven通过插件机制来执行各种任务,如编译源代码、运行测试、...
Maven 支持多模块项目的构建,方便版本控制和模块间的依赖。 5. **站点生成(Site Generation)** Maven 提供了内置的站点生成机制,可以生成项目文档和报告。 ### Maven2 的使用步骤 1. **安装 Maven** 下载 ...
在Eclipse 3.7中,可以通过“New -> Dynamic Web Project”创建一个Maven Web应用程序,然后在项目属性中配置Maven支持,添加`maven-war-plugin`以完成web应用的构建。 **4. 生命周期** 4.1 三套生命周期 Maven有...
同时,Maven生命周期和构建阶段的设定,使得构建过程标准化,比如clean、compile、test、package、install和deploy等,这些阶段清晰地定义了从源码到可部署产品的整个流程。 在插件方面,Maven拥有丰富的生态,如...
Maven3+mybatis3+dwr3+mysql5.5,请用Chrome浏览器,兼容性还未调试。 自己写的一个小系统,包含一个模块:产品模块。 基本这个模块包括的内容就比较多了,CRUD,无刷新查询,图片上传等, 其实也是整个系统最复杂的...
Maven与持续集成工具如Jenkins、GitLab CI/CD等结合,可以实现自动化构建、测试和部署,提高开发效率和产品质量。 总结来说,Maven作为Java开发中的重要工具,通过标准化的项目管理方式,简化了项目构建过程,降低...
**Maven实用指南中文版**,作为Java开发者必备的构建工具,Maven简化了项目管理和构建过程,使得依赖管理、构建脚本以及项目信息管理变得标准化。本指南将深入探讨Maven的核心概念、配置和使用技巧,帮助你快速上手...
10. **持续集成**: Maven与Jenkins、Travis CI等持续集成工具结合,可以实现自动化构建和测试,提高开发效率和产品质量。 11. **版本控制**: Maven的版本控制系统可以帮助开发者跟踪和管理项目的版本,确保团队成员...
Maven与持续集成工具如Jenkins、GitLab CI/CD等配合良好,能够自动化构建、测试和部署流程,提升开发效率和产品质量。 总之,《Maven权威指南中文完整版清晰》全面涵盖了Maven的各个方面,无论是初学者还是有经验...
Apache Maven 是一个强大的Java项目管理工具,它极大地简化了项目的构建、依赖管理和...无论是小型项目还是大型企业级应用,Maven都能够提供强大的支持,使得开发者可以更加专注于业务逻辑的实现,而非项目构建的琐事。
开发者只需输入项目的基本信息,如Group Id(产品标识)、Artifact Id(项目ID)、Version(版本号)等,Eclipse将自动生成符合Maven约定的项目结构和配置文件。 总的来说,Maven是一个强大的工具,它通过自动化和...
Maven支持POM的继承,允许父POM定义共有的配置,子项目可以通过继承父POM来复用这些配置,简化项目结构。 总结,Maven通过其生命周期、POM和仓库机制,为Java项目提供了统一的构建流程,极大地提升了开发效率和...