Maven详解

Maven入门

Maven简介

最近在自学Java Web,需要用到比如mysql-common.jar、servlet-api.jar、jsp-api.jar,我们将这些jar包放到项目目录的Lib文件夹下即可完成部署,这样产生的问题也是显而易见的:如果我们在本地部署了多个项目,那么每个项目都需要来一份自己所需要的jar包,这样子一个一个包去放很不方便,于是便有了Maven

Maven

Apache组织维护的一个项目,主要用于自动化构建和管理JAVA项目

基于项目对象模型(POM Project Object Model)

下载地址:https://maven.apache.org/download.cgi

通过下面这张图可以看出来,Maven针对不同的项目可以对所依赖的jar包进行统一管理(后面会详细讲解),是不是看起来就比传统的项目高级了很多呢!

image-20210331163159736

当然,Maven的功能远不止这么简单,下面就从最基本的配置环境开始一起来学习Maven吧!

Maven安装

下载与安装

我们首先在上面的下载地址中下载,解压后放到你自己的磁盘里就行了

image-20210331164341544

配置环境变量

由于Maven是用Java编写的,依赖于Java包,所以我们首先要确保自己的JAVA_HOME环境变量配置完成,最好在path中也将maven根目录下面的bin目录配置进去

注意:两个home配置的都是根目录,也就是解压以后的那个文件夹

image-20210331164834965 image-20210331165020963

此时打开CMD,输入mvn -v,如果显示出版本号则证明maven配置成功!

image-20210331165158162

Maven项目目录结构

创建Maven项目时,Maven将创建默认的项目结构,开发人员只需要相应地放置文件即可

image-20210331165317890

src:项目根目录

main:存放源代码和项目资源

java:源代码

resources:项目资源

test:测试源代码

target:存放jar、war等

target/classes:存放字节码

target/test-classes:测试的字节码

webapp:web项目资源(图上没画,因为这个属于单另添加的文件夹)

pom.xml:配置各种项目资源的,比如说依赖哪些包,打包方式等

创建Maven

本地仓库结构

.m2文件夹用来存放本地的jar包,格式如下

image-20210331235723502

一个名字就是一个子目录

image-20210331235823231

依赖的jar包最终会放在target/lib中

修改相关配置信息

执行命令:mvn archetype:generate先不要执行,往下看

我们在运行时会发现如下信息,说明maven正在从远程仓库中下载一些东西,但是由于某种原因,下载起来会很慢,所以我们换个镜像来解决这个问题

image-20210331170317303

找到settings.xml文件夹,在maven_home/conf下面

image-20210331171518185

首先,我们先更改一下仓库路径,大约在55行,找到<localRepository>G:\Java_Study\maven\.m2\repository</localRepository>

中间的仓库路径可能和我的不一样,换成你自己想要的即可,这个**.m2文件夹**就是用来存放开篇讲的统一管理jar包的仓库,也就是上面这个图中下载的一些东西

然后修改镜像,大约在150-160行附近

<mirror>
      <id>aliyun</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun</name>
      <url>http://maven.aliyun.com/repository/public</url>
</mirror>

命令行方式创建

执行mvn archetype:generate

可以看到现在从国内的阿里云镜像中下载

image-20210331170156482

下载的这些东西最终会放在你配置好的.m2文件夹中,只会下载一次,下一次再执行这个代码就不会重复下载了

下载好以后他给出10中项目,问要创建哪一种,默认是7,也是我们所推荐的,所以直接回车即可

image-20210331172551048

接下来会让你输入一些信息

image-20210331172722529

groupId组织名称,一般是公司名倒过来,这里随便写一个比如com.baidu.maven等

artifactId就是项目名

version先按照默认的来,直接回车

package就是包名,直接回车,自动生成

结束后,当弹出成功的提示就代表你已经生成maven项目了!

Maven基本指令

maven的指令都需要先进入创建好的项目文件夹根目录中进行,否则找不到你的项目

编译

首先要在pom.xml文件中进行相关配置,maven默认你使用的时jdk7,但是我的项目用的是jdk14,如果直接编译的话肯定是报错的,所以我在这里就修改为jdk14,在<project>中添加以下内容,找到<properties>标签,没有就自己新建一个

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>14</maven.compiler.source>
    <maven.compiler.target>14</maven.compiler.target>
    <maven.compiler.complierVersion>14</maven.compiler.complierVersion>
