SpringBoot项目打jar包供别的项目调用问题

时间:2024-03-21 21:13:39

假如有两个项目A和B,假如A项目想打成jar包,然后在B中引入该jar包。

1、SpringBoot的Maven插件打包

如果用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。

SpringBoot项目打jar包供别的项目调用问题

图1.1、打包过程

SpringBoot项目打jar包供别的项目调用问题

图1.2、生成的jar包

SpringBoot会自带打包插件打的包不能用。将SpringBoot会自带打包插件打的包解压后会看到它的目录结构,它把包都达到BOOT-INF这个目录下了,引用的时候我们引用不到,会报“Cannot resolve symbol”的错,如图1.3。

SpringBoot项目打jar包供别的项目调用问题

图1.3、报的错

2、原生的Maven插件打包

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。

SpringBoot项目打jar包供别的项目调用问题

图2.1、打包过程

SpringBoot项目打jar包供别的项目调用问题

图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。

SpringBoot项目打jar包供别的项目调用问题

图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的依赖。为了解决这个问题,我又找到了第三种方式。

3、Assembly插件打包

为了解决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包。如图:

SpringBoot项目打jar包供别的项目调用问题

图3.1、打包过程

SpringBoot项目打jar包供别的项目调用问题

图3.2、生成的jar包

这种方式打的包利用坐标引入本地库的依赖和引入本地的jar都可以。引用方式同上。

4、打包的时候剔除不想要的依赖

当我们在打包的时候,有些依赖我们只想测试的时候后,打包的时候不想打入包中,

例;

我创建的项目是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,这样打包的时候就不会打入包中。

注:自己按经验而写,如有不对请指正。谢谢。