赞
踩
问题背景
maven-历史版本下载
https://archive.apache.org/dist/maven/maven-3/
Spring Boot 项目一般会依赖较多的包括 Spring 在内的第三方 jar 包,直接打可运行 jar 包,文件大小往往会达到100M甚至更大;
在重复部署测试或者生产环境的时候,每次都要上传包含所有依赖 jar 包的可运行 jar 文件,效率比较低;
期望目标
maven 配置,Spring Boot 项目打包时,只包含自己开发的代码,大小仅100kb,所依赖的第三方 jar 则复制到指定的目录下;
这样我们可以只需要上传一次第三方 jar,每次修改代码重新部署时,只上传仅包含我们开发代码的 jar 文件,大大提高了部署效率。
解决方法
maven 的 pom 配置如下,${} 变量根据自己的项目进行替换,第三方 jar 指定到 target/lib 目录下:
<plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <!-- 跳过单元测试 --> <skipTests>true</skipTests> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <!-- 复制第三方 jar 到项目目录下的 target/lib/ 下 --> <execution> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> <excludeScope>provided</excludeScope> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <!-- 指定 Spring Boot 启动类,实际测试中必须 --> <mainClass>${project.main.class}</mainClass> <!-- 将所有第三方 jar 添加到项目 jar 的 MANIFEST.MF 文件中,这样运行 jar 时依赖包才能被加载 --> <addClasspath>true</addClasspath> <!-- 指定复制第三方 jar 的目标目录为 target/lib/--> <classpathPrefix>./lib/</classpathPrefix> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <!-- repackage 时排除掉 第三方依赖 jar 文件,我们的可运行 Spring Boot 的 jar 文件瞬间变小 ^_^ --> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <includes> <include> <groupId>nothing</groupId> <artifactId>nothing</artifactId> </include> </includes> </configuration> </plugin> </plugins>
我们使用maven做一些日常的工作开发的时候,无非是想利用这个工具带来的一些便利。比如依赖管理,方便我们打包和部署运行。这里几个常见的插件就是和这些工程中常用的步骤相关。
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile (default-compile) on project springJMS: Compilation failure: Compilation failure:
[ERROR] /home/frank/programcode/SpringJMSSample/src/main/java/huangbowen/net/jms/MessageSender.java:[6,1] error: annotations are not supported in -source 1.3
[ERROR]
[ERROR] (use -source 5 or higher to enable annotations)
[ERROR] /home/frank/programcode/SpringJMSSample/src/main/java/net/EmbedBrokerApp.java:[5,7] error: static import declarations are not supported in -source 1.3
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
从错误显示的信息我们就可以看出,这是因为编译的时候是默认用的javac 1.3版本的,太老了不支持代码里的特性。为了修改这个问题,我们需要设置编译器的版本。解决这个问题的办法也比较简单,就是直接在后面的插件部分增加如下的插件,比如如下部分,将编译器的版本设定为1.6:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.yunzero.App</mainClass>
</configuration>
</plugin>
如果我们运行的时候需要提供一些输入的参数,也可以通过configuration的元素里添加。这样后续要执行这个程序时,我们只需要在命令行执行如下命令:mvn exec:java ,然后程序就可以运行起来了。
copy:将指定坐标对应的jar包拷贝到指定目录
unpack:将指定坐标对应的jar包解压到指定目录
3.1 copy
下述配置在打包阶段会将junit包拷贝到项目的target/alternateLocation目录下
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <id>copy</id> <phase>package</phase> <goals> <goal>copy</goal> </goals> </execution> </executions> <configuration> <artifactItems> <artifactItem> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <type>jar</type> <overWrite>false</overWrite> <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory> </artifactItem> </artifactItems> </configuration> </plugin> ————————————————
3.2 copy-dependencies
和copy命令的区别是,copy是拷贝指定坐标的jar包,而copy-dependencies则是拷贝项目依赖的所有jar包,具体用法如下
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
从上面的配置里我们可以看到,插件的执行被配置到install这个阶段,当然也可以是 package 阶段
这样,当我们执行命令:mvn clean install 的时候,会发现对应的target目录里生成了对应的jar包和依赖包。
3.3 unpack
unpack命令可以将指定的jar包解压到指定的目录,需要注意的是,如果指定的触发阶段为compile,那么解压之后的内容会一起打包到当前项目中,而如果是package则不会,它只会打包自己项目内容
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <!-- 为该操作定义一个名字 --> <id>unpack</id> <!-- 该操作在生命周期的那个阶段触发 --> <phase>compile</phase> <goals> <!-- 插件的具体操作,这里只介绍4种--> <goal>unpack</goal> </goals> <!-- 操作的配置 --> <configuration> <!-- 配置 --> <artifactItems> <!-- 具体配置,此处一般是针对某个坐标的具体配置 --> <artifactItem> <!-- 指定坐标 --> <groupId>org.example.it</groupId> <artifactId>po.webresource</artifactId> <version>1.0-SNAPSHOT</version> <type>jar</type> <overWrite>true</overWrite> <!-- 输出路径 --> <outputDirectory>${project.build.directory}/classes</outputDirectory> <!-- 坐标对应的jar包的名称 --> <destFileName>po.webresource-1.0-SNAPSHOT.jar</destFileName> <!-- 操作的内容 --> <includes>**/*.html,**/*.js</includes> <!-- 排除的内容 --> <excludes>**/*test.html</excludes> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin>
3.4 unpack-dependencies
和unpack命令的区别是,unpack是解压指定坐标的jar包,而unpack-dependencies则是解压项目依赖的所有jar包,具体用法如下
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <id>unpack-dependencies</id> <phase>package</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <includes>**/*.class</includes> <excludes>**/*.properties</excludes> <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> </configuration> </execution> </executions> </plugin>
4-1. maven-surefire-plugin 打包时跳过单元测试
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
4-2. 如果单元测试中有输出中文,eclipse的控制台里中文可能会变成乱码输出,也可以通过这个插件解决,参考配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-Dfile.encoding=UTF-8</argLine>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <!-- 操作名,自己指定 --> <id>assembly</id> <!-- 操作触发的阶段 --> <phase>package</phase> <goals> <!-- 只执行一次--> <goal>single</goal> </goals> <configuration> <!-- 自己指定的名字,和assemblies.xml配置文件中的id标签对应 --> <finalName>html</finalName> <!-- 配置文件的位置和名字(与pom.xml)的相对路径--> <descriptors>assemblies.xml</descriptors> </configuration> </execution> </executions> </plugin>
除了需要在pom中配置上述内容外,还需要引入一个配置文件assemblies.xml(名字由自己指定)
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>html</id> <formats> <!-- 生成一个zip文件 --> <format>zip</format> </formats> <fileSets> <fileSet> <!-- 从编译后的文件中拷贝 --> <directory>${project.build.directory}/classes</directory> <!-- 拷贝到的文件存放的路径 --> <outputDirectory></outputDirectory> <useDefaultExcludes>true</useDefaultExcludes> <excludes> <!-- 哪些文件不拷贝 --> <exclude>**/*.log</exclude> <exclude>**/${project.build.directory}/**</exclude> </excludes> </fileSet> </fileSets> </assembly>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。