</properties>

也可以直接在maven的settings.xml文件中200行左右添加这些代码,一劳永逸

<profile>
    <id>jdk14</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>14</jdk>
    </activation>
    <properties>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
        <maven.compiler.compilerVersion>14</maven.compiler.compilerVersion>
    </properties>
</profile>

image-20210331234816696

输入命令mvn compile即可成功编译,编译后的文件就放在maven项目的target/classes文件夹中

清除编译文件

mvn clean

会把编译后的文件target目录清除掉

单元测试

mvn test

运行test文件夹下的测试代码,编译后放入target/test-classes文件夹中

打包,生成Runnable Jar

mvn package

会将target/classes的文件打包到target目录下

在pom.xml中指定<packaging>jar<packaging>或者war

修改打包后的名字:build下面添加<finalName>名字</finalName>

打包的方式

方法一:maven-jar-plugin和maven-dependency-plugin

<build>  
    <plugins>  

        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-jar-plugin</artifactId>  
            <version>3.0,2</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <addClasspath>true</addClasspath>  
                        <classpathPrefix>lib/</classpathPrefix>  
                        <mainClass>com.xxx.Main</mainClass> <!--程序主类-->
                    </manifest>  
                </archive>  
                <finalName>jar的文件名</finalName>
            </configuration>  
        </plugin>  
        <!--管理依赖的插件,没有这个也运行不起来jar-->
        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-dependency-plugin</artifactId>  
            <version>3.1.2</version>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>copy-dependencies</goal>  
                    </goals>  
                    <configuration>           			<outputDirectory>${project.build.directory}/lib</outputDirectory>  
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build> 

maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xxx.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。

指定了Main-Class,有了依赖包,那么就可以直接通过java -jar xxx.jar运行jar包。

这种方式会生成一个jar包和一个lib文件夹(存放着项目依赖的jar包),所以打包以后要将两个文件给别人,比较麻烦

方法二:maven-assembly-plugin

<build>
	<plugins>
		<plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-assembly-plugin</artifactId>  
            <version>3.3.0</version>  
            <configuration>  
                <archive>  
                    <manifest>  
                        <mainClass>com.xxg.Main</mainClass>  
                    </manifest>  
                </archive>  
                <descriptorRefs>  
                    <descriptorRef>jar-with-dependencies</descriptorRef>  
                </descriptorRefs>  
                <finalName>jar的文件名</finalName>
                <appendAssemblyId>false</appendAssemblyId> <!--加上这个文件名就不会拼接了-->
            </configuration>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>single</goal>  
                    </goals>  
                </execution>  
            </executions>  
        </plugin>     
    </plugins>
</build>

其中package、single即表示在执行package打包时,执行assembly:single,所以可以直接使用mvn package打包。

打包后会在target目录下生成一个xxx-jar-with-dependencies.jar文件,这个文件不但包含了自己项目中的代码和资源,还包含了所有依赖包的内容。所以可以直接通过java -jar来运行。

方法三:maven-shade-plugin

<build>  
    <plugins>  

        <plugin>  
            <groupId>org.apache.maven.plugins</groupId>  
            <artifactId>maven-shade-plugin</artifactId>  
            <version>3.2.3</version>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>shade</goal>  
                    </goals>  
                    <configuration>  
                        <transformers>  
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
                                <mainClass>com.xxx.Main</mainClass>  
                            </transformer>  
                        </transformers>  
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build>  

配置完成后,执行mvn package即可打包。在target目录下会生成两个jar包,注意不是original-xxx.jar文件,而是另外一个。和maven-assembly-plugin一样,生成的jar文件包含了所有依赖,所以可以直接运行。

方法四:spring-boot-maven-plugin

<build>  
    <plugins>  

        <plugin>  
            <groupId>org.springframework.boot.plugins</groupId>  
            <artifactId>spring-boot-maven-plugin</artifactId>  
            <version>2.3.0.RELEASE</version>  
            <executions>  
                <execution>  
                    <phase>package</phase>  
                    <goals>  
                        <goal>repackage</goal>  
                    </goals>  
                    <configuration>  
                        <mainClass>com.xxx.Main</mainClass>  
                        <finalName>hellojava</finalName>
                    </configuration>  
                </execution>  
            </executions>  
        </plugin>  
    </plugins>  
