假如有两个项目A和B,假如A项目想打成jar包,然后在B中引入该jar包。
如果用Idea创建的SpringBoot会自带maven打包插件。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
表1.1、引入SpringBoot会自带maven打包插件
然后点击idea左边的Maven Project->你的项目名->Lifecycle->instal就会把这个项目放入你本地的Maven库,如图1.1。而且还会在你的项目下生成一个jar包,如图1.2。
图1.1、打包过程
图1.2、生成的jar包
SpringBoot会自带打包插件打的包不能用。将SpringBoot会自带打包插件打的包解压后会看到它的目录结构,它把包都达到BOOT-INF这个目录下了,引用的时候我们引用不到,会报“Cannot resolve symbol”的错,如图1.3。
图1.3、报的错
SpringBoot会自带打包插件打的包不能用,不能用我改为用原生的Maven打包插件打包。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <!--指明源码用的Jdk版本--> <target>${java.version}</target> <!--指明打包后的Jdk版本--> </configuration> </plugin> </plugins> </build>
表2.1、引入原生maven打包插件
然后点击idea左边的Maven Project->你的项目名->Lifecycle->instal就会把这个项目放入你本地的Maven库,而且还会在你的项目下生成一个jar包,如图2.1。
图2.1、打包过程
图2.2、生成的jar包
这种方式打完包并安到本地仓库后可以通过两种方式引用该jar包。
1、通过你打包项目的坐标然后在调用的项目中引用能够引用的到。
A项目的坐标
<groupId>com.bonc</groupId> <artifactId>mcp-activiti-invoke</artifactId> <version>0.0.1-SNAPSHOT</version>
表2.2、打包项目坐标
B项目中引用
<dependency> <groupId>com.bonc</groupId> <artifactId>mcp-activiti-invoke</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
表2.3、引入打包到本地库中jar的坐标
2、我们直接把jar包放在本地,然后通过maven引入本地jar包能够引用到。但是这种方式有个问题,那就是打包那个项目的依赖不会打入jar包。这种方式如果想用,还得在项目中已入依赖,这种方式是不行的。
引用方法:在项目下创建个文件夹(一般都会命名为lib,这个可以随意定),然后把jar包放在该文件加下,如图2.3。最后在pom文件中已入该jar包,如表2.1。
图2.3、jar放的位置
<dependency> <groupId>com.bonc</groupId> <artifactId>mcp-activiti-invoke</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/lib/mcp-activiti-invoke-0.0.1-SNAPSHOT.jar</systemPath> </dependency>
表2.4、引入本地jar
这种打包方式用第一种引用可以,用第二种不行。如果B项目想用A项目打的包,我只需要把A的包引入就可以,不需要考虑A的依赖。为了解决这个问题,我又找到了第三种方式。
为了解决A项目打的包直接可以放在B项目中用,在B用A项目打的包的时候不需要考虑A项目中的依赖,我找到了这种打包方式。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.1</version> <configuration> <encoding>UTF-8</encoding> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.bonc.activitiinvoke.McpActivitiInvokeApplication</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
表3.1、引入assembly插件
然后点击idea左边的Maven Project->你的项目名->Lifecycle->instal就会把这个项目放入你本地的Maven库,而且还会在你的项目下生成一个jar包。如图:
图3.1、打包过程
图3.2、生成的jar包
这种方式打的包利用坐标引入本地库的依赖和引入本地的jar都可以。引用方式同上。
当我们在打包的时候,有些依赖我们只想测试的时候后,打包的时候不想打入包中,
例;
我创建的项目是springboot的,会有springboot依赖,当掉我这个包的项目也是springboot项目,但是这两个springboot版本不一样。这时候如果我把springboot相关的依赖打入包中的时候,引用我的项目就可能包冲突,启动不起来。如果引入方式的时候引入的是从本地仓库中引用的话,那么我们还可以采用依赖排除。但是打入jar包中的我们不能排除(注;这种我试了,没有排除掉。我只是按我操作结果写的,也不知道对不对。如果不对请指正)。此时我就想打包的时候可以不把springboot相关依赖打入包中,把其他的依赖打入包中。
在引入依赖的时候,有个属性scope,叫作用。它对应的属性值有:
compile:是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath 中可用,同时它们也会被打包。
provided:依赖只有在当JDK 或者一个容器已提供该依赖之后才使用。例如, 如果你开发了一个web 应用,你可能在编译 classpath 中需要可用的Servlet API 来编译一个servlet,但是你不会想要在打包好的WAR 中包含这个Servlet API;这个Servlet API JAR 由你的应用服务器或者servlet 容器提供。已提供范围的依赖在编译classpath (不是运行时)可用。它们不是传递性的,也不会被打包。
runtime:依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。
test:范围依赖在一般的编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。
system:范围依赖与provided 类似,但是你必须显式的提供一个对于本地系统中JAR 文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven 也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,你必须同时提供一个 systemPath 元素。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的 Maven 仓库中引用依赖)。
我们可以把依赖的坐标设置为provided,这样打包的时候就不会打入包中。
注:自己按经验而写,如有不对请指正。谢谢。