maven 简述及使用 maven 管理单个项目
简单的说就是 maven 是一个项目管理工具,同时也是一个依赖管理工具。
使用 maven 生成的项目结构大致如下:
project
|- src/main/java
|- src/main/resources
|- src/test/java
|- src/test/resources
本篇笔记带一些核心重点和在 maven 中创建一个项目
使用 maven 创建项目及一些关键点
创建&安装&运行
创建 maven 项目
这里主要是用终端运行,指令包括构建 maven 项目、查看 pom 文件以及显示 maven 项目的结构,如下:
❯ mvn archetype:generate -DgroupId=com.goldenaarcher -DartifactId=hellomaven -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
# 如果是第一次下载会花一点时间
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: /Users/usr/study/maven
[INFO] Parameter: package, Value: com.goldenaarcher
[INFO] Parameter: groupId, Value: com.goldenaarcher
[INFO] Parameter: artifactId, Value: hellomaven
[INFO] Parameter: packageName, Value: com.goldenaarcher
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /Users/usr/study/maven/hellomaven
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.244 s
[INFO] Finished at: 2023-09-11T08:18:15-04:00
[INFO] ------------------------------------------------------------------------
# 查看 pom 文件
❯ cat hellomaven/pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.goldenaarcher</groupId>
<artifactId>hellomaven</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hellomaven</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
# 查看项目结构
❯ tree hellomaven
hellomaven
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── goldenaarcher
│ └── App.java
└── test
└── java
└── com
└── goldenaarcher
└── AppTest.java
10 directories, 3 files
artifactId
和项目名相同,指令做什么后面会进行解释
安装
这里主要是将 repositories 上的依赖打包下载到本地的 .m2
文件夹中,然后再根据 pom 文件进行管理:
❯ mvn install
[INFO] Compiling 1 source file to /Users/usr/study/maven/hellomaven/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.731 s
[INFO] Finished at: 2023-09-11T09:35:01-04:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project hellomaven: Compilation failure: Compilation failure:
[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
这其中会出现一些小问题,主要是默认的 java 版本太老(5),现在已经不支持,所以要根据项目安装并配置对应的 java 版本。这里的 pom 文件会在 properties 里面配置 java 的版本:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.goldenaarcher</groupId>
<artifactId>hellomaven</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hellomaven</name>
<url>http://maven.apache.org</url>
<!-- 这里指定 java 版本 -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
然后重新安装:
❯ mvn install
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hellomaven ---
[INFO] Building jar: /Users/usr/study/maven/hellomaven/target/hellomaven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ hellomaven ---
[INFO] Installing /Users/usr/study/maven/hellomaven/target/hellomaven-1.0-SNAPSHOT.jar to /Users/usr/.m2/repository/com/goldenaarcher/hellomaven/1.0-SNAPSHOT/hellomaven-1.0-SNAPSHOT.jar
[INFO] Installing /Users/usr/study/maven/hellomaven/pom.xml to /Users/usr/.m2/repository/com/goldenaarcher/hellomaven/1.0-SNAPSHOT/hellomaven-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.128 s
[INFO] Finished at: 2023-09-11T09:38:45-04:00
[INFO] ------------------------------------------------------------------------
❯ tree hellomaven
hellomaven
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── com
│ │ └── goldenaarcher
│ │ └── App.java
│ └── test
│ └── java
│ └── com
│ └── goldenaarcher
│ └── AppTest.java
└── target
├── classes
│ └── com
│ └── goldenaarcher
│ └── App.class
├── generated-sources
│ └── annotations
├── generated-test-sources
│ └── test-annotations
├── hellomaven-1.0-SNAPSHOT.jar
├── maven-archiver
│ └── pom.properties
├── maven-status
│ └── maven-compiler-plugin
│ ├── compile
│ │ └── default-compile
│ │ ├── createdFiles.lst
│ │ └── inputFiles.lst
│ └── testCompile
│ └── default-testCompile
│ ├── createdFiles.lst
│ └── inputFiles.lst
├── surefire-reports
│ ├── TEST-com.goldenaarcher.AppTest.xml
│ └── com.goldenaarcher.AppTest.txt
└── test-classes
└── com
└── goldenaarcher
└── AppTest.class
29 directories, 13 files
.m2
在的位置系统不同,目录不同,可以根据自己的系统找找对应的资料
运行
❯ java -cp target/hellomaven-1.0-SNAPSHOT.jar com.goldenaarcher.App com.goldenaarcher.App
Hello World!
最后就使用 java -cp
的指令运行一下打包好的 class 文件即可
plugins & goals & parameters
基础的语法为:plugin-prefix:goal
,如 mvn compiler:compile
,这里的插件就是 compiler,goal 就是 compile, mvn clean:clean
同理
plugins 是一个或多个相关任务(task)的集合,比如说一直使用的 mvn clean
中的 plugin 就是 maven-clean-plugin
,运行 mavn clean
的时候实际上指定的是 maven-clean-plugin
中的 clean
goal(也叫 MOJO)
比较常见的 maven goal 有 来自 mmaven-compiler-plugin
的 compile
, maven-surefire-plugin
中的 test
,来自各种不同插件中的 package(war 和 jar 的插件就不一样),以及上面提到的 clean。
parameters 就是上面使用的如 -DgroupId=com.goldenaarcher
,语法为 -D<parameterName>=<value>
,这个 param 意思就是指定 groupId
为 com.goldenaarcher
lifecycle & phases & goals
POM 是 Project Object Mode,是 maven 最基础的工作组件。
lifecycle
maven 的生命周期有三个:
-
default
管理项目的部署
-
clean
管理项目的清理
-
site
管理项目文档网页的创建
生命周期主要是定义 goal 执行的顺序,以便可以完成特定的 task,官方文档说的更直接,就是说……只要学一点指令 POM 就保证结果令人满意
phase
phase 是 lifecycle 的步骤,每个 phase 代表了生命周期特定的阶段
官方文档中是提供了 default
中的一些 phase,如:
-
validate
验证项目结构是否正确,所有必要信息是否都有提供
-
compile
编译源代码
-
test
更具对应的测试框架执行源码的测试,这段代码不应当被打包到部署中去
顺便这一步可跳过
-
package
将编译好的源码和包打包成合适的格式,如 jar、war
-
verify
执行一些必要的集成测试区保证包的合规性和质量
-
install
安装所有需要的依赖,这可以是从 central repo 上拉下来的,也可以是本地的项目
-
deploy
在打包环境下完成,将最终成品包覆知道远程 repo 进行共享
当单独执行某一个 phase 的时候,其前置 phase 也会被执行,如执行 mvn package
,它也会先执行 validate
, compile
, test
与 goal 的关系
每个打包阶段都是由不同的 goal 构成的,但是 goal 具有可以被单独运行的独立性,而不需要单独打包到指定的 lifecycle 中
完成先清理项目,再完成依赖的复制,最后执行打包操作的指令为:
❯ mvn clean dependency:copy-dependencies package
顺便简单说一下 clean
,maven 本身会执行 clean
这个生命周期,默认情况下会执行 clean
这个 phase,这个 phase 是被绑定到 maven-clean-plugin:clean
,即 插件maven-clean-plugin
上的 clean
这个 goal 上。
对于实际操作上来说,执行 maven-clean-plugin:clean
并不需要调动 clean
这个生命周期,但是反过来是不成立的。
coordinates
coordinates
指的就是一些可以辨识项目的集合,它又以下几个部分组成:
-
groupId
通常意义上由公司域名+特有的项目名称组成,如 hadoop 的 groupId 就是
org.apache.hadoop
-
artifactId
打包的 jar 名称,不包含版本,如 hadoop 下的 Common 名称就是
hadoop-common
-
version
版本呢
-
packaging
指定项目的类型,如 jar、war 等,不设置的默认值为 jar
repositories
下载包的 central repo 地址, 默认的下载地址为 https://repo.maven.apache.org/maven2/
具体看各个公司,比如我们公司就在 nexus 上做了自己的镜像库
eclipse 中折腾一下 maven
这里用 eclipse,intellij 之后搞,下载了一个 spring 插件后一直要登陆,就横帆……
创建一个新的 maven 项目
-
选择新建一个 maven 项目
-
填写信息,如 maven 项目目录在哪之类的
-
选择创建的类型,这里用 archetypes-quickstart
-
填写项目信息
package 的默认名称是
group id
+artifact id
,可以按需修改 -
点击完成
这是命令行上的一些指令:
[[1;34mINFO[m] ----------------------------------------------------------------------------
[[1;34mINFO[m] Using following parameters for creating project from Archetype: maven-archetype-quickstart:1.4
[[1;34mINFO[m] ----------------------------------------------------------------------------
[[1;34mINFO[m] Parameter: groupId, Value: com.goldenaarcher.product
[[1;34mINFO[m] Parameter: artifactId, Value: productservices
[[1;34mINFO[m] Parameter: version, Value: 0.0.1-SNAPSHOT
[[1;34mINFO[m] Parameter: package, Value: com.goldenaarcher.product
[[1;34mINFO[m] Parameter: packageInPathFormat, Value: com/goldenaarcher/product
[[1;34mINFO[m] Parameter: package, Value: com.goldenaarcher.product
[[1;34mINFO[m] Parameter: groupId, Value: com.goldenaarcher.product
[[1;34mINFO[m] Parameter: artifactId, Value: productservices
[[1;34mINFO[m] Parameter: version, Value: 0.0.1-SNAPSHOT
[[1;34mINFO[m] Project created from Archetype in dir: /Users/usr/study/maven/productservices
[[1;34mINFO[m] [1m------------------------------------------------------------------------[m
[[1;34mINFO[m] [1;32mBUILD SUCCESS[m
[[1;34mINFO[m] [1m------------------------------------------------------------------------[m
[[1;34mINFO[m] Total time: 44.738 s
[[1;34mINFO[m] Finished at: 2023-09-11T11:04:01-04:00
[[1;34mINFO[m] [1m------------------------------------------------------------------------[m
修改 java 编译版本
默认的 pom 是这样的
<?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>productservices</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>productservices</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>Ï
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
可以看到 java 的版本是 1.7,这个就根据项目需求进行修改,可以直接修改 properties 里的版本,或者是用下面这个配置也可以:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
随后又见项目选择更新一下 maven 项目即可:
我是记得有个配置可以自动更新来,不知道是不是记错了
Java 实现
这里不太涉及 maven,带一下就过去了
感兴趣 b 站也好那里也好,找一下 servlet/spring 相关的实现也行……我暂时还没复习到那,复习了再做笔记
创建 Data Access Layer
这里折腾的都是一些 Java 方面的配置
src/main 下的结构如下:
❯ tree productservices/src/main
productservices/src/main
└── java
└── com
└── goldenaarcher
└── product
├── dao
│ ├── ProductDAO.java
│ └── ProductDAOImpl.java
└── dto
└── Product.java
7 directories, 3 files
完整的代码如下:
-
Product.java
package com.goldenaarcher.product.dto; public class Product { private int id; private String name; private String description; private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
-
ProductDAO.java
package com.goldenaarcher.product.dao; import com.goldenaarcher.product.dto.Product; public interface ProductDAO { void create(Product product); Product read(int id); void update(Product product); void delete(int id); }
-
ProductDAOImpl.java
package com.goldenaarcher.product.dao; import com.goldenaarcher.product.dto.Product; public class ProductDAOImpl implements ProductDAO { @Override public void create(Product product) { // TODO Auto-generated method stub } @Override public Product read(int id) { // TODO Auto-generated method stub return null; } @Override public void update(Product product) { // TODO Auto-generated method stub } @Override public void delete(int id) { // TODO Auto-generated method stub } }
实现 data access layer
package com.goldenaarcher.product.dao;
import java.util.HashMap;
import java.util.Map;
import com.goldenaarcher.product.dto.Product;
public class ProductDAOImpl implements ProductDAO {
Map<Integer, Product> products = new HashMap<>();
@Override
public void create(Product product) {
products.put(product.getId(), product);
}
@Override
public Product read(int id) {
return products.get(id);
}
@Override
public void update(Product product) {
// TODO Auto-generated method stub
}
@Override
public void delete(int id) {
// TODO Auto-generated method stub
}
}
更新 JUnit
这里补一下 [JUnit] JUnit5 基础 1 - Junit5 结构 与 断言的使用 里没提到的配置,我之前知道 junit5 是有个合集,不用单独下载三四个依赖,但是找了下自己笔记里没写……
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
版本可以选择用当前最新的稳定更新,或者这个……短期之内应该不会差太多。然后跑下 mvn clean install
,有可能也需要更新 maven-surefire-plugin
这个版本去跑对应的测试
重复一下,maven-surefire-plugin
是 test
这个 goal 的插件
执行测试
这里写一点测试主要是为了看下跑 mvn install
会执行测试
package com.goldenaarcher.product.dao;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import com.goldenaarcher.product.dto.Product;
public class ProductDAOImplTest {
@Test
public void createShouldCreateAProduct() {
ProductDAO dao = new ProductDAOImpl();
Product product = new Product();
product.setId(1);
product.setName("Iphone");
product.setDescription("It's awesome");
product.setPrice(800);
dao.create(product);
Product result = dao.read(1);
assertNotNull(result);
assertEquals("Iphone", result.getName());
}
}
结果:
[[1;34mINFO[m] -------------------------------------------------------
[[1;34mINFO[m] T E S T S
[[1;34mINFO[m] -------------------------------------------------------
[[1;34mINFO[m] Running com.goldenaarcher.product.dao.[1mProductDAOImplTest[m
[[1;34mINFO[m] [1;32mTests run: [0;1;32m1[m, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.018 s - in com.goldenaarcher.product.dao.[1mProductDAOImplTest[m
[[1;34mINFO[m]
[[1;34mINFO[m] Results:
[[1;34mINFO[m]
[[1;34mINFO[m] [1;32mTests run: 1, Failures: 0, Errors: 0, Skipped: 0[m
跳过测试
命令行的 flag:
❯ mvn install -DskipTests
Eclipse 里的设置:
这里 user settings 不需要加值,默认会显示 m2 下面的配置文件
执行结果:
[[1;34mINFO[m] [1m--- [0;32mmaven-surefire-plugin:2.22.1:test[m [1m(default-test)[m @ [36mproductservices[0;1m ---[m
[[1;34mINFO[m] Tests are skipped.
创建 Business Obuect Layer
此时的结构:
❯ tree productservices/src/main
productservices/src/main
└── java
└── com
└── goldenaarcher
└── product
├── bo
│ ├── ProductBO.java
│ └── ProductBOImpl.java
├── dao
│ ├── ProductDAO.java
│ └── ProductDAOImpl.java
└── dto
└── Product.java
8 directories, 5 files
代码实现:
-
ProductBO.java
package com.goldenaarcher.product.bo; import com.goldenaarcher.product.dto.Product; public interface ProductBO { void create(Product product); Product findProduct(int id); }
-
ProductBOImpl.java
package com.goldenaarcher.product.bo; import com.goldenaarcher.product.dao.ProductDAO; import com.goldenaarcher.product.dao.ProductDAOImpl; import com.goldenaarcher.product.dto.Product; public class ProductBOImpl implements ProductBO { private static ProductDAO dao = new ProductDAOImpl(); @Override public void create(Product product) { dao.create(product); } @Override public Product findProduct(int id) { return dao.read(id); } }
添加 spring 依赖
这里也不会过多的折腾配置……下次一定
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.11</version>
</dependency>