</build>  

在Intellig Idea部署Maven

原始方法

先通过命令行生成maven项目,然后将pom.xml文件导入idea中(不推荐)

idea自带方法

上面这种方式虽然成功导入了idea中,但是通过导入pox.xml的方法未免也太麻烦了,还好idea为我们提供了一种更加便捷的方法,我们直接在新建项目的时候选择就可以了

我们之前命令行创建的maven项目其实在idea中是如下这一种quickstart方式,记得勾选上面那个,但是这个创建出来的会在pom.xml中添加一些其他东西,暂时用不上,所以我建议直接next

image-20210331180917591

然后输入以下信息,点击finish,这样就会创建出最原始的一个maven项目了

image-20210331181101594

记得在settings设置中把以下两个改成自己配置的,不要用它默认给出的,除非你之前没有在settings.xml文件中修改本地仓库路径

包括上面的maven home path,也要一并修改,最后的效果是这样的

image-20210331175724050

点开idea右边的maven,点开你的项目名,就能看到列举出一个生命周期,这个在之后会讲到,里面是不是有很多熟悉的指令?没错,在这里双击就可以运行刚才的指令了,是不是便捷很多

image-20210331180015416

现在来到pom.xml,非常清爽,没有那么多冗余项

image-20210331223820373

添加依赖jar包

所有的依赖jar包放在<dependencies>

<?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">
    <!-- pom的版本 -->
    <modelVersion>4.0.0</modelVersion>
	<!-- maven坐标,用来标识唯一的信息 -->
    <groupId>org.example</groupId>
    <artifactId>MyBatis</artifactId>
    <version>1.0-SNAPSHOT</version>
	<!-- 打包方式 -->
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
   
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>  <!-- 这里有个scope之后讲 -->
        </dependency>
    </dependencies>
</project>

进入[maven仓库](Maven Repository: Search/Browse/Explore)可以搜索你要用的依赖jar包具体的dependency怎么写

以junit为例,默认的junit是3.x版本的,使用的时候比较麻烦,所以要自己配置4.x版本的,直接通过@Test注解就可以在test中使用了,非常方便

首先搜索junit

image-20210331224602344

一般选择这个使用最多的,注意看清楚名字

image-20210331224738271

点击最新的即可

image-20210331224806135

全部复制粘贴即可

image-20210331224930709

有时候一个jar包又依赖其他的,我们可以在下面看到,依次导入即可

image-20210331225026300

配置完pom.xml文件后会出现这个按钮,如果代码中报了红线就证明你的本地仓库中没有下载这个依赖,点击一下这个按钮就会从远程仓库,配置过镜像就是去镜像中(我用的是阿里巴巴)自动下载,下一次其他项目再使用就不再需要下载了,不过仍然建议每次配置完了都点一次(有强迫症)

image-20210331225245541

有时写依赖包的作者没来得及上传到maven远程仓库,但是你又急需使用这个jar,那么首先想到可以在src同级目录中添加一个lib文件夹,把jar包放进去,但是这个时候上面讲的打包方式就不好使了,因为项目结构改变了,识别不到你加了新的文件夹

解决方案:安装本地jar到Maven的LocalRepository

mvn install:install-file -Dfile=jar的路径 -DgroupId=组织名 -DartifactId=库名 -Dversion=版本 -Dpackaging=jar

比如,我将jar包放到仓库中,并在仓库中打开命令行窗口,输入

mvn install:install-file -Dfile -Dfile=dom4j-2.1.3.jar -DgroupId=com.xxx -DartifactId=dom4j -Dversion=2.1.3 -Dpackaging=jar

构建生命周期

maven内置了3个构建生命周期

  • clean(清理)
  • default(默认)
  • site(站点)

构建生命周期由phase(阶段)组成

  • phase可以跟plugin goal(插件目标)绑定
  • plugin goal代表一个特定的任务
  • 一旦某个phase被执行,就会执行其绑定的所有goal
  • 可以通过mvn 插件名:help查看绑定了哪些goal
image-20210331234211328

之前学过的命令就是这样

mvn archetype:generate archetype插件执行generate目标

default生命周期

default生命周期由以下phase组成

image-20210331235247083

由上往下依次执行,使用mvn package会自动按顺序执行前四个阶段

在idea中查看生命周期

