摘要

以前的学习过程中,都是自己导包。现在学习一下java的这个项目管理工具,不得不说,简直太爽了!

之前玩古三时,里面有句话,“再有万年,我人族,苍天可踏!”,虽然用在这里有点不太合适,但也说明了,人的创造力是无限的,哈哈。大佬们就是牛逼!

正文

一、Maven的概念

Maven是一个项目管理工具。

Maven的两个作用

  • 依赖管理:传统项目的jar包就在项目中,而maven开发的项目jar包放在仓库中,项目中只存放jar包的坐标。当有多个项目时,就体现出了maven的好处,这也符合开发中的代码可复用的要求。
  • 一键构建:项目一般要经过编译、测试、运行、打包、安装、部署等操作,通过maven,这些操作可以通过一个命令完成。

二、Maven的使用

2.1 安装

Maven官网

下载压缩包,解压到文件目录(没有中文)即可。

bin:存放了maven的命令

boot:存放了一些maven本身的引导程序,如类加载器。

conf:存放了maven的一些配置文件。

lib:存放了maven本身运行所需的jar包。

只要电脑本身配置好了jdk,那么maven只需要配置环境变量,就可以正常使用了。

配置系统变量MAVEN_HOME,存入maven的路径,将path中添加上%MAVEN_HOME%\bin即可。

最后查看是否安装成功,只需要管理员模式运行cmd,输入

powershell
1
mvn -v

2.2 Maven仓库

打开Maven根目录下的conf文件夹,找到setting.xml,里面有maven仓库的路径。

1.png

仓库分为三类

  • 本地仓库:用来存储从远程或者中央仓库下载下来的jar包,项目使用时,优先从本地仓库寻找。
  • 远程仓库:也叫私服;本地仓库没有时,默认去远程仓库下载,远程仓库可以在互联网中,也可以在局域网中。
  • 中央仓库:由Maven团队自己维护,里面存储了非常全的jar包,包含世界上大部分流行的开源项目构件。

如果不想使用默认仓库路径时,可以自己进行设置。如下图

2.png

中央仓库直接复制pom到idea即可自动下载,若Maven仓库没有,可以通过本地命令行来加入。

安装指定文件到本地仓库命令:mvn install:install-file

  • -DgroupId=<groupId>:设置项目代码的包名(一般用组织名)
  • -DartifactId=<artifactId>:设置项目名或模块名
  • -Dversion=1.0.0:版本号
  • -Dpackaging=jar:什么类型的文件(jar包)
  • -Dfile=<myfile.jar>:指定jar文件路径与文件名(同目录只需文件名)

比如

pom

xml
1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/javax/javaee-api -->
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

转换后

shell
1
mvn install:install-file -DgroupId=javax -DartifactId=javaee-api -Dversion=7.0 -Dfile=javaee-api-7.0.jar -Dpackaging=jar

成功后会有success字样

7.png

2.3 Maven标准目录结构

Maven的java工程。

  • src/main/java目录:核心代码部分
  • src/main/resources目录:配置文件部分
  • src/test/java目录:测试代码部分
  • src/test/resources目录:测试配置文件

如果是Maven的web工程,那么还需要在上面的基础上,再添加下面这个

  • src/main/webapp目录:页面资源,js、css、image等

三、Maven的常用命令

3.1 常用命令

我们可以在cmd中通过一系列的maven命令来对我们的项目工程进行编译、测试、运行、打包、安装、部署

  • mvn compile:编译命令,将src/main/java下的文件编译为class文件输出到target目录下。
  • mvn test:测试命令,会执行src/test/java下的单元测试类。
  • mvn clean:清理命令,删除target目录及内容。
  • mvn package:打包命令,对java工程执行package打成jar包,对于web工程打成war包。打包后的扩展名,在pom中的packing中可以设置。
  • mvn install:安装命令,将maven打成jar或war包发布到本地仓库。
  • mvn deploy:发布命令

3.2 指令的声明周期

maven有三种生命周期。

  • 清理生命周期
  • 默认生命周期:最常用的生命周期
  • 站点生命周期

默认生命周期的顺序是,compile(编译)->test(测试)->package(打包)->install(安装)->deploy(发布),后面的每一项,都会经历了他之前的工作,就像人生,老年的人,已经经历过了童年青年壮年的阶段。

