[maven] scopes & 管理 & profile & 测试覆盖率

[maven] scopes & 管理 & profile & 测试覆盖率

这里将一些其他的特性和测试覆盖率(主要是 jacoco)

scopes

maven 的 scope 主要就是用来限制和管理依赖的传递性,简单的说就是,每一个 scope 都有其对应的特性,并且会决定依赖包在打包和运行时是否会被使用

这里主要谈论的差别是 compile classpath 和 runtime classpath,前者是编译时存在的环境,后者是运行时存在的环境。

总共有 6 个 scopes

  • compile (default)

    这个是默认的 scope,这个 scope 下的依赖会被打包到代码的最终代码里,它也代表着该依赖会被保存到 compile classpath 和 runtime classpath,粗暴的理解就是,打包好的 jar/war 文件会包含 runtime classpath 的代码

  • provided

    这个 scope 代表着在部署时,JDK 或者容器在运行时会提供该依赖,所以在 compile classpath 可以找到这个依赖,但是 runtime classpath 中不会

    例子就是 tomcat 这种 servlet api,编译时肯定是需要的,但是部署时肯定,环境里自己会启一个 servlet,因此 runtime classpath 不需要包涵

  • runtime

    这个 scope 意味着依赖在编译时不需要,但是运行时需要,比如说 JDBC driver

  • test

    顾名思义,只需要用在编译和测试,不会打包到最终的代码里

  • system

    这个挺少用的,因为一旦用它就代表着要用到 systemPath 相关,也就会变得非常依赖于系统,似的其可移植性变低

  • import

    比较特殊的 scope,用在 BOM 这种特殊的依赖,主要用来管理其他依赖版本

目前来说,从 central repo 上拉下来的 scope 还是比较准的,比如说 junit 相关的 scope 就是 test,不过这也可以按需修改。

项目管理

这里分为三个部分:

  • 依赖管理
  • 插件管理
  • 版本管理

主要应用场景都是对于依赖/插件的版本控制。重载版本的情况下,越下层(靠近执行项目的 pom)的值会取代上层设置的值

依赖管理

这个主要是通过在父元素中实现 dependencyManagement,这样子元素中就不用重新声明版本,方便进行统一管理。

在父元素中定义 junit 的版本:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>

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

	<groupId>com.goldenaarcher.product</groupId>
	<artifactId>productparent</artifactId>
	<version>1.0</version>
	<packaging>pom</packaging>

	<name>productparent</name>
	<!-- FIXME change it to the project's website -->
	<url>http://www.example.com</url>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>4.11</version>
				<scope>test</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<modules>
		<module>productservices</module>
		<module>productweb</module>
	</modules>
</project>

这个时候,如果子项目中重新声明了版本,eclipse 就会出现这样的报错:

子项目中的 pom 荏苒需要按需定义使用的依赖,只不过就可以跳过版本声明,方便统一管理

插件管理

插件管理有个相似的 pluginManagement,不过它需要被放到 build 下:

xml 复制代码
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
					<configuration>
						<release>17</release>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

同理,子项目中也是需要声明同样的插件,但是可以不用实现 versionconviguration

版本管理

除了直接将版本写到 version 中,如果一些依赖(如 spring 全家桶)都需要使用同一个版本,与其重复 cv,也可以在 properties 中声明版本变量,方便管理:

xml 复制代码
	<properties>
		<java.version>17</java.version>
		<junit.version>5.10.0</junit.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.junit.jupiter</groupId>
				<artifactId>junit-jupiter-engine</artifactId>
				<version>${junit.version}</version>
				<scope>test</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
					<configuration>
						<release>${java.version}</release>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

profiles

profile 是一些配置型的内容,可以用来重写默认值。

maven 中也可以用不同的项目家在加载不同的配置文件,祈祷方便管理的作用。

创建新项目

选择 quickstart 创建一个新的 demo 项目即可

创建配置文件

这里的 profile 和 main 同级,新建 3 个案例即可:

bash 复制代码
❯ tree src
src
├── main
│   ├── java
│   │   └── com
│   │       └── goldenaarcher
│   │           └── maven
│   │               └── profiledemo
│   │                   └── App.java
│   └── profiles
│       ├── dev
│       │   └── application.properties
│       ├── prod
│       │   └── application.properties
│       └── test
│           └── application.properties
└── test
    └── java
        └── com
            └── goldenaarcher
                └── maven
                    └── profiledemo
                        └── AppTest.java

