优秀的编程知识分享平台

网站首页 > 技术文章 正文

Maven填坑记二(maven-checkstyle-plugin)

nanyue 2024-08-09 07:00:43 技术文章 9 ℃

前文(Maven填坑记一)以持续集成为例,引申出了maven命令的正确使用方法,并简单介绍了一下maven的基本概念。今天我们从一个具体的pom文件入手来了解一下maven的其他概念以及面试中常见的一些问题。

Maven的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.1.0.RELEASE</version>
 <relativePath/> 
 </parent>
 <groupId>com.bancheng</groupId>
 <artifactId>demoTest</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>demoTest</name>
 <description>Demo project for Spring Boot</description>
 <properties>
 <spring.version>4.2.1</spring.version>
 </properties>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <version>${spring.version}</version>
 <scope>test</scope>
 </dependency>
 </dependencies>
</project>

上面是一个标准的pom文件,其中的坐标部分,前文已经涉及过,今天就不展开了,我们来重点关于一下<dependencies></dependencies>包含的内容。这部分内容在maven中被称为依赖,定义了该项目需要引入的外部jar包,在实际构建过程中,会遵循上文的依赖搜索顺序,将相应的jar包打入最终的项目jar包或者war包里面。

接下来让我们看一下依赖可能涉及的具体元素吧。

  • dependencies:一个 pom.xml 文件中只能存在一个这样的标签。用来管理依赖的总标签。
  • dependency:包含在dependencies标签中,可以有无数个,每一个表示一个依赖
  • groupId,artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,maven根据坐标才能找到需要的依赖。如果一个依赖在项目中需要引用多次,对于其版本定义可以采用变量的方式,具体请参考上面。
  • type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值是jar。
  • scope:依赖的范围,默认值是 compile。
  • optional:标记依赖是否可选。
  • exclusions:用来排除传递性依赖。

项目中多次引用相同的类包,版本相同,可以采用上面变量的方式统一声明,那如果版本不相同呢,特别是不同类包的间接依赖导致的版本不一致,maven是如何解决对应版本冲突的呢?

这就必然需要定义一个依赖传递规则。

1.第一声明者优先原则

2.路径近者优先原则

可以通过mvn dependency:tree命令生成项目的依赖树,如下图所示:

该依赖树的根节点是本项目生成的jar包,接下来是本项目直接依赖的类包,其他是本项目直接依赖类包依赖的间接类包,这三者形成了一个不同层级的树状结构。依据上面的两个原则,如果发生冲突的类包是在同一层级,那么优先声明的类包版本生效,如果是在不同层级的类包,那么离根节点层级更近的类包版本生效。当然这种方式不够直观,最好的方法还是通过exclusions标签来显示排除,如下图所示。

<exclusions> 
 <exclusion> 
 <artifactId>unitils-database</artifactId> 
 <groupId>org.unitils</groupId> 
</exclusion> </exclusions> 

Maven的依赖范围

上面的依赖中用到的scope标签的值是test,这个有什么特殊含义呢?

1. compile:编译依赖,默认的依赖方式,在编译(编译项目和编译测试用例)、运行测试用例、运行(项目实际运行)三个阶段都有效。

2. test:测试依赖,只在编译测试用例和运行测试用例有效,典型的有JUnit。

3. provided:对于编译和测试有效,不会打包进发布包中,典型的例子为servlet-api,一般的web工程运行时都使用容器的servlet-api,如tomcat容器。

4. runtime:只在运行测试用例和实际运行时有效,典型的是jdbc驱动jar包。

5. system: 不从maven仓库获取该jar,而是通过systemPath指定该jar的路径。

6. import: 用于一个dependencyManagement对另一个dependencyManagement的继承。

常见的面试题

Maven常见的面试题有哪些呢?

Q:dependencies和dependencyManagement,plugins和pluginManagement有什么区别呢?

A:dependencyManagement是表示依赖jar包的声明,即使在项目中的dependencyManagement下声明了依赖,maven不会直接加载该依赖,但是其声明可以被继承。一个常用的使用案例是父子项目的时候,应用于父项目。之后在在子项目中的dependencies节点可以只配置groupid和artifactid就可以完成类包的引用。类似的还有plugins和pluginManagement。

Q:如何制定JDK版本

A:有两种方式,一种是通过properties方式,如下面所示:

<properties>
 <maven.compiler.source>1.8<maven.compiler.source>
 <maven.compiler.target>1.8</maven.compiler.target>
<properties>

一种是使用maven-compiler-plugin插件,并制定source和target版本,如下面所示:

<build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactedId>maven-complier-plugin</artifactedId>
 <version>3.3</version>
 <configuration>
 <source>1.8</source>
 <target>1.8</target>
 </configuration>
 </plugin>
 </plugins>
</build>

Q:如何避免将dependency打包到构件中

A:如上文所述,将<scope>标签的值设为provided,只会在编译和测试阶段生效。

以上介绍了依赖的传递规则、范围及常见的面试题,希望对大家有帮助,更多精彩,请持续关注哦。

最近发表
标签列表