3.png

下面这张是Maven的概念模型图

4.png

四、Maven的工程调试

4.1 Idea或者Eclipse集成Maven

Eclipse集成Maven插件

Idea集成Maven插件并创建项目

jar包的引入,如果本地没有的话,可以去中心仓库复制dependency。

一开始,创建项目时,各种报错,后来经过搜索知道,原来Maven的命令 mvn tomcat:run,默认是用的Tomcat6,之所以访问jsp和servlet都报错,是因为本地没有安装Tomcat6的原因。

maven默认是tomcat6,如果本地没有的话,需要配置tomcat。以Tomcat9为例,Maven配置Tomcat9

而相应的运行命令,就要编程mvn tomcat7:run

因为Tomcat内置了servlet跟jsp,所以与开发中的maven内部依赖的servet跟jsp就会有冲突。

5.png

解决办法是,在pom中,将servlet跟jsp的dependency中添加scope的作用范围为provided,意思是只在编译时,即开发时起作用。如果是test,那么就是只在测试时起作用。scope默认是compile

6.png

4.2 创建第一个Maven项目

简易的web项目跟java项目,都放在gitee

Web项目

  • 打包方式设置为war包,生成war包命令:mvn package

  • 通过tomcat6部署,即可直接访问:mvn tomcat:run

  • 通过tomcat9部署(目前没有tomcat9的插件,可以通过tomcat7配置),即可直接访问:mvn tomcat7:run

Web配置文件

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
<?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>

    ... ...
    <!-- 打包方式设置为war包 -->
    <packaging>war</packaging>
    ... ...

    <build>
        <finalName>Maven_web</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <!-- 配置Tomcat9 -->
                    <configuration>
                        <port>8080</port>
                        <server>tomcat9</server>
                        <update>true</update>
                    </configuration>
                </plugin>
                ... ...
            </plugins>
        </pluginManagement>
    </build>
</project>

遇到的问题

loader constraint violation: loader org.apache.jasper.servlet.JasperLoader:这是因为tomcat本身的servlet与maven指定的矛盾,只需要配置scope即可。

不能编译jsp:有可能是因为服务器版本问题,解决方案

Java项目

  • 打包方式设置为jar包,生成jar包命令:mvn package

Java配置文件

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
<?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>
    ... ...
    <!-- 打包方式为jar包 -->
    <packaging>jar</packaging>
    ... ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                </configuration>

                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>

                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <!--jar包的入口函数-->
                                    <mainClass>top.meethigher.danmu.Main2</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

4.3 第一个正式项目

哔哩哔哩直播间定时弹幕-java

遇到的坑

  • 生成jar包版本不一致问题:设置Maven下面的setting里面的jdk
  • 打包没有主清单:配置如上面4.2,需要设置入口函数
xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
... ...
<profile>
  <id>jdk8</id>
  <activation>
      <activeByDefault>true</activeByDefault>
      <jdk>1.8</jdk>
  </activation>
  <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
  </properties>
</profile>
... ...

五、依赖的作用范围

当我们使用Maven添加依赖时,配置如下

xml
1
2
3
4
5
6
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.14</version>
    <scope>compile</scope>
</dependency>

scope表示这个依赖的作用范围。默认是compile,因此大部分情况下scope可以省略。

scope的分类以及在各个阶段中是否引入依赖,如下

分类编译测试运行依赖传递性打包
compile
runtime
provided
system
test
import-----

import主要用于复杂项目的版本管理。通常用法如下

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
<dependencyManagement>
    <dependencies>
        <!-- https://projectreactor.io/docs/core/release/reference/gettingStarted.html -->
        <!-- 使用reactor提供的物料清单,确保库之间的版本兼容性 -->
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-bom</artifactId>
            <version>2020.0.19</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-core</artifactId>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-test</artifactId>
    </dependency>
</dependencies>

针对依赖的传递性,maven提供了optional

  • false: 默认值。不影响maven默认行为。
  • true: 阻断依赖传递,优先级最高,不论scope是什么。

比如

xml
1
2
3
4
5
6
7
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.12</version>
    <scope>compile</scope>
    <optional>true</optional>
</dependency>