Maven

To Do

  • 聚合与继承
    • 对于聚合模块来说,它知道有哪些被聚合的模块,但那些被聚合的模块不知道这个聚合模块的存在
    • 对于继承关系的父 POM来说,它不知道有哪些子模块继承与它,但那些子模块都必须知道自己的父 POM是什么
    • 聚合 POM与继承关系中的父POM的 packaging都是pom
  • SNAPSHOT与RELEASE版本之争
    • NAPSHOT依赖泛指以-SNAPSHOT为结尾的版本号
    • 所有非-SNAPSHOT结尾的版本号则都被认定为RELEASE版本,即正式版
    • 在开发期间,一般使用SNAPSHOT,在生产期间,更多地依赖RELEASE版本模块
  • 私服访问http://localhost:8081弹框:正在请求您的用户名和密码。该网站称:“XDB”
    oracle安装过程中默认安装了XDB数据库,占用了8081端口,端口冲突

一. Maven简介

Maven 是apache下的开源项目,项目管理工具,管理 java 项目

  • 项目对象模型 (Project Object Model)
    POM对象模型,每个maven工程中都有一个pom.xml文件,定义工程所依赖的jar包、本工程的坐标、打包运行方式
  • 依赖管理系统(基础核心 )
    maven 通过坐标对项目工程所依赖的jar包统一规范管理
  • maven 定义一套项目生命周期
    清理、初始化、编译、测试、报告 、打包、部署、站点生成
  • 一组标准集合
    强调:maven工程有自己标准的工程目录结构、定义坐标有标准
  • maven 管理项目生命周期过程都是基于插件完成的

1. Maven仓库

  • 中央仓库
    即远程仓库,仓库中jar由专业团队(maven 团队)统一维护:中央仓库的地址
  • 本地仓库
    相当于缓存,工程第一次会从远程仓库(互联网)去下载jar包,将jar包存在本地仓库(在程序员的电脑上),第二次不需要从远程仓库去下载。先从本地仓库找,如果找不到才会去远程仓库找
  • 私服
    在公司内部架设一台私服,其它公司架设一台仓库,对外公开

2. Maven环境搭建

  • 本地仓库配置
    打开 maven 的安装目录中 conf/ settings.xml 文件,在这里配置本地仓库
1
2
<!-- 配置本地仓库的目录为 D:\repository_ssh -->
<localRepository>D:\repository_ssh</localRepository>

3. Maven入门

3.1 创建Maven工程

  • 工程坐标(maven 对所有工程管理基于坐标进行管理)
    • Group Id:项目的名称,项目名称以域名的倒序
    • Artifact Id:模块名称(子项目名称)
    • Version:模块的版本,snapshot(快照版,没有正式发行)、release(正式发行版本)
    • Packaging:打包方式,jar(普通java项目),pom(pom工程),war(web项目)
  • 工程目录结构
    • /src/main/java 主体程序 java 源文件(不要放配置文件)
    • /src/main/resources 主体程序所需要的配置文件(不要放 java 文件)
    • /src/test/java 单元测试程序 java 源文件
    • /src/test/resources 单元测试程序所用的配置文件
    • /target 编译输出目录
    • pom.xml Maven 进行工作的主要配置文件

3.2 设置编译版本

  • 将maven-compiler-plugin设置为2.3.2版本
    本步骤可以通过右键工程Maven->add plugin,然后搜索并安装
  • Maven工程默认是JDK1.5,我们需要将编译版本改为JDK1.7 【勿忘
    本步骤手动添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 下述信息配置在pom.xml中【并对Maven工程Update Project】-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>

3.3 添加依赖

Eclipse:Maven – > Add Dependency【通过下面的搜索框进行模糊搜索
经过上述操作,pom.xml会自动增添配置信息;Maven Dependecies目录下会自动增添Jar包(包含依赖包...)

4. Maven命令

Maven 有三套相互独立的生命周期,分别是:clean、default、site

  • clean 主要是清理项目
  • default 是 Maven 最核心的的构建项目
  • site 是生成项目站点

核心命令
【run as --> maven build(在Goals中输入命令)】

  • compile编译
  • clean清理,将 target 下的 class 文件清理
  • test执行单元测试类,执行 src/test/java 下的类
  • package将 java 工程打成 jar、war
  • install安装命令,将将程的 jar 发布到本地仓库发布到仓库,目录按照本工程定义的坐标生成目录
  • clean tomcat7:run:清理之前的内容,并启动tomcat7服务器(tomcat默认为6)
  • package Dskiptests跳过测试代码进行打包(避免由于测试代码中有错导致打包不成功)

    其实我们所执行的这些命令是对 maven 原生命令的封装,我们可以在命令提示符下直接通过这些命令来对代码进行编译打包等操作

