文章目录

前言

相信经历过很久以前初代Java Web开发的程序员都应该有体验,在那个时候是没有Maven这种东西的,每引入一个新功能,就需要手动下载依赖的JAR包导入,还可能和已经导入的JAR包产生冲突。更难受的是,运行的时候抛出异常查半天,到处修改业务代码以为自己写错了,结果发现问题处在JAR包冲突……所以,之前一直在用师兄师姐传承下来的经过多年验证的Jar包组……

而有了Maven,所有的JAR包问题都不用担心,可以完全集中精力写逻辑了。当然,管理Jar包只是Maven的其中一个功能,它还可以用来拆分和聚合模块,将整个大项目分成多个独立的模块分别开发,然后自动部署。

本文将只注重基础的管理Jar包的基础功能,其他的以后填坑。

Maven简单入门

Maven读音

官方的读法应该是[ˈmevən],“美ven”,其实“A”也可以读成苹果“apple”的“a”,但千万别读成“马ven”。

Maven官网

http://maven.apache.org/

使用Maven管理JAR包

(1)Maven的世界坐标

Maven通过:

【包名 / groupId】:通常是公司域名反写,如com.bewindoweb.javaweb

【项目名 / artifactId】:如webdemo

【版本 / version】:如0.0.1-SNAPSHOT

三个参数来定位一个Jar包,可以把这三个参数看作是X轴、Y轴、Z轴,一旦参数确定,Jar包也就确定了。很容易理解,如果是你开发的工程打包的Jar包,只要你的公司名确定、项目名确定、项目版本确定,这个工程也就确定了。

(2)Maven的快照版本和发布版本

我们常常可以看到许多不同的version,但对于Maven来说只有两种版本,一种是快照版本SNAPSHOT,一种是稳定版本RELEASE。识别的标准就一个,只要没有写SNAPSHOT,通通归为RELEASE。例如:1、1.12、1.0.3、2.0-rc1、4.3.5-Final、4.0.3-RELEASE、2.0-beta9等等,虽然字面意思看来,存在软件工程角度的beta测试版、Release Candidate最终测试版,但对于Maven的约定而言,全都是稳定版本。

SNAPSHOT什么时候用?就是你内部快速迭代不同功能模块的时候用。例如,我们开发了两个模块A、B,假设B发布的版本是1.0.0-RELEASE,A依赖于B的1.0.0,当B发生了新的修改,那么就必须发布一个1.0.1,A也必须修改B为1.0.1。两个模块还好,如果有100个A呢?如果B只是每次改1行代码,一天提交100个版本呢?所以,在开发期间,活跃的模块应该使用SNAPSHOT。只要采用SNAPSHOT,其他依赖它的模块会自动部署为最新的版本,而无需改变版本号。例如,B发布的版本是1.0.0-SNAPSHOT,B提交更新并部署到仓库后,A只需要重新构建就可以得到最新版本的B,完全不用去改变版本号。

但这样会带来一个问题,那就是如果B更改了A依赖的关键代码,A在没有更改自己任何代码的情况下,发现竟然构建失败了,这对于A来说是很诡异的事情。所以,线上一定要采用RELEASE版本。但如果B只提供了SNAPSHOT版本呢?你需要使用versions-maven-plugin插件来将SNAPSHOT固定下来,例如使用之后会将1.0.0-SNAPSHOT变为1.0.0.20181231.123456-1这种时间戳

,就可以把SNAPSHOT固定了。

(3)Maven解决Jar包冲突

有可能会有两个Jar依赖不同版本的相同底层Jar,Maven需要解决Jar包冲突的问题。

【方法一】让Maven自己处理。

Maven用两个原则处理Jar包冲突。

① 第一原则:最短路径优先

对于两个依赖关系

A→B→C→D(1.0.0-RELEASE)

E→D(2.0.0-RELEASE)

Maven会选择最短依赖路径E→D,加入D(2.0.0-RELEASE)。

② 第二原则:第一原则如果失效,那么最先声明优先

对于两个相同长度依赖路径的依赖关系

A→D(1.0.0-RELEASE)

E→D(2.0.0-RELEASE)

Maven会选择最先声明的A→D,加入D(1.0.0-RELEASE)。

【方法二】通过exclusions手动处理

通过exclusions排除不想要的包,例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

就排除了spring-boot-starter-test中的junit包。

(4)scope依赖范围

对于Jar包,需要什么范围内才使用,什么范围内不使用,可以使用scope来进行约束。例如前面的spring-boot-starter-test就只会在测试阶段才会被导入。scope取值含义列表如下:

scope取值 编译阶段 测试阶段 运行阶段 典型Jar 
 compile √ √ √ 默认值
 test  √  Junit
 provided √ √  servlet-api
 runtime  √ √ JDBC-driver
 system √ √  本地jar

compile:默认就是comile,三个阶段均有效。

test:一些测试时才会用到的包。

provided:一些容器提供的包,编译和测试需要用,但运行不需要。

runtime:一些编译不需要的接口之类的包。

system:自己手动导入的包。

但其实最常使用的就只有test和provided而已。


POM文件

以上所有的内容都写在pom.xml里,POM的含义是项目对象模型(Project Object Model),只要编写好pom.xml,Maven就会按照你的思路去进行操作了。常见的spring-boot工程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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <packaging>war</packaging>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

主要就是需要编写dependency,如果你只知道包名,不知道其他信息,你可以通过mvnrepository这个网站来查询,它会提供有哪些版本、每个版本使用情况如何等信息:

以及不同的管理工具对应的语法应该怎么写:

非常方便。

总结

这些都是基础的Maven用法,掌握了这些之后写一个Java Web就会很顺利的。如果还想了解更多,可以去了解Parent、import、type、properties中的固定约定、如何手动导入Jar包(不推荐、还是自己使用nexus搭建本地服务器比较好),和前面提到拆分模块等等。另外,如果你还在使用Java 1.7、1.6,或者还在使用eclipse、myeclipse,希望能够尝试一下Java8+、IntelliJ IDEA,你会打开新世界大门的。



转载请注明出处http://www.bewindoweb.com/238.html | 三颗豆子
分享许可方式知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
重大发现:转载注明原文网址的同学刚买了彩票就中奖,刚写完代码就跑通,刚转身就遇到了真爱。
你可能还会喜欢
具体问题具体杠