简述

java开发中能够运用maven来办理依靠,引进依靠,构建终究jar文件,当然其中也可能需求处理依靠抵触问题。

  1. 办理依靠:经过<dependencyManagement>,声明依靠版别,进行依靠的版别控制的。
  2. 引进依靠:经过<dependency>,进行依靠的实际引进。
  3. 构建jar包:在需求打包的模块中增加<build>并加入定制插件plugin进行jar生成。
  4. 依靠抵触:经过东西或许命令行排查抵触的依靠后,运用exclusion来排出抵触的依靠。

注:

  1. 依靠抵触能够运用idea的mavenhelper插件来检查,简略直观,也能够命令行运用mvn dependency:tree -Dverbose > tree.txt,在文件中检索conflict关键字。

maven运用前,需求设置好setting.xml装备文件,如镜像库房。

  1. maven的打包命令mvn clean package -Dmaven.test.skip=true
  2. 指定装备文件打包mvn clean package -s setting.xml -Dmaven.test.skip=true
  3. maven的裁定机制:途径最近者优先,途径相同榜首声明者优先(途径距离是从打包模块的pom开端算,榜首声明是pom中声明的前后次序)

maven常用标签的运用

的根本运用

主要讲解的内容:依靠常用的两种引证方法,依靠的排除方法,依靠的效果域,<option>标签。

  1. 库房引进
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>${mybatis-plus.version}</version>
</dependency>
  1. 本地引进
  • 注:需求在<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>
  1. 依靠排除
<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>
  1. 依靠的效果域标签<scope>,其默认值为compile
<!-- Lombok -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<scope>provided</scope>
</dependency>

企业开发中Maven的基本使用
拓宽:<scope>import</scope> 只能在<dependencyManagement> 模块中运用,用于处理maven的单承继问题。

  1. <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>
  1. 拓宽常识:<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工程,一次性构建多个项目/模块。 常用标签

  1. <packaging>:这是聚合模块必须要有的标签内容为pom,表示这是一个聚合模块(没有代码),用来办理多个模块。
  2. <module>: 标签用于指定办理的那些模块,不记录模块办理的模块(浅引证)。
  3. <dependencyManagement>:声明依靠版别,子模块引进依靠无需写入版别号,共同办理依靠版别。
  4. <pluginManagement>,声明插件,办理插件装备,子项目直接承继,无需重复编写装备规则。
  5. <properties>声明变量,用于对变量的办理,如版别号,经过${}取值。

依靠模块和完成模块

如api和common只供给东西和功用支持的模块称其依靠模块,而完成模块则是一个用于打包部署运转的详细微服务模块。 依靠模块常用标签

  1. <dependency>:引进所需依靠
  2. packaging: 需求把代码打包,一般为jar

微服务模块常用标签

  1. <dependency>:引进所需依靠
  2. packaging: 需求把代码打包,一般为jar(放在web容器则为war)
  3. <build>:关于一个springboot项目,详细微服务模块需求经过build指定一个构建方法,如指定springboot-maven-plugin来进行构建。

JVM加载类

JVM会依据次序加载class文件,假如全限定名重复,后边的class将会被疏忽。 假如存在同类名的class能够考虑:

  1. 移除重复的class
  2. 写类加载器来加载特定的class
  3. 改动classpath里的次序

springboot生成jar结构目录

阿里的一些开发规范

【强制】制止在子项意图 pom 依靠中呈现相同的 GroupId,相同的 ArtifactId,可是不同的 Version
阐明:在本地调试时会运用各子项目指定的版别号,可是合并成一个 war,只能有一个版别号呈现在终究的 lib 目录 中。从前呈现过线下调试是正确的,发布到线上却出毛病的先例。
【推荐】一切 pom 文件中的依靠声明放在句子块中,一切版别裁定放在 句子块中。 阐明:里仅仅声明版别,并不完成引进,因此子项目需求显式的声明依靠,version 和 scope 都读取自父 pom。而一切声明在主 pom 的里的依靠都会自动引进,并默 认被一切的子项目承继。 【强制】二方库的新增或升级,坚持除功用点之外的其它 jar 包裁定成果不变。假如有改动,必须清晰评 估和验证。 阐明:在升级时,进行 dependency:resolve 前后信息比对,假如裁定成果完全不共同,那么经过 dependency:tree 命 令,找出差异点,进行排除 jar 包。 **【强制】依靠于一个二方库群时,必须界说一个共同的版别变量,防止版别号不共同。 ** 阐明:依靠 springframework-core,-context,-beans,它们都是同一个版别,能够界说一个变量来保存版别: ${spring.version},界说依靠的时分,引证该版别。

开发中遇见的问题

某些包没有打入生成jar中

  • 在idea开发完成后,生成镜像上云中发现微服务j发动ar报错,找不某个类,检查jar包发现某个依靠未打入jar包,jar为spring-boot-configuration-processor,检索引进地方,发现其引进效果域<scope>option<scope>,将其注释后,检查idea侧边maven也确实经过common引进,打包后依然未打入jar包,将此依靠直接引进微服务打包后依靠引进成功,但各个微服务都有引进,需求都复制一份有些麻烦,后将其从父工程根pom引进,打包后依靠引进成功。只要注释掉效果域也不收效,其原因不知道。
  • 另一次就是pom引进本地jar包,但打包未增加<includeSystemScope>true</includeSystemScope>导致打包未打入jar。

jar包抵触

  • mybatis-plus-boot-starter中引进了jsqlparser依靠,可是mavenhelper未检测到,idea每次编译都会发生一个低版别的jsqlparser,因为开端不清楚低版别的来处,导致浪费了许多精力。
  • jsqlparserpagehelper版别不匹配导致,方法不存在报错,终究经过查询到一个匹配版别处理。

某些二次封装的包与曾经包全限定类名共同而且接口内容不共同发生过错

  • 如对一些常用依靠进行了二次封装,可是接口方法有差别,导致编译时呈现过错。

莫名其妙的循环依靠问题:增加了依靠或许改了一点无关的代码,循环依靠报错就会呈现,按道理低版别springboot能够经过三级缓存来处理循环依靠,可是并不收效。

抱着疑问,我找到了程序员导师:Google来求助,终究兜兜转转找到了github里spring-framework的一个issue,提的就是这个问题: github.com/spring-proj… 能够看到这个issue从2016年初次被提出,到2019年reopen,实际上一直都没有找到过原因。issue里好几个人遇到了和我一样的问题:一样的代码,在不同的环境上编译,出来的jar包有的能运转,有的却报错。 spring的维护人员可能是觉得循环依靠不应当在程序中呈现,乃至目前springboot2.6版别已经完全不允许循环依靠了,所以对这个issue也就没有动力去处理。

  1. 重打包问题

参考链接

blog.csdn.net/u012925692/…

blog.csdn.net/u012925692/…

www.cnblogs.com/xtf2009/p/1…

zhuanlan.zhihu.com/p/610374858

blog.csdn.net/xhf852963/a…

blog.csdn.net/m0_56079407…

blog.csdn.net/z69183787/a…

blog.csdn.net/u013315062/…

my.oschina.net/liuyongpo/b…