软件工程:为了能够实现软件的流水线生产,在设计和构建软件时能够有一种规范和工程化的方法,人们便提出了软件工程概念

maven简介

maven:项目构建工具

maven三大功能:

  • 管理依赖,并自动下载、
  • 管理项目信息
  • 自动构建
    • 自动测试
    • 自动编译程序
    • 自动打包文件,形成jar文件或war文件
    • 自动部署

构建:构建是面向过程的,完成项目代码的编译,测试,运行,打包,部署等等。

maven支持的构建包括:

  1. 清理:把之前项目编译的东西删掉,为新的编译代码做准备
  2. 编译:批量把程序源代码编译为可执行文件
  3. 测试:批量执行测试程序代码,验证功能是否正确
  4. 报告:生成测试结果报告
  5. 打包:把项目中的资源文件放到一个压缩文件中,这个压缩文件就是项目的结果文件。
  6. 安装:把打包生成的结果文件安装到本地仓库
  7. 部署:把程序安装好,可以直接执行

maven核心概念

  • POM
  • 约定的目录结构
  • 坐标
  • 依赖管理
  • 仓库管理
  • 生命周期
  • 插件和目标
  • 继承
  • 聚合

POM

pom.xml:项目对象模型文件。maven把一个项目当作一个模型使用,可以构建项目的过程,管理jar依赖
(类似于docker-compose.yaml文件和docker-compose之间的关系)

字段

  • modelVersion:maven模型的版本,一般都是4.0.0
  • groupId:组织ID。一般是公司域名的倒写吗,格式可以是:
    • 域名倒写:com.baidu
    • 域名倒写+项目名:com.baidu.appolo
  • artifactId:项目名称。也是模块名称,对应groupId中项目中的子项目
  • version:版本号。如果是不稳定版本,通常在版本后带一个-SNAPSHOT

坐标:上述三个字段构成坐标,用于唯一标志一个项目

1
2
3
<groupId>ai.ones</groupId>
<artifactId>JavaSDK</artifactId>
<version>1.0-SNAPSHOT</version>
  • packaging:项目打包后压缩文件的拓展名,可以是jar(默认值),war,rar,ear,pom
  • dependencies和dependency:依赖配置。依赖的配置就是通过坐标来定位的,由此我们不难看出,maven把所有jar包也都是为项目存在了。
  • properties:定义配置属性。例如project.build.sourceEncoding(项目构建源码的编码方式)可以设置为utf-8。也可以定义相关构建版本号,便于日后统一升级。
1
2
3
4
5
6
7
8
<properties>
<!-- 构建采用utf8 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 使用1.7版本的maven编译source -->
<maven.compiler.source>1.7</maven.compiler.source>
<!-- 使用1.7版本的maven运行target -->
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
  • build:与构建相关的配置,例如设置编译插件的jdk版本
  • parent:继承。如果多个模块都需要声明相同的配置,例如groupId,version,有相同的依赖,或者相同的组件配置等等,也有类似于java的继承机制,用perent声明要继承的父工程的pom配置
  • modules:聚合。在maven的多模块开发中,为了统一构建整个项目的所有模块,可以提供一个额外的模块,该模块打包方式为pom,并且在使用modules聚合的其他模块,这样通过本模块就可以意见自动识别模块间的依赖关系来构建所有模块。(类似于docker-compose.yaml文件和Dockerfile文件的关系)

示例:

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?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.ones</groupId>
<artifactId>JavaSDK</artifactId>
<version>1.0-SNAPSHOT</version>

<name>JavaSDK</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>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.7.04</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.9.0</version>
</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>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.ones.App</mainClass>
<arguments>
<argument>foo</argument>
<argument>bar</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

约定的目录结构

maven项目的目录和文件的位置都是规定好的。

1
2
3
4
5
6
7
8
9
10
11
12
hello-world
|-- src
| |-- main # 主程序java代码和配置文件
| | |-- java # 程序java源码
| | | |-- com
| | | |-- ones
| | | |-- hellowlord.java
| | |-- resources # 配置文件
| |-- test # 测试代码文件
| |-- java
| |-- resources
|-- pom.xml # maven的核心文件

之后在hello-world目录执行

1
mvn compile

便会编译src/main目录下的所有java文件。然后在项目根目录生成一个target目录。此目录就是结果目录,maven编译的java程序生成的class文件都放在了target目录中

最后执行

1
2
cd target/classes
java com.ones.helloworld

即可执行java程序。

坐标

一个唯一的字符串,用于表示资源的位置。

一个坐标表示如下:

1
2
3
<groupId>ai.ones</groupId>
<artifactId>JavaSDK</artifactId>
<version>1.0-SNAPSHOT</version>

artifactId和version决定了jar包的名称

依赖管理

管理项目可以使用的jar文件。

依赖表示如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.7.04</version>
</dependency>
</dependencies>

仓库管理

maven使用的jar项目使用的jar的存放位置。

配置本地仓库地址:

