03月08, 2020

Java - 使用maven构建打包普通项目

本文讲述了在项目结构固定的情况下,如何不改变结构、不重建项目而后期将项目改变为maven项目并导出jar包,主要面向对maven一窍不通的新人。

1. 普通项目转为maven项目

首先,File->open打开一个项目文件夹,例如我打开下面这个test项目:

W02P01.png

可由以下两种方式将其转为maven项目:

  • 右键项目文件夹->Add Framework Support->勾选Maven->OK
  • 在项目文件夹下新建一文件,重命名为pom.xml->在IDEA中右键pom.xml->Add as Maven Project

(使用第一种方法可能发现右键菜单里没有Add Framework Support,或者里面没有Maven,换用第二种方法就行。)

第一种方法会自动创建pom.xml并且添加必要的信息,并且在src里面创建main包,不过我们已经完成了项目的编写,这个包就没有存在的必要了。有关pom.xml的内容后面再讲

W02P04.png

2. pom.xml

2.1 初始化

使用第一种方法创建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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>


</project>

第一行是xml文件的声明,后面的 <project>...</project> 是xml的根标签,后面做的所有改动都需要在这个标签内进行。 其中,modelVersion标识了模型版本,maven 2或3可将其设置为4.0.0 后面三行的groupId-artifactId-version可简单理解为:谁的项目-项目名称-项目版本

2.2 依赖库的添加

在maven项目中,添加一个依赖库需要在pom.xml的 <project> 标签中添加一个 <depency> 标签。 若要添加多个依赖库,需在所有 <depency> 标签外添加 <depencies> 标签,结构如下:

<dependencies>
    <dependency>
        <!-- first depency -->
    </dependency>
    ...
    <dependency>
        <!-- last depency -->
    </dependency>
</dependencies>

添加 <depency> 标签可以前往mvnrepository查询所需库,选择对应版本,复制粘贴到pom.xml中即可。 例如现在我想添加Junit4.12,搜索Junit,选择使用最多的一项。

W02P05.png

可以看到Junit的各个版本,点击我们需要的4.12版本,就可以看到相应的标签内容了,将其复制到pom.xml中就可以了。

W02P06.png

W02P07.png

(注:要将 <scope>test</scope> 标签删去,它指定了依赖范围,有compile,test,provided,runtime,system 五种状态,默认为compile,不删去的话在编译时无法使用该依赖)

2.3 构建环境

这部分( <project> 标签下的 <build> 标签)将指引maven构建项目。

2.3.1 指定源代码、测试代码目录

maven默认的源代码目录为src/main/java,测试代码目录为src/test/java,而我们的项目结构已经定型,直接编译打包的话会生成一个空包,提示Maven: No sources to compile,这时我们就需要添加标签,将其指向项目中的目录。

<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>

2.3.2 添加maven插件

Maven 实际上是一个依赖插件执行的框架,每个任务是由插件完成。 在 <build> 标签中添加 <plugins> 标签

2.3.2.1 compiler

编译 Java 源文件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.0</version>
    <configuration>
        <source>1.8</source><!-- 源代码使用的JDK版本 -->
        <target>1.8</target><!-- 需要生成的目标class文件的编译版本 -->
    </configuration>
</plugin>

2.3.2.2 jar

将项目打包成jar包

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.0.2</version>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>P1.test</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

其中只需要注意 <mainClass> 标签即可,它指定了jar包运行的主类,比如以上述标签打包,运行时就会第一个运行P1.test。它会写入到jar包中META-INF目录下的MANIFEST.MF文件中(main-Class: P1.test),打包后也可以手动进行更改。 (注:MANIFEST.MF中冒号后面一定要有一个空格)

2.3.2.3 assembly

用于将依赖库一同打入另一个jar包。

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <mainClass>P1.test</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>

<mainClass> 标签功能与上面叙述的相同。

<descriptorRefs> 标签指定了带有依赖库的jar包的额外名字,例如我用mvn package打包生成的jar包名为a.jar,则使用mvn assembly:assembly命令打包生成的jar包就命名为a-jar-with-dependencies.jar。

2.4 更换镜像源

maven项目的构建需要把依赖库下载到本地仓库,可换用国内源增加下载速度。

<repositories>
    <repository>
        <id>alimaven</id>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

2.5 中文编码

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

3. 导出jar包

双击右侧菜单栏中的package,或在命令行中输入命令 mvn package ,默认存放路径为target目录

W02P08.png

注:在IDEA中操作与在命令行中操作结果可能有所不同,是因为在IDEA设置中(File->Settings->Build, Execution, Deployment->Build Tools->Maven)可以修改maven的配置文档位置,大部分网上的maven配置教程都会将这个位置修改成maven安装目录下的conf/settings.xml,而命令行中mvn使用的默认配置文件是用户文件夹下的.m2/settings.xml

4. 关于软件构造Lab1的分P打包

我个人的做法是在src中新建了一个包/类MainActivity,作用是根据命令行的输入决定执行P几的程序,并在pom.xml中生成jar包的mainClass设置为这个类。

W02P09.png

而将三个部分分开打包我是手动操作的,先整体打包,结构如下:

W02P10.png

对于每个单独的jar包,删除其他两个P以及MainActivity,只留下相应的包(P1, P2或P3),然后修改META-INF目录下的MANIFEST.MF,将其中的 Main-Class: MainActivity.MainActivity 分别修改为

  • Main-Class: P1.MagicSquare
  • Main-Class: P2.turtle.TurtleSoup
  • Main-Class: P3.FriendshipGraph

即可

W02P11.png

5. 常用maven命令

  • mvn clean 清理编译结果
  • mvn compile 编译
  • mvn package 打包
  • mvn assembly:assembly 带依赖库打包

6. 遇到过的问题

6.1 程序包org.junit不存在

删除 <depency> 标签中的 <scope> 标签

6.2 jar包为空

原因:没有指定源代码目录 在 <build> 标签中添加:

<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>

6.3 jar包中java文件没有编译成class导致的"找不到或无法加载主类"

原因:没有编译 在插件中添加compiler

6.4 .jar中没有主清单属性

原因:没有写入mainClass 见 2.3.2.2

本文链接:http://blog.zireaels.com/post/maven.html

-- EOF --

Comments