maven原来这么简单?

介绍

Maven是apache的项目,地址:Welcome to Apache Maven – Maven,上面可以下载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官网: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启动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值