里面的内容也很简单:

bash 复制代码
❯ cat src/main/profiles/dev/application.properties
db.url=devurl
db.userName=dev
db.password=dev%

其实 profiles 也可以放在其他地方,我记得一个项目是放到 resources 里,这点看项目习惯

配置 profile

profile 直接放在 xml 下即可:

xml 复制代码
	<profiles>
		<profile>
			<id>dev</id>
			<properties>
				<build.profile.id>dev</build.profile.id>
			</properties>
			<build>
				<resources>
					<resource>
						<directory>src/main/profiles/dev</directory>
					</resource>
				</resources>
			</build>
		</profile>

		<profile>
			<id>prod</id>
			<properties>
				<build.profile.id>prod</build.profile.id>
			</properties>
			<build>
				<resources>
					<resource>
						<directory>src/main/profiles/prod</directory>
					</resource>
				</resources>
			</build>
		</profile>

		<profile>
			<id>test</id>
			<properties>
				<build.profile.id>test</build.profile.id>
			</properties>
			<build>
				<resources>
					<resource>
						<directory>src/main/profiles/test</directory>
					</resource>
				</resources>
			</build>
		</profile>
	</profiles>

只有一个 profile 的话不需要设置 id,有一个以上不设置会报错

profile 使用案例

命令行执行 profile

语法为: mvn <lifecycle-phase> -P<profile-name>

如:

bash 复制代码
❯ mvn install -Pdev
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.goldenaarcher.maven:profiledemo >-----------------
[INFO] Building profiledemo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ profiledemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ profiledemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/usr/study/maven/profiledemo/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ profiledemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/profiledemo/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ profiledemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/usr/study/maven/profiledemo/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ profiledemo ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.goldenaarcher.maven.profiledemo.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 s - in com.goldenaarcher.maven.profiledemo.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ profiledemo ---
[INFO] Building jar: /Users/usr/study/maven/profiledemo/target/profiledemo-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ profiledemo ---
[INFO] Installing /Users/usr/study/maven/profiledemo/target/profiledemo-0.0.1-SNAPSHOT.jar to /Users/usr/.m2/repository/com/goldenaarcher/maven/profiledemo/0.0.1-SNAPSHOT/profiledemo-0.0.1-SNAPSHOT.jar
[INFO] Installing /Users/usr/study/maven/profiledemo/pom.xml to /Users/usr/.m2/repository/com/goldenaarcher/maven/profiledemo/0.0.1-SNAPSHOT/profiledemo-0.0.1-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.714 s
[INFO] Finished at: 2023-09-14T22:44:31-04:00
[INFO] ------------------------------------------------------------------------

如果解压打包好的 jar 文件,就能看到里面的 application.properties 内容如下:

bash 复制代码
❯ cat target/profiledemo-0.0.1-SNAPSHOT/application.properties
db.url=devurl
db.userName=dev
db.password=dev%
eclipse 中设置

这个在 project properties 修改就行:

jacoco 代码覆盖率

sonarqube 执行失败

jacoco

修改 pom:

xml 复制代码
    <build>
		<plugins>
			<plugin>
				<groupId>org.jacoco</groupId>
				<artifactId>jacoco-maven-plugin</artifactId>
				<version>0.8.7</version>
				<executions>
					<execution>
						<goals>
							<goal>prepare-agent</goal>
						</goals>
					</execution>
					<execution>
						<id>report</id>
						<phase>test</phase>
						<goals>
							<goal>report</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
    </build>

这个 plugin 放到 pluginManagement 下管理会报错,但是拉出来直接放到 build 下就好了,原因未明,从 Stack Overflow 上找到的解决方法:maven jacoco: not generating code coverage report

简单的过一遍 xml 的配置,goal 在 [maven] maven 简述及使用 maven 管理单个项目 提过了,execution 没有。

goal 是 plugin 提供的,这里只是负责调用。

