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包进行统一管理(后面会详细讲解),是不是看起来就比传统的项目高级了很多呢!
当然,Maven的功能远不止这么简单,下面就从最基本的配置环境开始一起来学习Maven吧!
Maven安装
下载与安装
我们首先在上面的下载地址中下载,解压后放到你自己的磁盘里就行了
配置环境变量
由于Maven是用Java编写的,依赖于Java包,所以我们首先要确保自己的JAVA_HOME环境变量配置完成,最好在path中也将maven根目录下面的bin目录配置进去
注意:两个home配置的都是根目录,也就是解压以后的那个文件夹
此时打开CMD,输入mvn -v
,如果显示出版本号则证明maven配置成功!
Maven项目目录结构
创建Maven项目时,Maven将创建默认的项目结构,开发人员只需要相应地放置文件即可
src:项目根目录
main:存放源代码和项目资源
java:源代码
resources:项目资源
test:测试源代码
target:存放jar、war等
target/classes:存放字节码
target/test-classes:测试的字节码
webapp:web项目资源(图上没画,因为这个属于单另添加的文件夹)
pom.xml:配置各种项目资源的,比如说依赖哪些包,打包方式等
创建Maven
本地仓库结构
.m2文件夹用来存放本地的jar包,格式如下
一个名字就是一个子目录
依赖的jar包最终会放在target/lib中
修改相关配置信息
执行命令:mvn archetype:generate
,先不要执行,往下看
我们在运行时会发现如下信息,说明maven正在从远程仓库中下载一些东西,但是由于某种原因,下载起来会很慢,所以我们换个镜像来解决这个问题
找到settings.xml文件夹,在maven_home/conf下面
首先,我们先更改一下仓库路径,大约在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
可以看到现在从国内的阿里云镜像中下载
下载的这些东西最终会放在你配置好的.m2文件夹中,只会下载一次,下一次再执行这个代码就不会重复下载了
下载好以后他给出10中项目,问要创建哪一种,默认是7,也是我们所推荐的,所以直接回车即可
接下来会让你输入一些信息
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>
输入命令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
然后输入以下信息,点击finish,这样就会创建出最原始的一个maven项目了
记得在settings设置中把以下两个改成自己配置的,不要用它默认给出的,除非你之前没有在settings.xml文件中修改本地仓库路径
包括上面的maven home path,也要一并修改,最后的效果是这样的
点开idea右边的maven,点开你的项目名,就能看到列举出一个生命周期,这个在之后会讲到,里面是不是有很多熟悉的指令?没错,在这里双击就可以运行刚才的指令了,是不是便捷很多
现在来到pom.xml,非常清爽,没有那么多冗余项
添加依赖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
一般选择这个使用最多的,注意看清楚名字
点击最新的即可
全部复制粘贴即可
有时候一个jar包又依赖其他的,我们可以在下面看到,依次导入即可
配置完pom.xml文件后会出现这个按钮,如果代码中报了红线就证明你的本地仓库中没有下载这个依赖,点击一下这个按钮就会从远程仓库,配置过镜像就是去镜像中(我用的是阿里巴巴)自动下载,下一次其他项目再使用就不再需要下载了,不过仍然建议每次配置完了都点一次(有强迫症)
有时写依赖包的作者没来得及上传到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
之前学过的命令就是这样
mvn archetype:generate
archetype插件执行generate目标
default生命周期
default生命周期由以下phase组成
由上往下依次执行,使用
mvn package
会自动按顺序执行前四个阶段
在idea中查看生命周期
install阶段:将打包好的jar包放到本地仓库中,双击以后会将前面的phase都执行一遍,然后本地仓库就会多出一个jar包
前面说了,一个phase对应多个goal,可以在执行了phase时在终端看到执行了哪些goal
双击compile可以看到
所以mvn compiler
和mvn 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
修改Maven项目的JDK版本
maven默认你是jdk5,要自己修改
方法一 :在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项目
配置好以后就会出现webapp
Tomcat插件
非Maven项目在idea中部署tomcat方法
- 创建空java项目
-
输入项目名和路径后点击finish
-
右键模块文件夹,点击add framework support
-
勾选web application并确定
-
点击add configuration
-
点击+号,选择tomcat server 的 local
-
点击configure配置tomcat home,注意是根目录
-
添加模块到tomcat中
-
设置自己的context
-
点击确定完成配置
-
如果没找到自己的模块,就去项目结构中添加
不是maven项目的话最终会打包到out/artifacts目录下
怎么找到的呢?
启动tomcat,在Catalina_base目录下找到项目路径名.xml,里面配置了相关信息
我们先不用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,双击运行
此时页面会报错,原因是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中:
在文件中开放用户权限,有了权限才给部署
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="root" password="root" roles="manager-gui,manager-script"/>
maven中:
在settings.xml添加server
<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>
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中,这样做效率太低
所以我们还是在idea中自带的tomcat部署就可以了…
-
idea打包:
横线处的名字通过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>