[TOC]
一、 缘起
编写java agent插件的时候,用到javassist修改字节码,插件用来记录调用链的,需要在方法的前后插入代码。
突发奇想,用来看看javassist是怎么调用的,结果达不到预期效果,因为java agent中,javassist的代码已经加载过了,
没插入记录调用链的代码,刚好看到guava中有介绍用maven-shade-plugin将guava repackage重命名包名,因此记录下。
二、maven-shade-plugin介绍
maven-shade-plugin是一个maven打包插件,提供的功能比较丰富,使用也简单易懂。
1、简单打包
简单打包只需要增加execution, 指定执行package的phase,为这个phase绑定global shade就ok
1 2 3 4 5 6 7 8 9 10 11 12 13
| <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>
|
2、打包可运行的jar
增加configuration, 添加ManifestResourceTransformer的transformer,指定main入口的mainClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.1.0</version> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>org.demo.App</mainClass> </transformer> </transformers> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>
|
3、打包第三方jar包和排除第三方jar包
configuration下增加artifactSet,includes添加需要增加的第三方maven依赖,excludes排除不需要打包进来的第三方依赖,
include和exclude的标签里格式是maven的坐标和类型等, 格式:groupId:artifactId[[:type]:classifier],type可以是jar、war、pom,
这里需要注意的是scope是test、provided的话,是无法include进来的,compile(默认)、runtime会被包含进来。
1 2 3 4 5 6 7 8 9 10 11
| <configuration> <artifactSet> <includes> <include>*:*</include> </includes> <excludes> <exclude>org.projectlombok:lombok</exclude> </excludes> </artifactSet> ... </configuration>
|
也可以过滤第三方包中,指定那些文件打包进来,那些不打包。
configuration下增加filters, filter说明过滤的条件和信息,include和exclude注意是文件路径,不是包路径。
配置的每个filter,如果只配置了include,其他都会被exclude
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <configuration> <filters> <filter> <artifact>javax.servlet.jsp:jsp-api</artifact> <includes> <include>javax/servlet/jsp/**</include> </includes> <excludes> <exclude>javax/servlet/jsp/tagext/**</exclude> </excludes> </filter> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/NOTICE.txt</exclude> </excludes> </filter> </filters> ... </configuration>
|
4、第三方包的包路径重命名
可以通过relocations,将依赖的第三方包打包到jar包中,并且重命名类的包名,可以达到隔离第三方包、解决包冲突等功能。
如果有不需要导入的,可以用exclude排除掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <configuration> <artifactSet> <includes> <include>org.javassist:javassist</include> </includes> </artifactSet> <relocations> <relocation> <pattern>javassist</pattern> <shadedPattern>org.demo.javassist</shadedPattern>
</relocation> </relocations> ... </configuration>
|
5、其他配置
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<finalName>${project.name}-${project.version}</finalName>
<minimizeJar>false</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<createSourcesJar>false</createSourcesJar>
<shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>suffix</shadedClassifierName>
|
三、maven-shade-plugin实战
把官网的例子和网上一些文章的例子试验了一下。
其实,主要用到的应该是基本打包功能,jar包命名,ManifestResourceTransformer,这些功能其他打包插件也可以做得到。
relocation功能比较使用,引入第三方包有特殊需求的时候,比如隔离和避免版本冲突,可以用该功能解决。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>org.demo</groupId> <artifactId>maven-shade-plugin-demo</artifactId> <version>1.0-SNAPSHOT</version>
<name>maven-shade-plugin-demo</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.28</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.60</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.24.1-GA</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.6.RELEASE</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.1</version> <configuration> <finalName>${project.name}-${project.version}</finalName> <minimizeJar>false</minimizeJar> <createDependencyReducedPom>false</createDependencyReducedPom> <createSourcesJar>false</createSourcesJar> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>suffix</shadedClassifierName> <filters> <filter> <artifact>javax.servlet.jsp:jsp-api</artifact> <includes> <include>javax/servlet/jsp/**</include> </includes> <excludes> <exclude>javax/servlet/jsp/tagext/**</exclude> </excludes> </filter> <filter> <artifact>*:*</artifact>
<excludes> <exclude>META-INF/NOTICE.txt</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <artifactSet> <includes> <include>*:*</include> </includes> <excludes> <exclude>org.projectlombok:lombok</exclude> </excludes> </artifactSet> <relocations> <relocation> <pattern>javassist</pattern> <shadedPattern>org.demo.javassist</shadedPattern> </relocation> </relocations> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>org.demo.App</mainClass> <manifestEntries> <Premain-Class>org.demo.agent.Agent</Premain-Class> <Agent-Class>org.demo.agent.Agent</Agent-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> <Can-Set-Native-Method-Prefix>true</Can-Set-Native-Method-Prefix> </manifestEntries> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer"> <resource>META-INF/magic.xml</resource>
</transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ResourceBundleAppendingTransformer"> <basename>path/to/Messages</basename> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer"> <resources> <resource>.txt</resource> <resource>READ.me</resource> </resources> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer"> <resource>META-INF/README</resource> <file>ReadMe.file</file> </transformer> </transformers> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
|