Maven完全指南 - 1. 发展历史

218 阅读4分钟

1. 发展历史

发展历史.png

Java 构建工具的发展历程反映了构建需求的不断演进和技术的进步,主要经历了以下几个阶段:

1.1 手动构建

在 Java 的早期,开发者需要手动下载所需的依赖库文件Jar,并将这些库文件放到项目 lib 目录中,再将 lib 目录通过-classpath设置到类路径中。同时,项目的编译和打包需要手动执行,开发者依赖命令行工具 javac 和 jar 来完成编译和打包。项目文件数量增加时,这种方式的缺点就暴露出来了:手动管理依赖文件、classpath类路径、编译顺序等非常繁琐且易出错。

1.2 Make

Unix 系统上流行的 Make 工具也被用于 Java 项目中。尽管 Make 主要为 C/C++ 开发设计,但开发者可以使用 Makefile 定义 Java 的编译和打包过程。此外,部分开发者会编写 Shell 脚本来管理项目构建流程。然而,这些方法对于 Java 项目的跨平台支持不够友好且难以管理复杂的依赖关系,同时语法比较复杂可读性较差。

项目结构:

project/
├── src/
│   ├── Main.java
│   └── util/
│       └── Helper.java
├── lib/
│   └── some-library.jar
├── bin/
└── Makefile

Makefile:

# 指定变量
JAVAC = javac
JAR = jar
SRC_DIR = src
BIN_DIR = bin
LIB_DIR = lib
MAIN_CLASS = Main
CLASSPATH = $(LIB_DIR)/*:$(BIN_DIR)

# 查找所有 .java 文件
SOURCES := $(shell find $(SRC_DIR) -name "*.java")
# 将 .java 文件转换为 .class 文件路径(替换 src 为 bin)
CLASSES := $(SOURCES:$(SRC_DIR)/%.java=$(BIN_DIR)/%.class)

# 默认目标
all: build

# 编译目标
build: $(CLASSES)

# 将 .java 文件编译为 .class 文件
$(BIN_DIR)/%.class: $(SRC_DIR)/%.java
	@mkdir -p $(dir $@)  # 创建目标目录
	$(JAVAC) -cp $(CLASSPATH) -d $(BIN_DIR) $<

# 生成 JAR 文件
jar: build
	$(JAR) cvf $(BIN_DIR)/project.jar -C $(BIN_DIR) .

# 清理目标
clean:
	rm -rf $(BIN_DIR)/*

# 运行程序
run: build
	java -cp $(CLASSPATH) $(MAIN_CLASS)

# 声明伪目标
.PHONY: all build jar clean run

1.3 Ant

Apache Ant 是第一个为 Java 量身定制的自动化构建工具,基于 XML 语法定义任务,可以编写脚本完成编译、打包、清理等任务。Ant 的出现标志着 Java 构建自动化的开始。尽管 Ant 提供了丰富的任务控制,但缺少标准的项目结构和依赖管理机制,且编写 XML 脚本会随着项目复杂性增加而变得繁琐。

项目结构:

project/
├── src/
│   └── HelloWorld.java
├── build/
├── lib/
└── build.xml

build.xml:

<!-- build.xml -->
<project name="HelloWorldProject" default="run" basedir=".">
    <!-- 设置属性 -->
    <property name="src.dir" location="src"/>
    <property name="build.dir" location="build"/>
    
    <!-- 初始化:创建编译目录 -->
    <target name="init">
        <mkdir dir="${build.dir}"/>
    </target>

    <!-- 编译目标 -->
    <target name="compile" depends="init">
        <javac srcdir="${src.dir}" destdir="${build.dir}"/>
    </target>

    <!-- 运行目标 -->
    <target name="run" depends="compile">
        <java classname="HelloWorld" fork="true">
            <classpath>
                <pathelement path="${build.dir}"/>
            </classpath>
        </java>
    </target>

    <!-- 清理目标 -->
    <target name="clean">
        <delete dir="${build.dir}"/>
    </target>
</project>

1.4 Maven

Maven 是一个强大的项目管理和构建工具,主要用于 Java 项目,但也可以支持其他语言。Maven 是一个强大且灵活的构建工具,通过简化依赖管理和标准化构建过程,帮助开发者提高生产力。无论是在小型项目还是大型企业级应用中,Maven 都是非常受欢迎的选择。

虽然 Ant 在某些简单场景中仍然有效,但 Maven 的自动化、标准化、依赖管理和丰富的插件生态使其在大型项目和复杂开发环境中更具优势。因此,在现代 Java 项目中,Maven 被广泛采用。

项目结构:

HelloWorldProject/
├── src/
│   └── main/
│       └── java/
│           └── com/
│               └── example/
│                   └── HelloWorld.java
└── 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.example</groupId>
    <artifactId>HelloWorldProject</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 编译设置 -->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <!-- 插件配置 -->
    <build>
        <plugins>
            <!-- 插件用于编译项目 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
            </plugin>

            <!-- 插件用于执行项目 -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.example.HelloWorld</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

如果只是为了编译打包的话,那么使用标准化配置之后的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.example</groupId>
    <artifactId>HelloWorldProject</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 编译设置 -->
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

</project>

1.5 Gradle

Gradle 的设计旨在提供更高的灵活性、性能和可扩展性,同时结合 Maven 和 Ant 的优点。通过引入基于 DSL 的构建脚本和增量构建等现代特性,Gradle 成为许多项目的首选构建工具,尤其是在处理复杂或大型项目时。虽然 Maven 在社区中仍有很大的使用基础,但 Gradle 的出现为构建工具带来了新的思路和更好的用户体验。

但 Gradle 的灵活性确实可能在某些情况下导致大型项目管理复杂性的增加。

项目结构:

project/
├── build.gradle
├── settings.gradle
└── src
    └── main
        └── java
            └── com
                └── example
                    └── HelloWorld.java

build.gradle:

plugins {
    id 'java' // 应用 Java 插件
}

group 'com.example' // 设置项目的组 ID
version '1.0-SNAPSHOT' // 设置版本

repositories {
    mavenCentral() // 使用 Maven 中央仓库
}

dependencies {
    // 在这里添加依赖(如果需要)
}

tasks.named('jar') {
    manifest {
        attributes(
            'Main-Class': 'com.example.HelloWorld' // 设置主类
        )
    }
}