• [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 的版本:

    
    
    <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.0modelVersion>
    
    	<groupId>com.goldenaarcher.productgroupId>
    	<artifactId>productparentartifactId>
    	<version>1.0version>
    	<packaging>pompackaging>
    
    	<name>productparentname>
    	
    	<url>http://www.example.comurl>
    
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>junitgroupId>
    				<artifactId>junitartifactId>
    				<version>4.11version>
    				<scope>testscope>
    			dependency>
    		dependencies>
    	dependencyManagement>
    
    	<modules>
    		<module>productservicesmodule>
    		<module>productwebmodule>
    	modules>
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

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

    在这里插入图片描述

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

    插件管理

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

    	<build>
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.apache.maven.pluginsgroupId>
    					<artifactId>maven-compiler-pluginartifactId>
    					<version>3.8.0version>
    					<configuration>
    						<release>17release>
    					configuration>
    				plugin>
    			plugins>
    		pluginManagement>
    	build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    版本管理

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

    	<properties>
    		<java.version>17java.version>
    		<junit.version>5.10.0junit.version>
    	properties>
    
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.junit.jupitergroupId>
    				<artifactId>junit-jupiter-engineartifactId>
    				<version>${junit.version}version>
    				<scope>testscope>
    			dependency>
    		dependencies>
    	dependencyManagement>
    
    	<build>
    		<pluginManagement>
    			<plugins>
    				<plugin>
    					<groupId>org.apache.maven.pluginsgroupId>
    					<artifactId>maven-compiler-pluginartifactId>
    					<version>3.8.0version>
    					<configuration>
    						<release>${java.version}release>
    					configuration>
    				plugin>
    			plugins>
    		pluginManagement>
    	build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    profiles

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

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

    创建新项目

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

    创建配置文件

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

    ❯ 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    里面的内容也很简单:

    cat src/main/profiles/dev/application.properties
    db.url=devurl
    db.userName=dev
    db.password=dev%
    
    • 1
    • 2
    • 3
    • 4

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

    配置 profile

    profile 直接放在 xml 下即可:

    	<profiles>
    		<profile>
    			<id>devid>
    			<properties>
    				<build.profile.id>devbuild.profile.id>
    			properties>
    			<build>
    				<resources>
    					<resource>
    						<directory>src/main/profiles/devdirectory>
    					resource>
    				resources>
    			build>
    		profile>
    
    		<profile>
    			<id>prodid>
    			<properties>
    				<build.profile.id>prodbuild.profile.id>
    			properties>
    			<build>
    				<resources>
    					<resource>
    						<directory>src/main/profiles/proddirectory>
    					resource>
    				resources>
    			build>
    		profile>
    
    		<profile>
    			<id>testid>
    			<properties>
    				<build.profile.id>testbuild.profile.id>
    			properties>
    			<build>
    				<resources>
    					<resource>
    						<directory>src/main/profiles/testdirectory>
    					resource>
    				resources>
    			build>
    		profile>
    	profiles>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

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

    profile 使用案例

    命令行执行 profile

    语法为: mvn -P

    如:

    ❯ 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] ------------------------------------------------------------------------
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

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

    cat target/profiledemo-0.0.1-SNAPSHOT/application.properties
    db.url=devurl
    db.userName=dev
    db.password=dev%
    
    • 1
    • 2
    • 3
    • 4
    eclipse 中设置

    这个在 project properties 修改就行:

    在这里插入图片描述

    jacoco 代码覆盖率

    sonarqube 执行失败

    jacoco

    修改 pom:

        <build>
    		<plugins>
    			<plugin>
    				<groupId>org.jacocogroupId>
    				<artifactId>jacoco-maven-pluginartifactId>
    				<version>0.8.7version>
    				<executions>
    					<execution>
    						<goals>
    							<goal>prepare-agentgoal>
    						goals>
    					execution>
    					<execution>
    						<id>reportid>
    						<phase>testphase>
    						<goals>
    							<goal>reportgoal>
    						goals>
    					execution>
    				executions>
    			plugin>
    		plugins>
        build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    这个 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。

    运行结果:

    # 这里需要用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] ------------------------------------------------------------------------
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

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

    ❯ 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述

    sonarqube

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

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

  • 相关阅读:
    207.课程表 | 210.课程表II
    浅析linux 内核 高精度定时器(hrtimer)实现机制(一)
    01 - Apache Seatunnel 源码调试
    AGI STK使用本地地形和地图
    Postman全局配置变量token
    新手学习笔记-----⽂件操作
    win10下基于anaconda的detectron2安装
    高等数学(第七版)同济大学 习题3-2 个人解答
    【小程序】网络请求API介绍及网络请求的封装
    GBase 8c 存储技术---内存引擎(三)
  • 原文地址:https://blog.csdn.net/weixin_42938619/article/details/132914047