java开发中可以使用maven来管理依赖,引入依赖,构建最终jar文件,当然其中也可能需要解决依赖冲突问题。
<dependencyManagement>
,声明依赖版本,进行依赖的版本控制的。<dependency>
,进行依赖的实际引入。<build>
并加入定制插件plugin
进行jar生成。exclusion
来排出冲突的依赖。注:
mavenhelper
插件来查看,简单直观,也可以命令行使用mvn dependency:tree -Dverbose > tree.txt
,在文件中检索conflict
关键字。maven使用前,需要设置好setting.xml
配置文件,如镜像仓库。
mvn clean package -Dmaven.test.skip=true
mvn clean package -s setting.xml -Dmaven.test.skip=true
主要讲解的内容:依赖常用的两种引用方式,依赖的排除方式,依赖的作用域,<option>
标签。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
复制代码
<build>
中<plugin>
中需添加<includeSystemScope>true</includeSystemScope>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>kingbase8-hibernatedialect</artifactId>
<version>5.2.17.Finaldialect</version>
<scope>system</scope>
<systemPath>${project.basedir}/../../../lib/hibernate-5.2.17.Finaldialect.jar</systemPath>
</dependency>
复制代码
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
<!--需要排除的依赖项-->
<exclusions>
<!--排除的依赖无需声明版本号-->
<exclusion>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</exclusion>
</exclusions>
</dependency>
复制代码
<scope>
,其默认值为compile
。<!-- Lombok -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>provided</scope>
</dependency>
复制代码
拓展:<scope>import</scope>
只能在<dependencyManagement>
模块中使用,用于解决maven的单继承问题。
<option>
标签,固定值为true
<option>
表示这个依赖是需要选择是否引入的,如果需要引入则需要显示声明。 举例:下方代码块是B模块的pom文件,A项目将B项目作为依赖后,这些带<option>
的依赖并不会被引入,不会打进jar包,如果需要引入则显示的添加声明。
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<optional>true</optional>
<dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc3</version>
<optional>true</optional>
<dependency>
</dependencies>
复制代码
<classifier>
标签,提供一个新的维度定义jar,一般为不同jdk版本生成jar文件maven-resp (maven仓库)
└── org
└── apache
└── maven
├── maven-artifacr-3.8.1-calss1.jar (jdk8生成一个jar)
└── maven-artifacr-3.8.1-calss2.jar (jdk21生成一个jar)
在pom文件中区分环境的中添加<classifier>calss1</classifier>或<classifier>calss1</classifier>则不同环境生成不同jar文件
样例:
<properties>
<classifier>default</classifier>
</properties>
<profiles>
<profile>
<id>jdk8</id>
<properties>
<classifier>calss1</classifier>
</properties>
</profile>
<profile>
<id>jdk21</id>
<properties>
<classifier>calss2</classifier>
</properties>
</profile>
</profiles>
<bulid>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>default-jar</id>
<goals>
<goal>jar<goal>
</goals>
<configuration>
<classifier>${classifier}</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
复制代码
项目A,依赖B项目,并且需要mysql驱动
<dependencies>
<dependency>
<groupId>project-b</groupId>
<artifactId>project-b</artifactId>
<version>b-version</version>
<dependency>
<!--因为B模块中mysql驱动是可选的,所以A模块需要mysql驱动得显示引入-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<dependency>
</dependencies>
复制代码
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<!--1.在原始Maven打包形成的jar包基础上,进行重新打包,
新形成的jar包不但包含应用类文件和配置文件,
而且还会包含应用所依赖的jar包以及Springboot启动相关类(loader等),
以此来满足Springboot独立应用的特性;
2.将原始Maven打包的jar重命名为XXX.jar.original作为原始文件;-->
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<!--将本地jar包打入构建生成的jar文件中-->
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
复制代码
以现在广泛流行的springboot多个微服务来作为介绍模板,一个微服务可以作为一个单体项目看待。
├── common (公共模块)
│ └── pom.xml
├── services(微服务模块)
│ ├── common(微服务之间的公共模块)
│ │ └── pom.xml
│ ├── service1(某微服务1的聚合模块)
│ │ ├──api(提供调用接口的模块)
│ | | └── pom.xml
│ | ├──specific-service(实现具体功能的模块)
│ | | └── pom.xml
│ │ └── pom.xml
│ ├── service2(某微服务2的聚合模块)
│ │ ├──api(提供调用接口的模块)
│ | | └── pom.xml
│ | ├──specific-service(实现具体功能的模块)
│ | | └── pom.xml
│ │ └── pom.xml
│ └── pom.xml
├── settings.xml (maven的配置文件)
└── pom.xml
复制代码
作用:聚合用于快速构建maven工程,一次性构建多个项目/模块。 常用标签
<packaging>
:这是聚合模块必须要有的标签内容为pom
,表示这是一个聚合模块(没有代码),用来管理多个模块。<module>
: 标签用于指定管理的那些模块,不记录模块管理的模块(浅引用)。<dependencyManagement>
:声明依赖版本,子模块引入依赖无需写入版本号,统一管理依赖版本。<pluginManagement>
,声明插件,管理插件配置,子项目直接继承,无需重复编写配置规则。<properties>
声明变量,用于对变量的管理,如版本号,通过${}
取值。如api和common只提供工具和功能支持的模块称其依赖模块,而实现模块则是一个用于打包部署运行的具体微服务模块。 依赖模块常用标签
<dependency>
:引入所需依赖packaging
: 需要把代码打包,一般为jar微服务模块常用标签
<dependency>
:引入所需依赖packaging
: 需要把代码打包,一般为jar(放在web容器则为war)<build>
:对于一个springboot项目,具体微服务模块需要通过build
指定一个构建方式,如指定springboot-maven-plugin
来进行构建。JVM会根据顺序加载class文件,如果全限定名重复,后面的class将会被忽略。 如果存在同类名的class可以考虑:
【强制】禁止在子项目的 pom 依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的 Version。 说明:在本地调试时会使用各子项目指定的版本号,但是合并成一个 war,只能有一个版本号出现在最后的 lib 目录 中。曾经出现过线下调试是正确的,发布到线上却出故障的先例。 【推荐】所有 pom 文件中的依赖声明放在语句块中,所有版本仲裁放在 语句块中。 说明:里只是声明版本,并不实现引入,因此子项目需要显式的声明依赖,version 和 scope 都读取自父 pom。而所有声明在主 pom 的里的依赖都会自动引入,并默 认被所有的子项目继承。 【强制】二方库的新增或升级,保持除功能点之外的其它 jar 包仲裁结果不变。如果有改变,必须明确评 估和验证。 说明:在升级时,进行 dependency:resolve 前后信息比对,如果仲裁结果完全不一致,那么通过 dependency:tree 命 令,找出差异点,进行排除 jar 包。 **【强制】依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。 ** 说明:依赖 springframework-core,-context,-beans,它们都是同一个版本,可以定义一个变量来保存版本: ${spring.version},定义依赖的时候,引用该版本。
spring-boot-configuration-processor
,检索引入地方,发现其引入作用域<scope>option<scope>
,将其注释后,查看idea侧边maven也确实通过common引入,打包后依然未打入jar包,将此依赖直接引入微服务打包后依赖引入成功,但各个微服务都有引入,需要都复制一份有些麻烦,后将其从父工程根pom引入,打包后依赖引入成功。只有注释掉作用域也不生效,其原因未知。<includeSystemScope>true</includeSystemScope>
导致打包未打入jar。mybatis-plus-boot-starter
中引入了jsqlparser
依赖,但是mavenhelper未检测到,idea每次编译都会产生一个低版本的jsqlparser
,由于开始不清楚低版本的来处,导致浪费了很多精力。jsqlparser
与pagehelper
版本不匹配导致,方法不存在报错,最终通过查询到一个匹配版本解决。抱着疑问,我找到了程序员导师:Google来求助,最终兜兜转转找到了github里spring-framework的一个issue,提的就是这个问题: github.com/spring-proj… 可以看到这个issue从2016年首次被提出,到2019年reopen,实际上一直都没有找到过原因。issue里好几个人遇到了和我一样的问题:一样的代码,在不同的环境上编译,出来的jar包有的能运行,有的却报错。 spring的维护人员可能是觉得循环依赖不应当在程序中出现,甚至目前springboot2.6版本已经完全不允许循环依赖了,所以对这个issue也就没有动力去解决。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。