Maven 构建 java 项目(二)

概要

上一篇主要是对 Maven 构建项目的入门理解,这一篇将从实际项目出发,介绍了更改默认目录的问题,编码不可映射问题,以及如何添加资源文件,使用外部 jar 包,将依赖安装进生成的 jar 包等。内容都是对于 pom.xml更改,若是不知道以下内容在哪里更改的话,可先查看上一篇中介绍的 pom.xml 结构框架。

更改默认目录

上一篇内容中使用的是 Maven 默认的目录,但是如果我们项目的目录不是这样应该怎么办呢?如何进行配置呢?

假设当前项目结构如下:

my-app
|-- pom.xml
`-- src
|     `-- .java
|
`--    test
      `-- .java

即我将 src 指定为根目录,其中含有其他包或者 java 文件。将 test 指定为测试文件的根目录,其中含有测试所用的 java 文件或者其他包。

要想成功构建这样的项目,需要更改 pom.xml 文件,添加如下两行:

<build>
  <sourceDirectory>src</sourceDirectory>  
  <testSourceDirectory>test</testSourceDirectory>
  [...]    
</build>  

标签较易理解,指定了源目录与测试的目录,当然也可以更改其它的目录,可查看

Maven Documentation:Introduction to the Standard Directory Layout

对于其它目录的修改,可以参考:

<build>
  <sourceDirectory>src</sourceDirectory>  源代码文件夹  
  <scriptSourceDirectory>src/scripts</scriptSourceDirectory>  脚本  
  <testSourceDirectory>test</testSourceDirectory> 测试代码  
  <outputDirectory>target/classes</outputDirectory> 编译后输出的目录  
  <testOutputDirectory>target/test-classes</testOutputDirectory> 测试代码编译输出目录 
  [...]    
</build> 

编码的映射问题

在 eclipse 中写的 java 项目一般会有中文注释,直接采用以上的构建文件构建时可能报错 编码 UTF-8 的不可映射字符。 出现这类错误,原因就是项目源文件采用的编码方式与构建文件时采用的编码方式不一致。

  • 查看 eclipse 编码方式

    Project -> Properties -> Resource -> Text file encoding
    

    从中可以看到你该项目的编码方式,我的采用的是 GBK 编码。

    注意: 你可以将其更改为 UTF-8 编码,但这对于新建文件有效,对已存在的文件是不行的。

  • 更改 maven 项目的编码

    方式一:在 compiler 插件中设置编码方式

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.6.1</version>
      <configuration>
        <source>1.8</source>      <!-- 设置JDK版本 -->
        <target>1.8</target>
        <encoding>GBK</encoding>  <!-- 设置编码为 GBK-->
      </configuration>
    </plugin>
    

    方式二:在 properties 标签中设置

    <properties>
      <!-- eclipse default encoding is GBK -->
      <project.build.sourceEncoding>GBK</project.build.sourceEncoding>
      [...]
    </properties>
    

    想要了解该标签的可以参考:
    Maven Doc: Introduction-to-pom#Available Variables

  • 更改某一文件的编码

    若是编码方式错乱了,需要更改某个文件的编码,网上有许多文件转码工具,你也可以使用文本编辑器 notepad++。先将其编码方式设置为需要的编码: 设置 -> 首选项 -> 新建,然后新建文档,将原文档复制粘贴 ,再保存即可。

    若是需要 GBK 的,你可以选择编码为 ANSI

更改 JDK 版本

将 maven 默认的 JDK 版本更改为项目实际所用版本。与更改编码方式类似。

方式一:在 compiler-plugin 中设置 JDK 版本

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.6.1</version>
      <configuration>
        <source>1.8</source>      <!-- 设置JDK版本 -->
        <target>1.8</target>
        <encoding>GBK</encoding>  <!-- 设置编码为 GBK-->
      </configuration>
    </plugin>

方式二:在 properties 标签中设置

    <properties>
      [...]
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      [...]
    </properties>