image-20210331180015416

install阶段:将打包好的jar包放到本地仓库中,双击以后会将前面的phase都执行一遍,然后本地仓库就会多出一个jar包

前面说了,一个phase对应多个goal,可以在执行了phase时在终端看到执行了哪些goal

image-20210401000312587

双击compile可以看到

image-20210401000802145

所以mvn compilermvn compiler:compiler+mvn resources:resources效果是一样的

继续理解打包方式中的一大堆代码含义

<plugin>  
    <groupId>org.apache.maven.plugins</groupId>  
    <artifactId>maven-dependency-plugin</artifactId>  
    <version>3.1.2</version>  
    <!--说明如何执行这个plug,把goal和phase绑定到一起才可以运行-->
    <executions>  
        <execution>   
            <!--在package阶段执行copy-dependencies这个goal-->
            <phase>package</phase>  
            <goals>  
                <goal>copy-dependencies</goal>  
            </goals>  
            <configuration>           						 <outputDirectory>${project.build.directory}/lib</outputDirectory>  
            </configuration>  
        </execution>  
    </executions>  
</plugin>  

dependency中的scope选值

  • compile默认,主代码运行时,测试代码运行时,打包好的jar给别人运行时,都可以用这个依赖

  • test依赖的jar包仅在测试编译和执行阶段可用,比如说junit,真正给别人运行时是不需要这个测试包的

  • runtime编译时不是必须的,运行时是必须的,用的较少

  • system之前举过一个本地jar包的例子,放在lib文件夹中,如果不想放在仓库中的话,就配置<scope>system</scope>并添加路径<systemPath>${basedir}/lib/jar包名字</systemPath>,这个时候,只需要在springboot那个插件中configuration添加<includeSystemScope>,并且右键jar包add as library即可使用。不推荐

  • provided仅在编译和测试类路径中可用,在tomcat插件中会介绍这个

常见问题

idea控制台乱码

-Dfile.encoding=GBK

image-20210401003301361

修改Maven项目的JDK版本

maven默认你是jdk5,要自己修改

image-20210401003958465

方法一 :在pom.xml中添加属性,每个Maven项目都要

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>14</maven.compiler.source>
    <maven.compiler.target>14</maven.compiler.target>
    <maven.compiler.complierVersion>14</maven.compiler.complierVersion>
</properties>

方法二:在pom.xml中添加插件,每个Maven项目都要

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
    	<source>14</source>
        <target>14</target>
    </configuration>
</plugin>

方法三:在%MAVEN_HOME%/conf/settings.xml的<profile>标签中添加信息,一劳永逸

<profile>
    <id>jdk14</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>14</jdk>
    </activation>
    <properties>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
        <maven.compiler.compilerVersion>14</maven.compiler.compilerVersion>
    </properties>
</profile>

maven中Web项目补充webapp包

我们生成的maven,缺少webapp文件夹,

现在我们通过Idea创建,一定要先将打包方式写为war,在Maven中,如果打包方式为war就证明是web项目

image-20210401011108903

配置好以后就会出现webapp

Tomcat插件

非Maven项目在idea中部署tomcat方法
  • 创建空java项目

image-20210401004345506

  • 输入项目名和路径后点击finish

  • 右键模块文件夹,点击add framework support

    image-20210401004619832

  • 勾选web application并确定

  • image-20210401004719911

  • 点击add configuration

    image-20210401004811090

  • 点击+号,选择tomcat server 的 local

    image-20210401004904148

  • 点击configure配置tomcat home,注意是根目录

    image-20210401005032717

  • 添加模块到tomcat中

    image-20210401005150594

  • 设置自己的context

    image-20210401005214768

  • 点击确定完成配置

  • 如果没找到自己的模块,就去项目结构中添加

    image-20210401005439351

    image-20210401005420590

不是maven项目的话最终会打包到out/artifacts目录下

怎么找到的呢?

启动tomcat,在Catalina_base目录下找到项目路径名.xml,里面配置了相关信息

image-20210401005800092

image-20210401005911405

image-20210401010028706

我们先不用idea的tomcat工具,先通过maven插件来配置tomcat

maven添加tomcat插件
<!--后面还要加东西,别着急复制-->
<build>
	<plugins>
		<plugin>
    		<groupId>org.apache.tomcat.maven</groupId>    
            <artifactId>tomcat7-maven-plugin</artifactId>
            <verison>2.2</verison>
        </plugin>    
    </plugins>