二. 创建 SSH2 工程(★)

用 SSH2 集成框架搭建mavenweb工程,并以war形式打包

1. 创建war工程

  • 创建war工程(打包方式选择war)
  • 手动添加 web.xml
  • 添加插件【编译插件,tomcat插件
  • 添加servlet-api依赖
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
<!-- 添加插件 -->
<build>
<plugins>
<!-- 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
<!-- 添加servlet-api的依赖 -->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<!-- 版本 -->
<version>2.5</version>
<!-- 作用域 -->
<scope>provided</scope>
</dependency>
</dependencies>

2. 添加SSH依赖

  • servlet依赖
  • Hibernate依赖
  • struts2依赖
  • Spring依赖
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
<!-- 将各种版本信息用变量保存,然后引用 【变量】-->
<properties>
<hibernate.version>5.0.7.Final</hibernate.version>
<spring.version>4.2.4.RELEASE</spring.version>
<struts.version>2.3.24</struts.version>
</properties>
<!-- 依赖 -->
<dependencies>
<!-- servlet: 提供servlet-api,处理请求【必须指定scope】-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope> <!--依赖范围-->
</dependency>
<!-- hibernate核心包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!--spring核心及相关包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</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-context</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-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring用的aspectj-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!-- struts2核心及相关包-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts.version}</version>
<exclusions> <!-- ?? -->
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>${struts.version}</version>
</dependency>
<!-- mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--jstl包 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>

3. 配置文件

参照SSH整合:

  • web.xml:【置于Src下的main/webapp】:配置监听器自动加载applicationContext、拦截器加载struts、拦截器控制数据库session延迟问题
  • struts.xml:【置于Java Resources下的src/main/resource】:工程相关常量
  • hibernate.cfg.xml
  • applicationContext.xml【置于Java Resources下的src/main/resource】:一言难尽

4. 包结构

  • Java Resources下的src/main/java下配置包结构,存放java源代码
  • Java Resources下的src/main/resource下配置包结构,存放配置文件

三. 聚合与继承


(注:在现有的多模块maven项目中,一般一个POM既是聚合POM,又是父POM)

1. 聚合

多模块

把多个模块或项目聚合到一起,我们可以建立一个专门负责聚合工作的Maven工程

  • 该聚合模块本身也为一个 Maven 项目,它必须有自己的POM
  • 其打包方式必须为pom
  • 版本:聚合模块的版本和被聚合模块版本一致
  • 相对目录:每个 module 的值都是一个当前 POM 的相对目录
  • 目录名称:为了方便的快速定位内容,模块所处的目录应当与其 artifactId一致(Maven 约定而不是硬性要求)
  • 聚合模块减少的内容:聚合模块的内容仅仅是一个 pom.xml 文件,它不包含 src/main/Java、src/test/java 等目录,因为它只是用来帮助其它模块构建的工具,本身并没有实质的内容
  • 聚合模块和子模块的目录:他们可以是父子类,也可以是平行结构,当然如果使用平行结构,那么聚合模块的 POM 也需要做出相应的更改

2. 继承

针对plugin和dependency而言

  • 一般为父子结构
  • 作为父模块的 POM,其打包类型也必须为 POM
  • 父模块只是为了帮助我们消除重复,所以它也不需要 src/main/java、src/test/java 等目录
  • 子模块省略groupId 和 version:使用了继承的子模块中可以不声明 groupId和 version, 子模块将隐式的继承父模块的这两个元素

3. 聚合VS继承

聚合和继承通常是结合使用的,但是其作用是不同的

  • 聚合是将多个模块的工程汇聚到一起
  • 继承则是指明某个模块工程要继承另一个模块功能

四. 构建多模块Maven工程

1. 构建父工程(Maven Project)

父工程的打包方式必须为pom

2. 创建子模块(Maven Module)

配置文件同时也要分离存放在各模块

  • domain子模块 【打包方式为jar
    • 存放实体bean类的映射配置文件:*.hbm.xml 【必须构造和java代码中一样的包结构用于存放】
  • dao子模块 【打包方式为jar
    • 存放数据源配置文件:applicationContext_datasource.xml
    • 存放dao实现类的配置文件:applicationContext_dao.xml
  • service子模块【打包方式为jar
    • 存放数据库事务的配置文件:applicationContext_tx.xml
    • 存放service实现类的配置文件:applicationContext_service.xml
  • web.action子模块 【打包方式为war
    • 存放页面jsp文件
    • 存放实体类与数据表关系的配置文件:struts.xml

