天码营上关于Java的经验内容,大多是基于Maven项目的。今天我们介绍一下Maven这个构建工具,同时基于Maven来创建一个简单的项目。

Maven是一个项目构建和管理工具,为开发人员提供了一个项目构建(build)的生命周期框架。Maven可以管理构建生命周期中的各个阶段(Maven的术语中称为目标 goal),包括编译,构建,测试,发布,报告等。Maven也是“默认大于配置”的推崇者,使用标准的目录结构和默认的构建生命周期,同时帮助你管理项目依赖,因而开发者能够在非常短的时间里完成项目的配置工作,从而快速建立开发环境,极大提高开发效率。

安装Maven

在通过Maven构建之前,我们首先需要安装Maven。

从这个地址下载Maven,我们只需要下载二进制文件即可,因此我们下载apache-maven-{version}-bin.zip或者apache-maven-{version}-bin.tar.gz文件。

下载文件之后将zip包解压到某个目录,将bin文件夹设置到环境变量的path路径中就完成了安装。​为了验证Maven是否安装成功,在命令行执行mvn -v命令,如果安装成功,可以看到控制台输出:

Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T19:57:37+08:00)
Maven home: /Users/tianmaying/Dev/Tools/apache-maven-3.3.3
Java version: 1.8.0_20, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "10.10.4", arch: "x86_64", family: "mac"

创建代码

我们首先创建这样一个目录结构

└── src
    └── main
        └── java

在*nix系统中,执行mkdir -p src/main/java/命令即可。

src/main/java/目录下来创建我们需要的Java类,我们创建两个Java类:

HelloWorld.java

package com.tianmaying.mavendemo;

public class HelloWorld {
    public static void main(String[] args) {
        Greeter greeter = new Greeter();
        System.out.println(greeter.sayHello());
    }
}

Greeter.java

package com.tianmaying.mavendemo;

public class Greeter {
    public String sayHello() {
        return "Hello world!";
    }
}

定义POM文件

接下来我们对Maven项目进行配置,Maven通过pom.xml这样一个XML文件来定义项目,这个文件中包括了项目名称、版本和外部依赖等信息。

在项目根目录下创建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>org.springframework</groupId>
    <artifactId>gs-maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.tianmaying.mavendemo.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

上面这个文件中,基本是最简化的一个POM文件了。除了<packaging>元素之外,所有的XML元素都是构建一个Java项目必须要进行的设置。我们来看看细节:

  • <modelVersion> POM模型的版本(只能是4.0.0)
  • <groupId> 这个项目所属的组织,通常都是组织的域名的反写形式
  • <artifactId> 这个项目产生的制品的名称,比如生成的JAR包或者WAR包的名称
  • <version> 项目的版本,关于版本的描述策略, Spring推荐 语义化版本方法
  • <packaging> 项目如何打包,默认值为jar

有了这些信息,我们就定义了一个最小化的可被构建的项目。

构建Java代码

我们可以通过Maven执行不同的构建生命周期目标(build lifecycle goals),比如编译项目代码,创建制品(如JAR包),将包安装到本地仓库等。

在命令行中输入:mvn compile

这里输入引用文本这条命令告诉Maven执行编译,如果成功执行,将可以在target/classes文件夹下看到编译出来的.class文件

提示

如果首次运行maven命令,花一些时间去将依赖的包下载到本地仓库。

通常情况下,我们执行得更加频繁的命令是mvn package

package目标不仅会编译代码,同时会运行所有的测试,最后将target目录下的生成JAR包。JAR包的名称时<artifactId><version>两个属性值连接起来构成的。比如上面这个例子中,生成JAR包会被命名为gs-maven-0.1.0.jar

如果将<packaging>的值从"jar"改成"war",则将生成一个WAR包。

Maven在本地维护着一个缓存依赖的仓库,通常在用户目录下的.m2/repository目录,这样构建时可以迅速获取所需的依赖。如果你希望项目生成JAR包也放到本地仓库中,可以执行:mvn install

install目标不仅编辑、测试和打包,同时将打包出来的制品会复制到本地依赖仓库中,将来其它项目如果需要依赖于这个包时,就可以在POM文件中引用它。

那如何在pom.xml中引用所需的依赖呢?我们往下看。

定义依赖

之前的例子是一个完全自包含的项目,不需要额外的包依赖,因为它实在太简单了。但是我们实际的项目中肯定是要依赖于大量外部包的。

我们来让这个例子稍微复杂一点,在打印"Hello World!"的时候同时打印出日期和时间,我们希望使用Joda提供的时间库来让帮助我们简化时间相关的处理代码:

package com.tianmaying.mavendemo;

import org.joda.time.LocalTime;

public class HelloWorld {
    public static void main(String[] args) {
        LocalTime currentTime = new LocalTime();
        System.out.println("The current local time is: " + currentTime);
        Greeter greeter = new Greeter();
        System.out.println(greeter.sayHello());
    }
}

我们使用Joda Time包提供的LocalTime类来获取和打印当前时间。

这时如果我们执行mvn compile将会报出编译错误。需要将 Joda Time这个库添加到我们的POM依赖中:

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>

上面这段XML定义了这个项目的依赖。在<depency>元素中,包含三个子元素:

  • <groupId> 类似于项目所属的组织,所依赖的包也属于某一个组织
  • <artifactId> 依赖包的名称
  • <version> 依赖包的版本

依赖还有一个范围(scope)的属性,有三种取值:

  • compile表示这个依赖在编译时应该存在,这是scope的默认值
  • provided表示这个依赖不仅在编译时需要,同时应该在运行时也存在,比如Java Servlet API的依赖
  • test表示依赖在编译和测试时需要,但是运行时不要求存在,比如JUnit的依赖,运行时是不需要的

此时运行mvn compile或者mvn package,Maven应该可以解析到Joda库,并将其从中央仓库下载,构建成功啦!此时完整的POM文件如下:

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>org.springframework</groupId>
    <artifactId>gs-maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

    <!-- tag::joda[] -->
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>
    <!-- end::joda[] -->

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.tianmaying.mavendemo.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

提示

注意这里我使用了Maven Shade插件来让一个JAR包变成可执行的文件,通过在插件的配置中设置了<mainClass>属性来实现这一点。关于插件的使用这里就不展开了,且听下回分解。

登录发表评论 注册

反馈意见