execution 是用来配置 goal 应该在哪个 phase 中执行,这里有两个 execution,第一个 goal 就是 jacoco 提供的 prepare-agent,其他忽略代表着会从头开始执行。

第二个 execution 指定的是生成报告的阶段,生成测试报告的 phase 应该是测试,所以就是在测试这个 phase 执行 report 这个 goal。

运行结果:

bash 复制代码
# 这里需要用verify不能用test,test会跳过report
❯ mvn clean verify
[INFO] Scanning for projects...
[INFO]
[INFO] -------------< com.goldenaarcher.product:productservices >--------------
[INFO] Building productservices 1.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ productservices ---
[INFO] Deleting /Users/usr/study/maven/parent/productservices/target
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.7:prepare-agent (default) @ productservices ---
[INFO] argLine set to -javaagent:/Users/usr/.m2/repository/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar=destfile=/Users/usr/study/maven/parent/productservices/target/jacoco.exec
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ productservices ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/parent/productservices/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ productservices ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to /Users/usr/study/maven/parent/productservices/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ productservices ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/parent/productservices/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ productservices ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/usr/study/maven/parent/productservices/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ productservices ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.goldenaarcher.product.dao.ProductDAOImplTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.07 s - in com.goldenaarcher.product.dao.ProductDAOImplTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.7:report (report) @ productservices ---
[INFO] Loading execution data file /Users/usr/study/maven/parent/productservices/target/jacoco.exec
[INFO] Analyzed bundle 'productservices' with 3 classes
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ productservices ---
[INFO] Building jar: /Users/usr/study/maven/parent/productservices/target/productservices-1.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.440 s
[INFO] Finished at: 2023-09-15T00:01:59-04:00
[INFO] ------------------------------------------------------------------------

可以看到,运行到测试这里,jacoco 的 goal 被执行了:jacoco-maven-plugin:0.8.7:report (report) @ productservices,最终生成报告的目录与结果:

bash 复制代码
❯ tree target/site
target/site
└── jacoco
    ├── com.goldenaarcher.product.bo
    │   ├── ProductBOImpl.html
    │   ├── ProductBOImpl.java.html
    │   ├── index.html
    │   └── index.source.html
    ├── com.goldenaarcher.product.dao
    │   ├── ProductDAOImpl.html
    │   ├── ProductDAOImpl.java.html
    │   ├── index.html
    │   └── index.source.html
    ├── com.goldenaarcher.product.dto
    │   ├── Product.html
    │   ├── Product.java.html
    │   ├── index.html
    │   └── index.source.html
    ├── index.html
    ├── jacoco-resources
    │   ├── branchfc.gif
    │   ├── branchnc.gif
    │   ├── branchpc.gif
    │   ├── bundle.gif
    │   ├── class.gif
    │   ├── down.gif
    │   ├── greenbar.gif
    │   ├── group.gif
    │   ├── method.gif
    │   ├── package.gif
    │   ├── prettify.css
    │   ├── prettify.js
    │   ├── redbar.gif
    │   ├── report.css
    │   ├── report.gif
    │   ├── session.gif
    │   ├── sort.gif
    │   ├── sort.js
    │   ├── source.gif
    │   └── up.gif
    ├── jacoco-sessions.html
    ├── jacoco.csv
    └── jacoco.xml

6 directories, 36 files

sonarqube

sonarqube 也是一个挺好用的代码测试工具,不过它需要修改本机 proxy,并启动一个本地服务器去执行剩下的操作,很不幸的是工作机的 proxy 没法改,所以这里就......

它的运行方式还是挺简单的,sonarqube 提供了 sh/bat 文件,直接运行就能启动服务器,登陆后在 dashboard 生成一串登陆编号,maven 运行时添加登录编号 sonarqube 就可以对其进行分析,属于不太要修改 maven 配置的工具

相关推荐
东阳马生架构1 分钟前
商品中心—1.B端建品和C端缓存的技术文档
java
Chan164 分钟前
【 SpringCloud | 微服务 MQ基础 】
java·spring·spring cloud·微服务·云原生·rabbitmq
LucianaiB7 分钟前
如何做好一份优秀的技术文档:专业指南与最佳实践
android·java·数据库
面朝大海,春不暖,花不开31 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y31 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java
白宇横流学长2 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端