3. 单元测试

  1. 在dao层中添加junit依赖
  2. 在dao层src/test/java下创建测试类
  3. 右键点击你要测试的方法,选择右键菜单 Run as –> JUnit test

五. 依赖管理

1. 依赖范围

一些特殊应用场景:

  • servlet-api必须设置为provided
    如果在运行状态存在(即在war包中存在),会与tomcat中自带的servlet冲突
  • mysql 驱动建议设置为runtime
    编译过程并不需要利用到连接驱动
  • test设置为test
    只在测试中用到
1
2
3
4
5
6
7
<!-- servlet-api依赖的设置 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope> <!--依赖范围为provided-->
</dependency>

2. 依赖传递

依赖传递过程中,其最终依赖范围(Scope)为交集运算后的结果

3. 依赖调节原则

多条路径指向同一个依赖结果时,遵循如下原则

  • 依赖调解第一原则:路径优先
  • 依赖调解第二原则:声明优先

4. 版本锁定(★)

在Maven中利用<dependencyManagement>标签进行所依赖jar包进的版本管理

  • 版本控制器一般声明在父类(便于子类的依赖版本的统一管理)
  • 如果依赖中没有声明版本,才会采信版本控制器中的版本信息,否则遵循本身的设置
1
2
3
4
5
6
7
8
9
10
<!-- 锁定版本,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>
</dependencies>
</dependencyManagement>

5. 排除依赖

在使用框架中,又可能多个框架引入了相同的依赖Jar包,导致版本冲突,需要排除低版本的 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>
<!--排除struts中依赖的javassist【比hibernate中的版本低】-->
<exclusions>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>

六. 私服nexus搭建

nexus中的仓库按类型分类:
平常开发中都去连接仓库组Group,仓库组中包括:hosted、proxy

  • hosted:宿主仓库,自己项目的 jar 要放到 hosted 类型的仓库中
    • 3rd party一般指版权不明的第三方jar,但可以正常使用
    • release为发行版
    • snapshot为快照版
  • proxy:代理仓库,代理中央仓库
  • virtual:虚拟仓库,存储了 maven1 的构件,一般不用
  • group:仓库组,将一些仓库组成一个组,自己项目连接仓库组去下载 jar 包

1. nexus 安装

  • 解压安装包
  • 并在nexus-2.12.0-01-bundle\nexus-2.12.0-01\bin目录下使用cmd命令nexus install【cmd环境】
  • 启动nexus服务 【windows的本地服务】

2. 构建索引

刚刚安装好的 nexus 是无法直接搜索到 jar 包的,必须下载索引才可以正常使用

  • 到中央仓库地址 http://repo.maven.apache.org/maven2/.index/ 下载以下两个索引压缩文件及一个jar包
    • nexus-maven-repository-index.gz
    • nexus-maven-repository-index.properties(均在文档结尾)
    • indexer-cli-5.1.1.jar(直接google)
  • 将上述三个文件放在一个文件夹下,并在该目录下运行cmd:java -jar indexer-cli-5.1.1.jar -u nexus-maven-repository-index.gz -d indexer
    【该过程用于构建索引(自动生成在indexer目录下)】
  • nexus-2.12.0-01-bundle\sonatype-work\nexus\indexer\central-ctx目录下的文件删除,将上边的索引文件拷贝到此目录下

3. 镜像配置

在maven安装目录下的conf/settings.xml中进行配置

1
2
3
4
5
6
7
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public/</url>
</mirror>
</mirrors>

4. 发布自定义工程jar

在pom.xml中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<distributionManagement>
<!--releases版本的配置-->
<repository>
<id>releases</id>
<url>
http://localhost:8081/nexus/content/repositories/releases/
</url>
</repository>
<!--snapshots版本的配置 -->
<snapshotRepository>
<id>snapshots</id>
<url>
http://localhost:8081/nexus/content/repositories/snapshots/
</url>
</snapshotRepository>
</distributionManagement>

在maven的setting.xml中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<servers>
<!--releases版本的配置-->
<server>
<id>releases</id>
<username>admin</username>
<password>admin123</password>
</server>
<!--snapshots版本的配置 -->
<server>
<id>snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
坚持原创技术分享,您的支持将鼓励我继续创作!