外部 jar 包的引入

  • 本地 jar 包

    如果使用了外部的 jar 包,在较少的情况下,可以一个一个地在 <dependency> 中声明。
    比如我写 test 时使用了 junit.jar,就在根目录新建了 lib 文件夹,其与 srcpom.xml 是并列的,将使用的包放置其中,接着可以按如下方式更改:

    <properties>
      [...]
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12.0</version>
          <scope>system</scope>
          <systemPath>${basedir}/lib/junit.jar</systemPath>
        </dependency>
      </dependencies>
      [...]
    </properties>
    

    其中的 <groupId><artifactId> 要求不多,与名字相关即可。 ${basedir} 代表项目根目录。
    <scope> 标签共有6种,具体的含义你可以参考 Maven Doc:Introduction to the Dependency Mechanism

  • 联网下载依赖

    在使用上述方式添加依赖进行项目构建时,会发现 Maven 的提示,不建议这么做:

    It is highly recommended to fix these problems because they threaten the stability of your build.
    

    那么应该是怎么添加依赖呢?一般的操作是在 MVN Repository 中查找该依赖,然后添加。

    比如我想使用 Junit,先搜索,然后选择版本,之后你发现它已经给出了 MavenGradle等构建工具使用该依赖的代码,Maven 的如下,将其添加到 pom.xml 相应位置即可:

    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    
  • 大量 jar 包

    如果引用的外部 jar 包较少时,可以一个一个地使用 <dependency> 标签声明,但若是使用了很多的 jar 包呢,难道也得一个一个地声明吗?貌似没办法,应该是这样的,不过友情提示一下:

    项目真正使用的 jar 包可能并没有你想象那么多,你可在 java 类的 import 里查看到真正引用的 jar 包,比如我使用过 log4jJUNG 等工具,下载的包很多,但其实真正用上的就两三个。

导入资源文件

有时候 src 文件夹下可能不仅仅有 .java 文件,还会有你使用的其它文件,比如 .txt。 打开成功打包的 jar 包(其源自 zip ,使用压缩软件即可查看),发现这些文件并没有被打包进去,怎么将除了 .java 文件的其它文件也打包呢?你可以使用 <resource> 标签:

<build>
    [...]
    <resources>         <!--资源文件夹,可配置多个-->
      <resource>  
        <directory>src/data</directory> <!--文件目录-->  
        <includes>                         <!--包含的文件-->  
          <include>*.*</include>  
        </includes>  
      </resource>  
    </resources>  
    <testResources>  
      <testResource>  
        <directory>test/resources</directory> <!--测试资源目录-->  
      </testResource>  
    </testResources>
</build>

将依赖安装进 jar 包

成功打包之后运行 jar 包,发现使用依赖的那些类并不能正常使用。你可以查看 jar 包的内容(其源自 zip ,使用压缩软件即可查看),会发现在 pow.xml 中声明的那些依赖并没有安装进去,如何让依赖也安装进生成的 jar 包呢?添加如下代码即可:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id> <!-- this is used for inheritance merges -->
                    <phase>package</phase> <!-- bind to the packaging phase -->
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

再次打包 mvn package,会发现生成了 ...-1.0-SNAPSHOT-jar-with-dependencies.jar,该 jar 包则包含了你所需要的依赖。

pom.xml 展示


最后附上我某次项目使用的文件(点击展开/折叠)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<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>Maven-build</groupId>
<artifactId>Lab4_build</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lab4_build</name>
<url>http://maven.apache.org</url>

<build>

<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>src/data/</directory>
</resource>
</resources>
<plugins>
<!-- change the default jdk version 1.5 to 1.8-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>GBK</encoding>
</configuration>
</plugin>

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/net.sf.jung/jung-visualization -->
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-visualization</artifactId>
<version>2.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.sf.jung/jung-graph-impl -->
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-graph-impl</artifactId>
<version>2.0.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.sf.jung/jung-algorithms -->
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-algorithms</artifactId>
<version>2.0.1</version>
</dependency>

<dependency>
<groupId>collections-generic</groupId>
<artifactId>collections-generic</artifactId>
<version>4.01</version>
<scope>system</scope>
<systemPath>${basedir}/lib/collections-generic-4.01.jar</systemPath>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.0</version>
</dependency>


</dependencies>

</project>



总结

本文主要介绍了在实际项目中如何使用 Maven 进行构建,你会发现 Maven 构建项目并不用像第一篇说的那样要使用命令初始化,其实直接将写好的 pom.xml 放置在项目根目录,然后编译打包即可。Maven 十分强大,自己还有待学习。谢谢观看,欢迎留言!

请我吃根棒棒糖吧