Maven基础及使用

介绍

Maven是apache的项目,地址:http://maven.apache.org,上面可以下载maven,如:

apache-maven-3.0.4-bin.zip

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,本地访问:

http://localhost:8081/nexus

点左边的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官网:http://www.eclipse.org/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启动

FAQ

1、idea中的maven配置:

idea代码编译时使用的maven配置是环境变量path里面指定的路径,然后找到对应上级目录的conf/settings.xml

而project-settints里面的maven配置是在执行package、debug等时使用的,所以有时候编译报错也能够打包成功,可能就是编译和打包使用的不是同一settings.xml的原因。

 

2、阿里云的私有仓库

搜索"云效",控制台即可打开。新进一个"企业",就可以创建仓库了。

上传jar包的时候注意不要用ide上传,而尽量直接用页面的上传文件。

posted @ 2020-12-16 10:24  吴克兢  阅读(186)  评论(0)    收藏  举报