介绍
Maven是apache的项目,地址:Welcome to Apache Maven – Maven,上面可以下载maven,如:
Maven主要是用于分模块管理项目,对模块间的依赖管理很方便。
安装
1、解压缩apache-maven-3.0.4-bin.zip,例如解压到
D:\work\j2ee\apache-maven-3.0.4
解压后目录结构如下:
conf是配置,lib是maven的jar包
2、加入环境变量,将D:\work\j2ee\apache-maven-3.0.4\bin加入到path环境变量。
命令行输入mvn –version可以显示版本信息,
3、修改本地仓库位置
创建D:\work\j2ee\repository目录,
修改apache-maven-3.0.4\conf下的settings.xml,localRepository标签
中心仓库位置修改
pom.xml中,增加
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://nexus.sourcesense.com/nexus/content/repositories/public/</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
其中url就是配置的中心仓库的地址,默认的中心仓库地址在:
maven安装目录lib下的maven-model-builder-3.0.4.jar中org\apache\maven\model\ pom-4.0.0.xml中。
后面会讲到用镜像的方式修改,所以这里只做实验,实际很少使用。
配置使用
1、为项目创建一个根目录
例如D:\work\j2ee\maven_projects\01
(该目录结构一般是src目录、target目录、pom.xml三个,其中target是自动生成,src和pom.xml需要自己建)。
2、在01下新建文件pom.xml
(pom.xml是构建文件,其中指明了当前构建的版本、模块,以及依赖的模块等)
内容:
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cdd.hello</groupId>
<artifactId>hello-first</artifactId>
<version>SNAPSHOT-0.0.1</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
其中groupId是分组名称,也就是我们的项目名称,artifactId是模块名称,约定是:项目名加”-“加模块名,version表示版本,SNAPSHOT是快照版本。
groupId、artifactId、version合起来叫“项目的坐标”(GAV坐标)
dependencies标签是它所依赖的分组。
3、创建主java文件
3.1创建01\src\main\java\com\cdd目录,
3.2创建java文件,Hello.java
package com.cdd;
public class Hello {
public String sayHello(String name) {
return "hello:" + name;
}
public static void main(String[] args) {
System.out.println("hello world!");
}
}
放到01\src\main\java\com\cdd目录
maven_projects\01\src\main\java是所有包的根路径,这是规定。
4、创建测试java文件
4.1创建01\src\test\java\com\cdd目录,
3.2创建java文件,HelloTest.java
package com.cdd;
import org.junit.*;
import static junit.framework.Assert.*;
public class HelloTest {
@Test
public void testHello() {
Hello h = new Hello();
assertEquals(h.sayHello("zs"), "hello:zs");
}
}
放到maven_projects\01\src\test\java\com\cdd目录
maven_projects\01\src\test\java是所有测试包的根路径,这是规定。
(注:import static 是引入类的静态方法,这里Assert.*表示引入Assert类的所有静态方法,调用方法的时候可不加类名)
5、执行构建命令,生成target目录
(target目录存放的是编译后的class以及生成的jar包)
命令行进入到D:\work\j2ee\maven_projects\01,执行mvn compile,即可开始编译,此时使用到的jar包等资源会自动到maven的中心仓库(在apache的官网)下载,因此需要网络通畅。下载完以后会存到本地仓库中,下一次先到本地仓库去找,找到就直接使用。
默认存在C:\Users\Administrator\.m2\repository中。(前面已将其修改为D:/work/j2ee/repository)
编译后的class文件自动放在D:\work\j2ee\maven_projects\01\target\classes下
mvn clean:清理,删除target包
mvn compile:编译
mvn test:测试(自动先执行编译),运行测试方法(测试类中有@Test注解的所有方法)
mvn package:打包 (自动先执行编译、测试),在target下生成hello-first-SNAPSHOT-0.0.1.jar(模块名加版本号.jar)
mvn install:安装(自动先执行编译、测试、打包),将打好的包发到本地仓库。
mvn deploy:比package多一步,将打好的包发到私服上。(需要的时候先到本地仓库找、然后私服上找、最后中心仓库找)
命令可以连用,如:
mvn clean package,先清理后打包。
6、创建02项目,跟01类似
pom.xml:
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cdd.hello</groupId>
<artifactId>hello-second</artifactId>
<version>SNAPSHOT-0.0.1</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.cdd.hello</groupId>
<artifactId>hello-first</artifactId>
<version>SNAPSHOT-0.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
新建目录02\src\main\java\com\cdd2
新建World.java放到该目录:
package com.cdd2;
import com.cdd.Hello;
public class World {
public static void main(String[] args) {
Hello h = new Hello();
h.sayHello("wangwu");
}
}
7、对02项目mvn package,会自动找到依赖的01的jar
先将01项目mvn install到本地仓库,然后将02项目mvn package,会自动找到01的依赖。
注:junit尽量用4.10,其他的版本可能会提示找不到类。
快速建项目(mvn archetype:generate)
创建03目录,命令行进入,执行mvn archetype:generate可自动创建项目
创建过程中会要求用户输入groupId、artifactId、version。
完成后会自动创建pom.xml和src/main/java、src/test/java等目录结构。
这也叫做“基于骨架的生成”
eclipse配置
1、安装elipse的maven插件
2、Window-Preference-Maven-Installations, 点Add,选择下载的maven主目录
User Settings选择mavan主目录下conf下的settings.xml
3、可以新建maven项目,也可以导入已经存在的maven项目。
新建maven项目,
选quickstart
如hello-third,
groupId是com.cdd.hello,
artifactId是hello-third
version默认0.0.1-SNAPSHOT
,自动生成如下结构
pom.xml中加入依赖配置:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.cdd.hello</groupId>
<artifactId>hello-first</artifactId>
<version>SNAPSHOT-0.0.1</version>
</dependency>
</dependencies>
刷新工程,则自会自动加入依赖包
项目上或者pom.xml上点右键,run as-maven build…,Goals中输入命令运行即可,如:
依赖
网上仓库查找GAV坐标
依赖都是通过GAV指定,
有一些网上仓库提供了坐标的查询,如:
http://mvnrepository.com
http://www.sonatype.org/nexus
输入关键字,即可查找到坐标
依赖的传递性
模块A依赖于B,则会自动依赖于B所依赖的其他包,依次传递。
scope是test的不会传递。
如UserDao配置的依赖junit的scope是test,而UserService依赖于UserDao,则不会自动依赖于junit。
依赖传递性的冲突处理
当依赖的包有不同版本,首先比较路径长短,路径短的优先,路径相同的看哪个写在前面,写在前面的优先,如:
1、
aàb1.0
bàb1.1
càa,b
则càb1.0
(a写在了b前面)
2、
aàb1.0
càb1.1
dàa
fàd,c
则fàb1.1
(f到b1.0有三步,到b1.1只有两步)
可以在dependency标签内部用exclusions标签设置需要排除的依赖,通常用于避免依赖冲突。
如:
<dependency>
<groupId>com.cdd.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
这里依赖了user-core,而user-core依赖了log4j,但此时log4j的依赖不传递,避免冲突。排除的依赖不用写版本。
依赖的范围
即scope的值:
test:测试范围有效,编译和打包都不会加入依赖包。
compile:编译、测试、打包都会加入依赖jar。
provided:编译、测试有效,最后生成war包时不会加入依赖jar,如servlet-api,为了避免加入后跟容器的servlet-api产生重复引起冲突。
runtime:运行时依赖,编译时不依赖
默认范围是compile。
聚合和继承
聚合
如果希望用一个命令安装多个项目,可以建一个聚合项目,里面只有一个pom.xml,如:
pom.xml:
<groupId>com.cdd.user</groupId>
<artifactId>user-aggregation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../user-dao</module>
<module>../user-core</module>
<module>../user-service</module>
</modules>
其中packaging需要将jar改成pom,modules是需要安装的模块列表。../是上层目录,因此需要在同一个eclipse的工作空间下(聚合的项目和其他项目在同一级目录)。
继承
pom.xml文件可以继承,减少重复配置。可以创建父工程user-parent,同聚合工程类似,也是只有pom.xml文件,packaging是pom,其他目录都删掉。继承的时候project标签内的元素都会被继承。
子工程pom.xml增加配置:
<parent>
<groupId>com.cdd.user</groupId>
<artifactId>user-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../user-parent/pom.xml</relativePath>
</parent>
其中../user-parent/pom.xml是指定父工程pom.xml文件的路径
为了减少子pom.xml的依赖定义和统一管理依赖版本,通常把所有的依赖都写到父pom.xml中,继承的时候父pom.xml的dependencies依赖也会被继承,但这样就会使所有子工程都依赖所有jar,造成很多冗余依赖。
解决办法是父pom.xml中定义 dependencyManagement元素,将依赖放到里面,如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.cdd.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.cdd.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
子pom.xml中写依赖时,就可以不写version和scope,这样的好处是可以在父pom.xml把所有依赖的版本统一管理。
继承聚合统一
通常将继承和聚合放到一起,作为一个总体工程,如:
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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cdd.user</groupId>
<artifactId>user-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../user-dao</module>
<module>../user-core</module>
<module>../user-service</module>
</modules>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.cdd.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.cdd.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
常用属性
如果是同一个项目中的依赖,groupId和version通常是相同的,因此可以用${project.groupId}、${project.version}来指定,如:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>user-dao</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
此时的groupId和version就取当前pom.xml上面定义的。
查看错误报告
如:
target/surefire-reports/com.cdd.test.UserTest.txt
版本管理
版本号一般由4部分构成:
如:
user3.5.2-release
总版本号.分支版本号.小版本号-里程碑版本
总版本号:框架的变动(上面的3)
分支版本号:增加了一些功能(上面的5)
小版本号:修复了一些bug(上面的2)
里程碑:SNAPSHOTàalphaàbetaàreleaseàGA(上面的release)
SNAPSHOP:开发中的版本
alpha:内测版
beta:公测版
release:发布的版本,可以使用
GA:稳定版本,可以商用。
版本变化过程如:
user0.0.1-SNAPSHOT à user0.0.1-Release à user1.0.0SNAPSHOT à user1.0.0-Release
à user0.1.0-SNAPSHOP à user0.1.0Release
仓库
仓库分为本地仓库、中心仓库、私有仓库。默认情况下install时会发布到本地仓库,本地找不到依赖时会到中心仓库去找,由于中心仓库在广域网,因此效率很低。
通常会建立私有仓库,由私有仓库负责与中心仓库通信,本地仓库找不到时直接到私有仓库去找。如图:
nexus创建私有仓库
1、下载解压,bin目录加入path环境变量
可以用nexus创建私有仓库,下载nexus-2.0.3-bundle.zip,解压
将bin目录加入path环境变量,如D:\work\j2ee\nexus-2.0.3-bundle\nexus-2.0.3\bin
nexus有两个版本,一个是war,可以发布到tomcat等容器里,一个是jetty,nexus自带的服务器,这里用jetty。
2、修改jdk的java路径配置
编辑nexus-2.0.3-bundle\nexus-2.0.3\bin\jsw\conf\wrapper.conf
将wrapper.java.command=java改为本机jdk的java路径,如:
wrapper.java.command=D:\work\j2ee\jdk1.7\bin\java
3、安装服务,启动
命令行执行nexus install,即可将nexus服务安装到服务管理器。
可以用nexus start、nexus stop启动和停止服务,也可以在服务器管理器中启停。
4、访问服务,登录
nexus默认端口8081,本地访问:
点左边的Repositories即可查看仓库。
右上角点Log In,默认用户名admin 密码admin123
登录之后左侧即可看到很多链接。
仓库简介
仓库的Type有hosted、virtual、proxy、group等
virtual:是maven1的,目前基本不使用.
hosted:是本地项目发布的仓库,Snapshots、Releases分别对应不同的版本,3rdparty是第三方包的发布仓库,通常由内部管理员去发布。
proxy:代理仓库,向远程中心仓库寻找数据的仓库。选中某个proxy仓库,点下面的configuration即可看到远程地址。
group:组仓库,将多个仓库设置为一个组,设置仓库是在pom.xml中用repositories设置,如果有多个仓库就需要有多个repository标签,而用组可以只用一个repository标签指定组即可。
仓库右侧的地址是访问地址,浏览器用ip访问时,右侧地址会跟着变化,如本机是ip是192.168.1.104时:
使用仓库
一般在在parent工程的pom.xml中配置私有仓库地址,使用时会到私有仓库下载,而如果私有仓库后台发现没有,会到中心仓库去下载,先下载到私有仓库,再返回给本地仓库。
<repositories>
<repository>
<id>nexus</id>
<name>Nexus Repository</name>
<url>http://192.168.1.104:8081/nexus/content/groups/public/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
其中url就是本地仓库列表中右侧的地址。
配置镜像
对于repository中配置的仓库,可以在settings.xml中配置镜像网址,这样下载时就会到镜像地址下载,如:
pom.xml中配置的私有仓库:
对应到settings.xml中配置成:
一般这样配置:<mirrorOf>*</mirrorOf>,这样对于所有的仓库都使用同一个镜像地址。
更新索引
可以将mvnrepository等网站提供的gav搜索的方式弄到私有仓库,即将索引弄到私有仓库,这样以后搜索gav的时候就不用到mvnrepository等网站,而直接在私有仓库搜索,本地只存索引,需要的jar私有仓库也会到中心仓库去下载。
1、仓库自动更新
选中Central仓库,点”Configuration”
将Download Remote Indexes设置为True
点save。
此时就会开始更新索引,点左边的Adminitration- Scheduled Tasks,就可以看到该任务正在进行。
2、手动更新
如果自动更新很慢,则可以手动更新(不过目前网速提速以后已基本没问题)
2.1、下载nexus-maven-repository-index.zip,解压
2.2、停服务nexus stop
2.3、删除nexus-2.0.3-bundle\sonatype-work\nexus\indexer\central-ctx目录下所有文件(都是lucene的索引文件),将解压的文件全部复制到该目录下。
2.4、启动服务nexus start
效果:
注,可以右键单击某个仓库,点Update Index更新索引。
仓库通常使用方法
一般所有项目都使用同一个私有仓库,这样好管理。这样就只用配置一个镜像,然后maven中的默认中心仓库镜像到私有仓库即可。
而由于默认仓库的snopshots是false的,没有打开快照的依赖。
我们需要让他为ture,打开快照的依赖。
因此需要创建一个仓库覆盖它,而如果定义到parent工程的pom.xml,则只有一个parent的项目及子项目可以用,其他的parent项目用不了,因此最终的配置如下:
仓库最终配置
在全局的settings.xml中配置一个central覆盖默认的,然后将它镜像到私有仓库。
settings.xml中的<profiles>及activeProfiles配置如下:
<profiles>
<profile>
<id>central-repos</id>
<repositories>
<repository>
<id>central</id>
<name>Central</name>
<url>http://maven</url>
<release><enable>true</enable></release>
<snapshots><enable>true</enable></snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>central-repos</activeProfile>
</activeProfiles>
其中profile的id跟activeProfiles的一致,表示要激活哪一个profile。
repository的id跟maven默认的一致,表示覆盖默认配置。
url是随便写的,会被镜像的覆盖。加上配置的镜像:
<mirror>
<id>mav</id>
<mirrorOf>*</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://192.168.1.104:8081/nexus/content/groups/public/</url>
</mirror>
就是通常的使用方法。
项目的发布(deploy)
1、设置release可以发布:私有仓库中,选中Release仓库,Configuration中,Deployment Policy设置为Allow Redeploy。Snapshots同样设置。
2、parent的pom.xml中配置发布的仓库。
project标签下添加:
<distributionManagement>
<snapshotRepository>
<id>user-snapshots</id>
<name>User Project SNAPSHOTS</name>
<url>http://192.168.1.104:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>user-release</id>
<name>User Project Release</name>
<url>http://192.168.1.104:8081/nexus/content/repositories/releases/</url>
</repository>
</distributionManagement>
这里添加了两个发布仓库,一个snapshots版,一个release版,其中url是仓库地址
3、settings.xml中配置权限。
nexus默认带了3个用户,可以在Security-Users中看到
其中annoymous匿名用户只有查看权限不能发布。deployment是发布用户,可以发布。admin是超级用户,拥有有所有权限。
在settings.xml中servers标签下增加:
<server>
<id>user-snapshots</id>
<username>deployment</username>
<password>deployment123</password>
</server>
<server>
<id>user-release</id>
<username>deployment</username>
<password>deployment123</password>
</server>
其中server的id对应刚才pom.xml中的配置。
用户名deployment,密码deployment123是nexus默认的,类似于admin用户。
4、parent工程运行mvn clean deploy。就会进行upload发布。,效果:
分仓库管理项目
默认情况下私有仓库中只有一个Snapshots和一个Release,因此所有的项目都会发布到里面,但这样就很乱,因此需要为每个项目都创建一个Snapshots和一个Release仓库(工厂)。
1、创建仓库
点Add,选择Hosted Repository:
创建一个release的仓库(Repository Policy选Release):
Repository ID:MyUserReposRelease
Repository Name:My User Project Release
Repository Policy:Release
Deployment Policy:Allow Redeploy,
再创建一个snapshots的仓库(Repository Policy选Snapshot):
Repository ID:MyUserReposSnapshots
Repository Name:My User Project Snapshots
Repository Policy:Snapshots
Deployment Policy:Allow Redeploy,
创建后列表中就能看到:
2、创建权限
点Security- Privileges,”add…”
分别创建Snapshots和Release的权限
Snapshots:
Name: MyUserProSnapshots
Description:用户管理工程的快照权限
Respository:选择刚才创建的Snapshots仓库
Respository Target:选择All(Maven2)
Release:
Name: MyUserProRelease
Description:用户管理工程的release工厂权限
Respository:选择刚才创建的Release仓库
Respository Target:选择All(Maven2)
创建完之后即可在列表中看自动创建的create、delete、read、update权限
3、创建角色分配权限
点Security-Roles,add..,Nexus Role
填入:
Role Id:MyUserProject
Name:MyUserProject
Description:用户管理工程的角色
点下面的Add添加权限:
输入My过滤查找,选出刚才添加的权限。
4、创建用户分配角色
点Security-Users,add..,Nexus User
User ID:wuk
邮箱:12345@qq.com
Status:选择Active
NewPassword:123456
ConfirmPassword:123456
以上的内容根据实际情况填写。
点下面的add增加用户角色:
选择刚才创建的角色
5、配置项目发布到仓库
parent工程的pom.xml中distributionManagement配置的Snapshots仓库地址和Release仓库地址的url改为刚才创建的仓库地址:
<distributionManagement>
<snapshotRepository>
<id>user-snapshots</id>
<name>User Project SNAPSHOTS</name>
<url> http://localhost:8081/nexus/content/repositories/MyUserReposSnapshots/ </url>
</snapshotRepository>
<repository>
<id>user-release</id>
<name>User Project Release</name>
<url> http://localhost:8081/nexus/content/repositories/MyUserResposRelease/ </url>
</repository>
</distributionManagement>
6、修改全局settings.xml中配置的用户名、密码
<server>
<id>user-snapshots</id>
<username>wuk</username>
<password>123456</password>
</server>
<server>
<id>user-release</id>
<username>wuk</username>
<password>123456</password>
</server>
parent上运行clean deploy即可发布到创建的仓库,效果如下:
maven生命周期
maven生命周期有clean、compile、site三个,
他们是相互独立的三个生命周期,没有任何关联。
其中site用于发布站点,很少使用。
clean生命周期
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
compile生命周期
- validate
- generate-sources
- process-sources
- generate-resources
- process-resources 复制并处理资源文件,至目标目录,准备打包。
- compile 编译项目的源代码。
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources 复制并处理资源文件,至目标测试目录。
- test-compile 编译测试源代码。
- process-test-classes
- test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署。
- prepare-package
- package 接受编译好的代码,打包成可发布的格式,如 JAR 。
- pre-integration-test
- integration-test
- post-integration-test
- verify
- install 将包安装至本地仓库,以让其它项目依赖。
- deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享。
上面加粗的都是经常命令里使用的
生命周期的执行
生命周期中执行任何一步操作都会先完成前面的操作,例如mvn install,
会先compile,然后test,一直执行到install停止。
maven插件
插件的概念
maven中的所有操作都是由插件来完成的,例如compile、test、install等,一个插件中可能有多个目标,执行的就是插件中的目标。
例如这里执行了maven-compiler-plugin:2.3.2插件的compile目标、maven-resources-plugin:2.5插件的testResources目标
可以自己配置插件,将它绑定到生命周期中,在绑定的位置执行。
插件所在位置
插件都放在仓库中,如:D:\work\j2ee\repository\org\apache\maven\plugins
都有jar包,如:
apache查看maven插件,check out插件源代码
打开http://maven.apache.com网站,左侧点Plugins。
即可看到各种插件,点compiler。
即可查看compiler插件。
可以看到这个插件的目标有:compile和testCompile。
点左侧的Source Repository。
即可看到svn的check out地址:
check out下源码之后,可以在src\main\java\org\apache\maven\plugin\compiler\ CompilerMojo.java里查看compiler的源码,一个Mojo就是一个目标。
如:
其中name= “compile”表示目标是compile。
LifecyclePhase.COMPILE表示在compile生命周期使用。
使用source插件打包源文件
默认mvn package打包的是class文件,可以用source插件把源文件打包。
点击官网中plugins列表中中的source插件
可以看到source插件有4个目标:
点示例可以看到配置方法:
user-service的pom.xml中加入如下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
这里配置了source插件,gav定位插件,跟依赖类似。
phase指定在compile完成之后执行。goals是插件的目标,具体可以参考使用说明,jar表示将源码生成jar文件、test-jar表示将测试文件成长test-jar文件。
执行clean package(生命周期中package在compile之后,因此会先执行compile)
效果:
控制台:
可以看出,compile执行完之后就立即执行source插件
使用compiler插件修改jdk编译版本
默认编译环境是jdk1.5的
可以通过compiler修改。
点compiler插件链接
点示例中的第二个
加入plugin配置,将source和target修改为1.6即可
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
工程上点右键-Maven-update project configuration,刷新。
效果:
注意:这里修改的仅仅是使用的jdk版本,jdk用的也是本地的,如果本地装的是1.6的jdk,那么就只能设置1.6及以下的版本,不能设置成1.7。
使用rar插件将所有依赖jar包打包到rar
找到rar插件链接:
该插件目标只有一个就是rar:
点示例的第一个
配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-rar-plugin</artifactId>
<version>2.3</version>
<configuration>
<includeJar>true</includeJar>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>rar</goal>
</goals>
</execution>
</executions>
</plugin>
clean package后效果,自动生成了user-service-0.0.1-SNAPSHOT.rar,并且将所有依赖jar包都打了进去。如果includeJar配置为false,则不会打入当前的jar包:user-service-0.0.1-SNAPSHOT.jar
使用sql插件创建数据库,创建表
找到sql插件的链接
sql插件只有一个目标execute
点第一个示例
即可看到示例配置。
点sql:execute目标可以看到配置参数
其中driver和url是必须配的,forceMojoExecution默认是false。
配置如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver>
<jdbc.url>jdbc:mysql://localhost:3306</jdbc.url>
<jdbc.username>root</jdbc.username>
<jdbc.password>cdd</jdbc.password>
</properties>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.5</version>
<!-- 使用插件也可以指定相应的依赖 -->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
</dependencies>
<configuration>
<driver>${jdbc.driver}</driver>
<url>${jdbc.url}</url>
<username>${jdbc.username}</username>
<password>${jdbc.password}</password>
</configuration>
<executions>
<execution>
<id>create_db</id>
<phase>compile</phase>
<goals><goal>execute</goal></goals>
<configuration>
<sqlCommand>
create database if not exists user_db
</sqlCommand>
</configuration>
</execution>
<execution>
<id>create_table</id>
<phase>test-compile</phase>
<goals><goal>execute</goal></goals>
<configuration>
<srcFiles><srcFile>src/main/resources/init.sql</srcFile></srcFiles>
</configuration>
</execution>
</executions>
</plugin>
这里在compile阶段创建数据库,test-compile阶段创建表。sqlCommand直接执行里面的sql。
srcFile是执行init.sql里面的sql
注意,一个插件的execution如果不止一个,则id不能省略,且不能相同,否则报错。
执行mvn package后效果:
plugin的继承
plugin和dependency一样,也可以采用继承的方式减少重复配置,如:
parent的pom.xml的plugin配置:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
userService的pom.xml的plugin配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
</plugins>
</build>
用help插件查询插件信息
任意一个工程下运行如下命令
help:describe -DgroupId=org.apache.maven.plugins -DartifactId=maven-compiler-plugin -Dversion=3.0
这里调用了help插件的describe目标,参数都是以-D开头,写上要查询插件的gav,运行即可看到如下结果。如果加上-Ddeatail还可以看到更详细信息。
测试
测试包都放在src/test/java目录下,默认只有以下三种类会自动执行测试。
Test*(Test开头)
*Test(Test结尾)
*TestCase(TestCase结尾)
只跟类名有关系,跟方法名没关系,方法前面只要加了@Test就表示测试方法。
配置测试类
测试默认是调用的surefire插件
可以对其进行配置,如parent的pom.xml中配置:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<!-- 设置包含的测试类 -->
<includes>
<include>**/Hello*.java</include>
</includes>
<!-- 设置排除的测试类 -->
<excludes>
<exclude>**/HelloMaven.java</exclude>
</excludes>
<!-- <skip>true</skip> --> </configuration>
</plugin>
包含排除的范围:
其中include表示包含,即只有满足这里条件的类才会执行测试
**/Hello*.java表示所有目录下,以Hello开头的java。
exclude表示排除,这里排除了所有目录下的HelloMaven.java
例如src/test/java下有
HelloUser.java
UserTest.java
UserTestCase.java
HelloMaven.java
则只有HelloUser.java会执行测试,因为此时配置了include,默认的三种情况失效,而HelloMaven.java又被排除。
测试的执行跳过与编译跳过:
skip如果为true,则表示跳过测试,所有测试均不执行,但测试类会编译,因此如果测试类有编译错误,则会报错。如果在maven-compiler-plugin插件(即刚才的修改jdk版本插件)中使用此属性,则连编译都不会检查,但这种方式不推荐使用。
也可以在命令中手动跳过测试,如:clean package -DskipTests=true
手动指定执行某一个测试类
clean package -Dtest=HelloMaven.java
注意:这里的子工程不用再配maven-surefire-plugin插件,因为默认已经自动加入。
生成测试覆盖率报告:
cobertura插件可以生成测试报告,执行cobertura:cobertura即可。
自动生成site,用浏览器打开index.html即可看到测试覆盖率
可以将它配置到生命周期中的test执行完自动生成覆盖率
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
<executions>
<execution>
<id>cobertura-report</id>
<goals><goal>cobertura</goal></goals>
<phase>test</phase>
</execution>
</executions>
</plugin>
maven web项目
创建maven web项目
1、创建maven项目时选择”maven-archetype-webapp”
输入Artifact Id为user-web,Package中会自动变成下划线user_web,点finish。
创建完成后,可以看到src/main/webapp目录,web工程的所有文件都放在这里面。
2、pom.xml中配置继承user-parent工程。
<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">
<parent>
<groupId>com.cdd.user</groupId>
<artifactId>user-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../user-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<finalName>user-web</finalName>
</build>
</project>
3、parent工程加入servlet api的依赖。
<dependency>
<groupId>jetty</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5-6.0.2</version>
</dependency>
user-web工程引入依赖
<dependency>
<groupId>jetty</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
创建源码目录src/main/java,方法:src/main下创建java目录,然后将它use as source folder
创建HelloServlet继承HttpServlet
写一个跳转方法:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/hello.jsp").forward(request, response);
}
src/main/webapp下新建一个hello.jsp
4、默认生成的web.xml中没有字符集的声明以及没有对el等xlms的声明,需要复制以下部分覆盖到<web-app>。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
web.xml中配置servlet
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.cdd.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
运行clean package,即可在target下看到生成的user-web.war,将它复制到容器webapps下启动服务即可访问。
访问地址:
http://localhost/user-web/hello
使用jetty插件
如果每次都拷贝war包,则程序修改后无法自动发布,比如jsp改了,需要页面刷新马上看到修改,便于调试。jetty是一个类似tomcat的容器,它提供maven插件,这样可以使项目跑在jetty容器中,实现程序修改自动发布,并可以提供程序的断点调试。
jetty官网:The Eclipse Jetty Project :: Eclipse Jetty
1、设置jdk7版本
目前jetty的最新版本为1.9,需要jdk7的支持,因此本机需要安装jdk7,再用maven-compiler-plugin插件把使用版本设置为1.7
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
2、配置插件和依赖
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.1.3.v20140225</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<webApp>
<contextPath>/user_web</contextPath>
</webApp>
<httpConnector>
<port>8787</port>
</httpConnector>
<webDefaultXml>src/main/resources/webdefault.xml</webDefaultXml>
</configuration>
</plugin>
其中scanIntervalSeconds是扫描间隔,这里5秒钟扫描一次文件改动并重新加载,检测的是java的改变,重新加载的是类,类似于myeclipse的热部署,jsp的改动是实时反应的。
contextPath是部署的应用名
port是访问端口
3、运行,访问
clean package jetty:run
访问地址:
http://localhost:8787/user_web/hello
不用为jetty插件绑定生命周期,因为并非每次都需要启动,所以一般都手动jetty:run启动