修改maven下载地址/conf/settings.xml<localZRepository>配置

生命周期

maven构建项目的过程。maven构建的生命周期的每个阶段都有特定的插件和命令来完成。

生命周期

  1. clean
  2. complie
  3. test-compile
  4. test
  5. package
  6. install
  7. deploy

对应的构建=命令:

  • mvn clean:清理。会删除原来编译的测试目录,即target目录。但是已经install到仓库里的包不会删除。
  • mvn complie:编译主程序。会在当前目录下生成一个target目录,里面存放编译主程序之后生成的字节码文件。
  • mvn test-compile:编译测试程序。会在当前目录下生成一个tatget目录,里面存放编译测试程序之后生成的字节码文件。
  • mvn test:测试。会生成一个surefire-reports,保存测试结果。
  • mvn package:打包主程序。会编译,编译测试,并且按照pom.xml配置把主程序打包生成jar包或者war包。
  • mvn install:安装主程序。会把本工程打包,并且按照本工程的坐标保存到本地仓库中。
  • mvn deploy:部署主程序。会把本工程打包,按照本工程的坐标保存到本地库中,并且还会保存到私服仓库中,还会自动把项目部署到web容器中。

注意,maven的生命周期是按序全部执行的。

当我们执行mvn test ,会先执行mvn cleanmvn compliemvn test-complie

插件

执行maven构建的时候用的工具。

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
 <build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<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-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.ones.App</mainClass>
<arguments>
<argument>foo</argument>
<argument>bar</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

Maven示例:单元测试

使用junit。junit是一个专门测试的框架,其测试内容:类中的方法,每个方法都是独立测试的。(方法是测试的基本单位,也就是测试单元)

  1. pom.xml加入依赖

    1
    2
    3
    4
    5
    6
    7
    8
    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
  2. 在项目中的src/test/java/目录下,创建测试程序。

  3. 编译主程序,执行

    1
    2
    mvn clean
    mvn complie
  4. 编译测试文件,执行

    1
    mvn test-complie
  5. 执行测试:

    1
    mvn test
  6. 打包:

    1
    mvn package
  7. 安装

    1
    mvn install
  8. 部署

    1
    mvn deploy

maven在idea中的应用

初始化

  1. file–Settings–build,excution,deployment–build tools–maven
    • Maven home:maven的安装目录
    • User settings file:maven安装目录conf/settings.xml
    • local repository:本机仓库地址
  2. file–Settings–build,excution,deployment–build tools–maven–runner:
    • jre:选择jre路径即可
    • vm options:-DarchetypeCatalog=internal。(maven项目创建时,会联网下载模板文件,使用存缓)

使用模版创建项目

  1. File–new–module…–maven
  2. 选择模版maven-archetype-quickstart

maven依赖管理

  1. 依赖的范围:表示依赖使用的范围,也就是说maven构建项目的哪些阶段中起作用,使用<scope>表示的。

  2. scope可选值为:

    • compile(默认值,范围是全生命周期皆可使用),
    • test,
    • provided(在部署时由服务器提供,项目本身不需要自带)
    1
    2
    3
    4
    5
    6
    7
    <!--  junit只在测试阶段才能使用和起作用  -->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
    </dependency>

maven常用设置

属性设置

properties设置maven的属性:

1
2
3
4
5
<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>

全局变量

一般用来定义依赖的版本号。当你的项目中要使用多个相同的版本号时,就可以先使用全局变量定义,再使用${标签名}使用变量的值

  • 自定义属性:

    1. <properties>标签通过自定义标签来声明变量
    2. 在pom.xml文件中其他位置,使用${标签名}使用变量的值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <properties>
    <sprint.version>5.1.0</sprint.version>
    </properties>

    <dependencies>
    <dependency>
    <groupId>sprint.sprintframework</groupId>
    <artifactId>sprint-core</artifactId>
    <version>${sprint.version}</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.sprintframework</groupId>
    <artifactId>sprint-aop</artifactId>
    <version>${sprint.version}</version>
    </dependency>
    <dependency>
    <groupId>org.sprintframework</groupId>
    <artifactId>sprint-context</artifactId>
    <version>${sprint.version}</version>
    </dependency>
    </dependencies>

指定资源位置

  • 默认没有使用resources的时候,maven执行编译代码的时候,会把src/main/resources目录下的文件拷贝到target/classes目录中。对于src/main/java目录下的非java文件不处理,不拷贝到target/classes目录中
  • 现在程序有需要把一些文件放在src/main/java目录下,当执行java程序时,需要用到src/main目录中的文件,就需要告诉maven在执行mvn compile src/main/java目录下的程序时,需要把文件一同拷贝到target/classes目录中
  • 此时就需要在<build>中加入<resources>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<build>
<resources>
<resource>
<directory>src/main/java</directory>

<!-- 包括目录下的.properties,xml文件都会被扫描到 -->
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>

<!-- 不启用过滤器 -->
<filtering>false</filtering>

</resource>
</resources>
</build>