关于Maven

之前虽然一直用Maven,但比较依赖于IDE的Maven-Plugins。最近抽了点时间决定系统得学习一下。

什么是Maven

Maven是使用Java开发的项目构建工具,至于它的作用网上相关的文章数不胜数,在此也不再累述。对于内容如果你看得云里雾里的话,我建议你直接上手使用一下Maven,就能知道它的魅力所在了。简而言之,我认为Maven在Java项目的开发过程中完成了以下两件事情:

  • 统一管理jar
  • 统一开发规范

安装

Ubuntu下安装非常简单:

sudo apt-get install maven

终端下mvn -v

Maven home: /opt/maven
Java version: 1.8.0_25, vendor: Oracle Corporation
Java home: /opt/java/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.13.0-44-generic", arch: "amd64", family: "unix"

出现类似的信息就说明成功了。与上面类似Windows下安装Maven需要配置几个环境变量,在此也不再累述。

使用Maven新建一个项目

终端下输入:

mvn archetype:generate


可以看到几百个archetype,archetype类似于模板,输入你想生成的模板的编号。比如最常见的org.apache.maven.archetypes:maven-archetype-webapp是19,然后我们输入19回车。接下来还会有各种各样的参数需要填,这里也作简单讲解。以国产优秀开源项目fastjson为例:

  • groupId:com.alibaba
  • arctifactId:fastjson
  • version:1.1.15

熟悉之后,其实通过一条命令来完成上面的操作:

mvn archetype:generate -DarchetypeArtifactId= maven-archetype-webapp -          DarchetypeGroupId= com.reeco -DarchetypeArtifactId= helloworld -DarchetypeVersion= 1.0-SNAPSHOT

你一定会奇怪这么长一串怎么记得住,在类Unix中通过强大的终端功能是可以轻松完成的,输入mvn archetype:generate -D 按Tab提示,就会出现,然后你只需按照上面的提示输入几个首字母就能补全所有的选项了。

Maven推荐的目录结构

我直接复制了官方文档

PATH ACTIVITY
src/main/java Application/Library sources
src/main/resources Application/Library resources
src/main/filters Resource filter files
src/main/webapp Web application sources
src/test/java Test sources
src/test/resources Test resources
src/test/filters Test resource filter files
src/it Integration Tests (primarily for plugins)
src/assembly Assembly descriptors
src/site Site
LICENSE.txt Project’s license
NOTICE.txt Notices and attributions required by libraries that the project depends on
README.txt Project’s readme

这是我们上面新建的项目目录结构

└── helloworld
    ├── pom.xml
    ├── src
    │   └── main
    │       ├── resources
    │       └── webapp
    │           ├── index.jsp
    │           └── WEB-INF
    │               └── web.xml

与推荐的相比,我们还需要添加几个目录

  • src/main/java
  • src/test/java
  • src/test/resources

如果你觉得resources不够,还可以添加其他的资源文件夹,然后像下面这样在pom.xml中配置一下

<build>
    <resources>
        <resource>
            <targetPath>.</targetPath>
            <directory>src/main/config</directory>
        </resource>
    </resources>
</build>

pom.xml

pom.xml是我们需要关注的重点,平时我们在IDE里也只需要关注它。先来看下我们项目中的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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.helloworld</groupId>
  <artifactId>helloworld</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>helloworld Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>helloworld</finalName>
  </build>
</project>

Dependencies

dependencies中每一个dependency就是我们项目中的一个依赖,对应一个Maven项目。我们只要去http://mvnrepository.com/搜索想要的依赖,然后复制粘贴到pom.xml中即可。
这里还有个scope属性,一共有五个值

  • cpmpile:默认作用域,编译、测试、运行时有效
  • test:测试时有效
  • runtime:测试、运行时有效
  • provided:编译、测试时有效
  • system::与provided类似,需要外在提供相应得元素

举几个例子说明下:

  • 比如我们项目中的JUnit,我们只在测试时使用,并不需要包含在最终的项目中,所以设置为test
  • Servlet和JSTL我们只需要在编译、测试时使用,运行时由于Servlet容器(比如Tomcat)自带了Servlet的lib,我们也不必自己提供Servlet,所以设置为provided
  • MySQL数据库的驱动,我们并不需要编译它,只需要在运行时去加载它即可,所以设置为runtime

Build

除了在上面提到的在build标签里配置resources之外,我们还可以配置plugins,各种plugin提供了一系列非常重要的功能

<build>  
    <plugins>  
      <plugin>  
        <groupId>org.apache.maven.plugins</groupId>  
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
            <source>1.7</source>
            <target>1.7</target>
        </configuration>
        </plugin>
    </plugins>
</build>

例如上面的plugin指定了项目编译用的JDK版本为1.7,具体的plugin可以参考这两篇文章:

http://www.cnblogs.com/crazy-fox/archive/2012/02/09/2343722.html

http://maven.apache.org/plugins/index.html

Lifecycle

Maven一共有9种生命周期:

  • clean:清理target目录
  • validate:验证Maven项目文件
  • compile:编译
  • test:运行测试
  • package:项目打包
  • verify:验证包
  • install:将项目安装到本地仓库
  • site:生成项目站点
  • deploy:将项目发布到远程仓库

我们可以通过mvn<生命周期>的方式运行Maven命令,比如常见的

mvn clean install site

Maven允许多个命令,同时执行三个生命周期。这里值得一提的是,运行任何一个生命周期,前面的生命周期都会被执行,所以我们一般执行

mvn install

就能完成编译、测试、打包。我们尝试着在我们之前的项目中运行这个命令,可以看到目录结构发生了变化:

└── helloworld
    ├── pom.xml
    ├── src
    │   └── main
    │       ├── resources
    │       └── webapp
    │           ├── index.jsp
    │           └── WEB-INF
    │               └── web.xml
    └── target
        ├── classes
        ├── helloworld
        │   ├── index.jsp
        │   ├── META-INF
        │   └── WEB-INF
        │       ├── classes
        │       └── web.xml
        ├── helloworld.war
        └── maven-archiver
            └── pom.properties

多了一个我们用于存放编译文件的目录target。那么怎么运行这个项目呢,对于Java Web项目来说,我们可以在build中通过plugin部署到tomcat下:

    <build>  
        <plugins>  
          <plugin>  
            <groupId>org.apache.tomcat.maven</groupId>  
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            </plugin>
        </plugins>
    </build>

然后:

mvn tomcat7:run-war

setting.xml

setting.xml是Maven全局配置文件,我们可以在里面配置Maven依赖下载的镜像和本地仓库目录。
我目前使用的是oschina的Maven镜像,下面的使用说明也讲解得非常清楚。
http://maven.oschina.net/help.html

总结

至此介绍了Maven的基本使用方式,以上的功能在IDE中也有很好的支持。Maven当然还有很多高级用法和最佳实践,值得我们去探索。