</build>

pom.xml写完后一定要点以下按钮更新配置

我们在idea的maven模块中找到这个goal,双击运行

image-20210401011841532

此时页面会报错,原因是tomcat7插件运行时会提供一个servlet-api.jar包,而自己在写代码时必须也添加一个servlet-api.jar包来运行代码,这样就会导致jar包冲突,此时就用到<scope>标签中的provided,仅在JDK或容器(tomcat插件)运行时提供它,即编译时和测试时提供,防止检测不到jar包报错,而运行时自己就不提供了

以前手动放置jar包为什么不报错:idea提供支持,优化过了,而Maven不行,他只会帮助你下载并依赖jar包,功能没有idea这么强

tomcat插件版本问题

双击tomcat7:run时默认使用tomcat7,而不是用自己下载的tomcat9,而现在这个插件下载不了tomcat9,没有这个插件,所以我们采用如下方案

先启动tomcat9,然后通过mvn tomcat7:deploy将项目部署到tomcat9中,不要用tomcat7:run

如何部署?

tomcat9中:

image-20210401013604325

在文件中开放用户权限,有了权限才给部署

image-20210401013628913

  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <user username="root" password="root" roles="manager-gui,manager-script"/>

maven中:

在settings.xml添加server

image-20210401013811700

<server>
    <id>tomcat9</id>
    <username>root</username>
    <password>root</password>
</server>

两个文件配置要一致

最后在pom.xml中添加如下代码

<build>
	<plugins>
		<plugin>
    		<groupId>org.apache.tomcat.maven</groupId>    
            <artifactId>tomcat7-maven-plugin</artifactId>
            <verison>2.2</verison>
            <configuration>
        	   <path>/context_path</path>    <!--根据之前填写的来,我写的是/test-->
                <port>8080</port>
                <update>true</update>  <!--开启热部署-->
                <url>http://localhost:8080/manager/text</url> <!--默认访问这个url连接tomcat9,可以省略-->
                <uriEncoding>UTF-8</uriEncoding>
                <server>tomcat9</server> <!--之前在maven中配置过用户名密码,所以这里直接用当初配置的那个id-->
                <!-- <username>root</username> -->
    		   <!-- <password>root</password> -->
            </configuration>
        </plugin>    
    </plugins>
</build>

都配置好以后,双击tomcat9的startup.bat,或者idea中的调试按钮,然后在maven中使用mvn tomcat7:deploy即可

tomcat7中文请求乱码问题

上面的配置中有<uriEncoding>UTF-8</uriEncoding>

image-20210401015036993

tomcat8、9:

  • get请求:中文参数没问题
  • post请求:中文参数乱码
    • 解决方法:request.setCharacterEncoding("UTF-8") response.setContentType("text/plain;charset=UTF-8")

tomcat7及以前,两种请求给tomcat都有问题,浏览器会将中文进行utf-8编码,即张三变成%E5%BC…,tomcat拿到以后要按照同样的编码方式进行解码,所以要进行配置<uriEncoding>UTF-8<uriEncoding>

maven项目在idea中部署tomcat

每次执行tomcat7:deploy时,观察日志,都会将项目部署到这个地址,也就是tomcat9中,这样做效率太低

image-20210401210513854

所以我们还是在idea中自带的tomcat部署就可以了…

  • idea打包:image-20210401211439152

    横线处的名字通过build下面添加finalName标签修改

  • maven打包:basedir/target/project名

可以发现如果是maven项目,两种方式进行打包输出目录是一样的(idea非常聪明,如果输出目录不一致的话,两种方法放在两个目录中,难维护代码),而非maven项目idea会打包放在out/artifacts/

maven打包乱码的问题

maven在进行打包时默认使用和操作系统一样的编码方式,Windows就是GBK,然而我们在编写Java代码的时候采用的是UTF-8的编码,这就会导致maven编译项目时(compile阶段,在打包之前必须执行这一步)编出来的就是乱码,解决的方案就是在pom.xml中添加代码告诉maven我们的Java项目是用UTF-8存储的,记得用UTF-8的方式编译打包

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

tomcat拿到以后要按照同样的编码方式进行解码,所以要进行配置<uriEncoding>UTF-8<uriEncoding>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值