Maven翻译为“专家”,“内行”。Maven是Apache下的一个纯java开发的开源项目,它是一个项目管理工具,使用Maven对java项目进行构建、依赖管理。当前使用Maven的项目在持续增长。
Maven
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。
此外,Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等。
Maven的安装
- 下载地址
- 解压后目录
bin
: 可运行程序- mvn: 以run方式运行项目
- mvnDebug: 以debug方式运行项目
boot
: 类加载器conf
: Maven配置文件lib
: Maven依赖的jar包
- 安装(安装目录最好英文)
传统项目的构建过程
- 构建过程
- 新建
Java Web
项目 - 导入jar包, 编写源码以及配置文件
- 对源码进行编译, 精java文件编译成class文件
- 执行Junit单元测试
- 将工程打包成war包, 部署到服务器
- 新建
Maven项目的构建过程
Maven将项目构建的过程进行标准化,每个阶段使用一个命令完成.
清理——>编译——>测试——>报告——>打包——>部署
清理阶段对应Maven的命令是mvn clean
,清理输出的class文件
编译阶段对应Maven的命令是mvn compile
,将java代码编译成class文件。
打包阶段对应Maven的命令是mvn package
,java工程可以打成jar包,web包可以打成war包
运行一个Maven工程(web工程)需要一个命令:mvn tomat:run
Maven工程构建的优点:
1、一个命令完成构建、运行,方便快捷。
2、Maven对每个构建阶段进行规范,非常有利于大型团队协作开发。
依赖管理
什么是依赖管理?就是对项目所有依赖的jar包进行规范化管理。
传统项目的依赖管理
传统的项目工程要管理所依赖的jar包完全靠人工进行,程序员从网上下载jar包添加到项目工程中,如下图:程序员手工将Hibernate、struts2、spring的jar添加到工程中的WEB-INF/lib目录下。
手工拷贝jar包添加到工程中的问题是:
1、没有对jar包的版本统一管理,容易导致版本冲突。
2、从网上找jar包非常不方便,有些jar找不到。
3、jar包添加到工程中导致工程过大。
Maven的依赖管理
Maven项目管理所依赖的jar包不需要手动向工程添加jar包,只需要在pom.xml(Maven工程的配置文件)添加jar包的坐标,自动从Maven仓库中下载jar包、运行.
使用Maven依赖管理添加jar的好处:
1、通过pom.xml文件对jar包的版本进行统一管理,可避免版本冲突。
2、Maven团队维护了一个非常全的Maven仓库,里边包括了当前使用的jar包,Maven工程可以自动从Maven仓库下载jar包,非常方便。
Maven仓库
- 本地仓库: 用来存储从远程仓库或中央仓库下载的插件和jar包,项目使用一些插件或jar包,优先从本地仓库查找
- 在maven安装目录下的有
conf/setting.xml
文件,此setting.xml文件用于maven的所有project项目,它作为maven的全局配置。1
<localRepository>你的本地查看目录</localRepository>
- 在maven安装目录下的有
- 远程仓库: 如果本地需要插件或者jar包,本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网内也可以在局域网内。
- 中央仓库: 在Maven软件中内置一个远程仓库地址 ,它是中央仓库,服务于整个互联网,它是由Maven团队自己维护,里面存储了非常全的jar包,它包含了世界上大部分流行的开源项目构件。
配置Maven中央仓库
由于国内墙的原因, 访问默认的中央仓库很慢, 所以需要配置一些Maven的国内镜像, 如果没有配置mirror, 默认使用中央仓库,
- 可以修改的地方
- Maven安装目录/conf/setting.xml
- 用户名/.m2/setting.xml
- 添加下面的内容
1
2
3
4
5
6
7
8<!-- 阿里云仓库 -->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<!--使用那个public的地址, 导致Intellij IDEA中更新索引失败-->
<url>http://maven.aliyun.com/nexus/content/repositories/central</url>
</mirror> - 字段说明
- id,name:镜像的唯一标识和用户友好的名称;
- url:镜像的url,用于代替原始仓库的url;
- mirrorof:使用镜像的仓库的id,可以使用下面匹配属性:
*
:匹配所有仓库id;external:*
:匹配所有仓库id,除了那些使用localhost或者基于仓库的文件的仓库;repo1,repo2
;多个仓库id之间用逗号分隔!repol
:表示匹配所有仓库,除了repol。
Maven项目目录结构
Project
|-src
| |-main
| | |-java —— 存放项目的.java文件
| | |-resources —— 存放项目资源文件,如spring, hibernate配置文件
| | |-webapp —— webapp目录是web工程的主目录
| | | |-WEB-INF
| | | | |-web.xml
| |-test
| | |-java ——存放所有测试.java文件,如JUnit测试类
| | |-resources —— 测试资源文件
|-target —— 目标文件输出位置例如.class、.jar、.war文件(运行mvn clean
后会删除)
|-pom.xml —— maven项目核心配置文件
Maven常用命令
符合Maven项目目录结构的工程可以使用Maven命令.
- compile:
mvn compile
, 会把src/main/java
目录下的文件编译成class文件并输出到target目录中 - test:
mvn test
, 会运行src/test/java
下的单元测试类 - clean:
mvn clean
, 会删除src/target
目录 - package:
mvn package
, 将java工程打包成jar包, web工程打包成war包. - install:
mvn install
, maven打成jar包或war包发布到本地仓库。
创建Maven项目
- Eclipse
- Preference—Maven—Installations中选择或者新建Maven版本
- Preference—Maven—User Setting中设置配置文件
- 选择
Maven Project
, 取消选择Create a simple project
Maven-archetype-quickstart
: 创建一个Maven的Java工程Maven-archetype-webapp
: 创建一个Maven的Web工程
- 初始化项目, 有的目录没有需要手动创建
- Intellj IDEA
command ,
——Maven
——Importing
——勾选Import Maven projects automaticlly
command ,
——Maven
——Repositories
——Update
——更新中央仓库索引到本地- 选择
Maven
- 勾选
Create from archetype
Maven-archetype-quickstart
: 创建一个Maven的Java工程Maven-archetype-webapp
: 创建一个Maven的Web工程
- 初始化项目, 有的目录没有需要手动创建
- 解决不能创建class和package方法
src/main/java
目录不能创建class和package, 可以右键——Make Directory as
——Sources Root
即可src/test/java
目录不能创建class和package, 可以右键——Make Directory as
——Test Sources Root
即可
- 配置
pom.xml
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<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.coppco</groupId>
<artifactId>mavenTest</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mavenTest Maven Webapp</name>
<url>http://maven.apache.org</url>
<!--配置依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<!--只在测试时起作用-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!--只在运行时不起作用, 因为tomcat中有这个jar包-->
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>mavenTest</finalName>
</build>
</project> - 依赖范围
- compile: 编译范围,指A在编译时依赖B,此范围为默认依赖范围。编译范围的依赖会用在编译、测试、运行,由于运行时需要所以编译范围的依赖会被打包。
- provided: provided依赖只有在当JDK或者一个容器已提供该依赖之后才使用, provided依赖在编译和测试时需要,在运行时不需要,比如:servlet api被tomcat容器提供。
- runtime: runtime依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如:jdbc的驱动包。由于运行时需要所以runtime范围的依赖会被打包。
- test: test范围依赖 在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用,比如:junit。由于运行时不需要所以test范围依赖不会被打包。
- system: system范围依赖与provided类似,但是你必须显式的提供一个对于本地系统中JAR文件的路径,需要指定systemPath磁盘路径,system依赖不推荐使用。
Maven项目分模块
实际开发中, 一般创建Maven项目时都是分模块的,即是一个父工程中包含若干个子module.
- 1、先创建一个父工程, 打包方式为pom, Eclipse勾选
Create a simple project
, Intellij IDEA不要勾选Create from archetype
.- 1.1、父工程中pom.xml中引入的依赖jar包, 所有子工程都可以使用. 一般把共同的jar包放在父工程的pom.xml中.
- 2、为父工程添加子module,
new
—Maven Module
,parent Project
必选要设置为父工程的GroupId+ArtifactId+version.- 2.1、dao-module可以选择打包模式为jar
- 2.3、添加完成module后, 父工程的pom.xml和子module的pom.xml中会相会有对方的信息.
1
2
3
4
5
6
7
8
9
10
11
12<!--父工程中-->
<modules>
<module>web-service</module>
<module>web-app</module>
<module>web-dao</module>
</modules>
<!--子工程中-->
<parent>
<artifactId>day45-crm</artifactId>
<groupId>com.coppco</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- 3、引入依赖以及依赖版本冲突
- 3.1、依赖调解原则
- 第一声明者优先原则: 在pom文件定义依赖,先声明的依赖为准。
- 路径近者优先原则: a依赖junit4.0, a继承b, 而b依赖junit4.9, 那么相对于a, 最近的路径是junit4.0.
- 3.1、也可以通过配置
dependency
—exclusions
来排除冲突的jar包1
2
3
4
5
6
7
8
9
10
11
12<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.24</version>
<!--排除exclusions中的jar包-->
<exclusions>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>javassist</groupId>
</exclusion>
</exclusions>
</dependency> - 3.3、版本锁定: 面对众多的依赖,有一种方法不用考虑依赖路径、声明优化等因素可以采用直接锁定版本的方法确定依赖构件的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<dependencyManagement>
<dependencies>
<!--这里锁定版本为4.2.4 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>- 3.3.1、在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添
标签. 1
2
3
4
5
6
7
8
9
10
11<dependencies>
<!--这里是添加依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
- 3.3.1、在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添
- 3.1、依赖调解原则
- 4、完整的SSH框架, pom.xml如下
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350<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.coppco</groupId>
<artifactId>day45-crm</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<!-- 子module -->
<modules>
<module>web-service</module>
<module>web-app</module>
<module>web-dao</module>
</modules>
<!-- 为了确定每个框架的版本号 -->
<!-- 锁定版本 -->
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<struts2.version>2.3.24</struts2.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<shiro.version>1.2.3</shiro.version>
<cxf.version>3.0.1</cxf.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.6</mysql.version>
</properties>
<!-- 锁定版本,struts2-2.3.24、spring4.2.4、hibernate5.0.7 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.37</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.1</version>
</dependency>
<!-- <dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency> -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- shiro -->
<!-- apache shiro dependencies -->
<!-- <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>${shiro.version}</version>
</dependency> -->
<!-- spring -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- struts2 begin -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
<exclusions>
<exclusion>
<artifactId>javassist</artifactId>
<groupId>javassist</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${struts2.version}</version>
</dependency>
<!-- struts2 end -->
<!-- hibernate begin -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- <dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency> -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!-- Javamail -->
<!-- <dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.4</version>
</dependency> -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.xfire</groupId>
<artifactId>xfire-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
<!-- <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.11</version>
</dependency> -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- <dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.4.0</version>
</dependency> -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.6</version>
</dependency>
</dependencies>
<build>
<finalName>day45-crm</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project> - 4、不同子模块之间依赖需要配置pom.xml
1
2
3
4
5
6
7
8<!--例如service模块 需要依赖 dao模块-->
<dependencies>
<dependency>
<groupId>com.coppco</groupId>
<artifactId>web-dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>