前段时间进行了一点 maven 的入门学习,在这里做个记录,希望能帮到一些正在学习的朋友们。maven 版本为 3.3.9。希望大家觉得好的点个赞,觉得不好的多提提意见和建议做个交流。这里也贴出我学习 Maven 的视频地址,大家也可以自行观看
首先,在中下载 maven 组件。进入官网后,在左边菜单找到 Download 选项,点击进入 Download 页面。
下拉页面,在 File 下选择合适的文件进行下载。
Maven 与 JDK 一样,需要配置环境变量,先建立一个 M2_HOME 变量,方便以后移动的时候修改路径,随后在 Path 中加入:%M2_HOME%\bin;
配置后在控制台输入 mvn -v , 出现 maven 及 jdk 的相关信息即为配置成功:
至此,即可完成 maven 环境变量的配置。
maven 工程与以往的 java 工程目录结构有所不同,以往的 java 工程目录目录一般只有一个 src 用于存放包及 java 文件,而 maven 工程目录长这样:
src
-main
-java
- 包
-test
-java
- 包
一般我们将一些主要的内容,放在 main/java 下面,而测试代码放在 test/java 下,这样在运行时,maven 才可以识别目录并进行编译。
了解了目录结构后,就可以开始第一个 maven 项目了。(为了更加便于理解 maven,暂时采用控制台 + 记事本 Editplus 的操作方式,IDE 将在后面使用。)
先按照目录结构建立好目录:、,这里包名为 cn.edu.HelloWorld
先编写 Hello.java:
- 1 package cn.edu.HelloWorld;
- 2 3 public class Hello {
- 4 public String sayHello() {
- 5
- return "Hello Maven";
- 6
- }
- 7
- }
再编写测试 TestClass.java,这里使用 junit4 框架:
- 1 package cn.edu.HelloWorld;
- 2
- 3 import org.junit.*;
- 4
- 5 public class TestClass{
- 6 @Test
- 7 public void testHello(){
- 8 System.out.println(new Hello().sayHello());
- 9 }
- 10 }
添加一个 maven 的配置文件 pom.xml(该文件在一些开源框架中如 struts,spring 中可以找到,也可以百度进行下载,在这里也提供一份,以供复制):
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/maven-v4_0_0.xsd">
- <modelVersion>
- 4.0.0
- </modelVersion>
- <!--groupId、artifactId、version为必需,将在后面介绍-->
- <groupId>
- cn.edu.HelloWorld
- </groupId>
- <artifactId>
- maven01
- </artifactId>
- <version>
- 0.0.1SNAPSHOT
- </version>
- <dependencies>
- <!--在这里引入junit4的依赖-->
- <dependency>
- <groupId>
- junit
- </groupId>
- <artifactId>
- junit
- </artifactId>
- <version>
- 4.12
- </version>
- </dependency>
- </dependencies>
- </project>
打开控制台,进入到工程的目录下,执行 mvn compile 命令:
看到 BUILD SUCCESS 表示编译成功(第一次编译可能需要下载环境比较慢)
编译成功后会在项目下生成一个 target 文件夹,里面存放编译后的文件
编译成功后执行 mvn test 命令,运行测试类:
看到 SUCCESS 即可看到结果,输出 Hello Maven:
来看一下 maven 几个常用的构建命令,格式为 mvn xxx:
mvn
-v 查看 maven 版本及其他相关信息
compile 编译 maven 项目,并生成 target 文件夹
test 运行 test 目录下的测试文件,即测试
package 将项目打包,默认打包为 jar 格式,也可以打包成 war 格式用于服务器运行
install 将打包的 jar 文件安装到 maven 本地仓库(仓库后面会详细介绍)
clean 删除 targert,相当于清除缓存
在前面我们采用手动的方式进行目录建立,显得略微有点繁琐,那么这里介绍一个插件用于生成符合 maven 规范的目录。
首先从控制台进入需要生成文件夹的位置,然后运行 mvn archetype:generate(第一次需要下载组件比较慢, 若是下载不下来可以设置一下 maven 的国内镜像库,百度即有步骤,这里不做介绍):
出现以下界面,提示我们选择生成一个版本类型的 maven 结构,这里选择 7(默认为 7),quickstart:
确认后要求输入 groupId、artifactId(也会作为文件夹名)、version(默认为 1.0-SNAPSHOT)、package(即包的结构),这里依次输入:
提示确认,输入 Y 确认后进行生成。出现 SUCCESS,则表示生成成功:
进入生成的项目中,输入 mvn compile test 进行确认:
打开文件夹即可看到我们生成的文件目录,已经符合了 maven 规范,且可以运行。
groupId: 项目组织唯一的标识符,一般为反写的公司网址 + 项目名
artifactId: 项目的唯一的标识符,一般为项目名 + 模块名
version: 版本号 x.x.x + 版本类型
第一个 x 表示大版本号
第二个 x 表示分支版本号
第三个 x 表示小版本号(可省略)
常见版本类型:
snapshot 快照
alpha 内部测试
beta 公测
release 稳定
GA 正式发布
注:包名应与 groupId+artifactId 相吻合
maven 中的依赖管理就是靠着仓库,仓库分为中央仓库及本地仓库。在编译项目时,maven 会根据配置的依赖,先在本地仓库中进行搜索,若是没有则再去中央仓库进行搜索,而搜索便是采用坐标进行查找。
默认本地仓库位于 C 盘之下,如果进行还原系统之类的便会清空十分不便,这里说一下更改本地仓库路径的方法:
多个生命周期之间相互独立。每个生命周期含有多个阶段,阶段按顺序执行,运行后阶段时,前阶段会自动执行。比如,直接运行 mvn test 命令,那么执行该命令时,会自动的附带 mvn compile 命令,因为 test 阶段在 compile 阶段之后。
完整的项目构建构成包括:
清理、编译、测试、打包、集成测试、验证、部署
clean 清理项目,包括以下阶段:
pre-clean 执行清理前
clean 清理上一次构建生成的所有文件
post-clean 执行清理后的文件
default 构建项目 (核心:常用),包括以下阶段
compile 编译
test 测试
packeage 打包
install 安装
site 生成项目站点, 根据 pom 中信息生成项目站点,包括以下阶段
pre-site 在生成项目站点前要完成的工作
site 生成项目的站点文档
post-site 在生成项目站点后要完成的工作
site-deploy 发布生成的站点到服务器上
maven 中提供了许多功能强大的插件,让我们更好的管理项目。一个插件通常提供了一组目标,可使用以下语法来执行:
类型 | 描述 |
---|---|
构建插件 | 在生成过程中执行,并在 pom.xml 中的 <build/> 元素进行配置 |
报告插件 | 在网站生成期间执行,在 pom.xml 中的 <reporting/> 元素进行配置 |
以下是一些常见的插件列表:
插件 | 描述 |
---|---|
clean | 编译后的清理目标,删除目标目录 |
compiler | 编译 Java 源文件 |
surefile | 运行 JUnit 单元测试,创建测试报告 |
jar | 从当前项目构建 JAR 文件 |
war | 从当前项目构建 WAR 文件 |
javadoc | 产生用于该项目的 Javadoc |
antrun | 从构建所述的任何阶段运行一组 Ant 任务 |
source | 从当前项目构建带源码的 JAR 文件 |
这里我们通过使用 source 插件作为例子,来看看如何在 maven 中配置插件:
首先我们快速创建一个 maven 项目(可以使用 archetype),在 pom.xml 中加入以下内容:
- <build>
- <!-- 配置插件集 -->
- <plugins>
- <plugin>
- <!--使用插件的坐标进行引用 -->
- <groupId>
- org.apache.maven.plugins
- </groupId>
- <artifactId>
- maven-source-plugin
- </artifactId>
- <version>
- 3.0.0
- </version>
- <executions>
- <execution>
- <!-- 绑定在哪个过程时一同执行,这里我们让它在使用package打包时一同执行 -->
- <phase>
- package
- </phase>
- <!--执行的目标类型,关于目标的详细介绍可以在maven官网中查到-->
- <goals>
- <goal>
- jar-no-fork
- </goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
接下来,在命令控制台,输入 mvn package 查看结果:
出现成功信息后,可以在我项目的 target 中找到打包后的 jar 文件及 src-jar 文件
从这个例子中,我们可以总结出以下几个关键点:
本节开始使用 Eclipse 进行编写,使用上与控制台方式出入不大。先略微介绍下 Eclipse 中构建 maven 项目:在新建项目时选择 maven project(需安装 maven 插件,eclipse3.1 以上自带)
设置好路径后在选择版本的界面,选择 quickstart 版本:
输入信息后点击 finish 即可构建 maven 项目:
完成步骤后,一般情况下会自动创建符合规范的 maven 项目。个别出现文件夹不符合规范的情况,可以使用项目右键→new→source folder 自行创建补充。
运行命令只要右键项目,run as→maven build 的 Goals 中输入即可,这里输入时不需输入 mvn。例如:mvn compile 只需输入 compile。
先来看看什么是传递依赖,比如现在有这么个情况:
C 依赖 B、B 依赖 A——C→B→A,那么此时 C 也会依赖 A 且会包含 A 中的依赖, 这就是传递依赖。接下来我们通过一个例子来详细了解依赖及如何消除传递依赖:
现有 ABC 三个项目:
A 中额外依赖了一个 commons-io 的 jar 包:
B 中对 A 进行依赖:
C 中对 B 进行依赖:
保存之后可以看到,C 中不但包含 B,还包含 A 和 A 依赖的 common-io:
那么如何消除传递依赖呢,这里就使用到 <exclusion> 标签了,在 C 中配置依赖 B 的地方加入以下内容:
保存后就可以看到,C 中关于 A 的依赖消失了,传递依赖的问题就解决了。
假设现在有这么个情况:A 依赖 common-io 的 2.4 版本,B 依赖 common-io 的 2.5 版本,C 依赖 A、B,那么此时 C 中的 common-io 是哪个版本的?
这就是依赖冲突,在 maven 中应对依赖冲突有两种解决方式:短路优先,先声明优先
先声明优先:顾名思义,在 pom 中,写在配置文件上面的优先,比如此时 A 的依赖配置在 B 之上,那 C 中就为 2.4 版本的 common-io。
短路优先:优先选择依赖路径较短的一端。假设现在多出一个 D,依赖情况改为 D 依赖 B,C 依赖 A、D——C→A、C→D→B,那么这里就是 A 的依赖路径比较短,所以为 2.4 版本。
试想一下这样的情况,在一个项目中,分模块使用了 maven,那么可能在这个项目中会有五六个,或者更多的 maven 项目存在。如果此时需要编译或测试要怎么办呢,进入每个 maven 项目中进行 mvn compile 么,那就要执行五六次的 compile 命令,十分繁琐,这里就可以用 maven 的聚合来解决这个问题。
现有 ABC 三个工程,那么我们使用一个新的工程 D,来聚合他们,以后只要对 D 进行编译即可对三个工程同时进行编译。使用 module 标签进行聚合:
另一种情形,如果多个 maven 项目具有相同的依赖时或配置时,那么应该如何处理呢?这里就用到继承的概念,在 maven 中使用 <parent> 标签来进行继承,下面通过一个例子来看一下:
首先建立一个项目,命名为 parent,在 parent 的 pom 文件声明一个 common-io 的依赖,不过这里用到了 dependencyManagement:
- <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>
- cn.edu
- </groupId>
- <artifactId>
- parent
- </artifactId>
- <version>
- 0.0.1-SNAPSHOT
- </version>
- <packaging>
- pom
- </packaging>
- <name>
- parent
- </name>
- <url>
- http://maven.apache.org
- </url>
- <properties>
- <project.build.sourceEncoding>
- UTF-8
- </project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>
- junit
- </groupId>
- <artifactId>
- junit
- </artifactId>
- <version>
- 4.12
- </version>
- <scope>
- test
- </scope>
- </dependency>
- </dependencies>
- <dependencyManagement>
- <!-- 在这里声明的依赖可以被子项目继承引用 -->
- <dependencies>
- <dependency>
- <groupId>
- commons-io
- </groupId>
- <artifactId>
- commons-io
- </artifactId>
- <version>
- 2.4
- </version>
- </dependency>
- </dependencies>
- </dependencyManagement>
- </project>
可以看到,虽然我们在父项目中配置了依赖,但是却不会在父项目中被引用:
在子项目 B 中,配置继承 parent 并使用 parent 中的 common-io 版本:
配置后保存即可看到,此处的依赖版本即为父项目中的版本:
这里介绍两种的 web 项目:规范目录的 web 项目及传统目录的 web 项目。再介绍使用两种服务器容器:tomcat 和 jetty 运行的方法。由于 tomcat 中有许多的需要注意的问题,较为复杂,所以这里先从简单的 jetty 入手。
首先构建项目,这次选择版本的时候我们选择 webapp:
建立好后的 webapp 项目,其目录结构是这样的:
这里的 resources 文件夹用于存放 java 文件、包、xml 配置文件等等,与我们传统意义上的 src 文件夹是一致的。这里 src 下的 webapp 文件夹则等同于我们 Web 项目中的 WebRoot 或 WebContent,一些页面和样式等文件放在这个目录下。
接下来看看 pom 文件:
先注意到我们这里的打包方式变为了 war,web 项目必需先编译打包,然后才能部署到 web 容器上运行。之后只需配置我们的 jetty 运行插件。
- <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/maven-v4_0_0.xsd">
- <modelVersion>
- 4.0.0
- </modelVersion>
- <groupId>
- cn.edu
- </groupId>
- <artifactId>
- mavenweb
- </artifactId>
- <packaging>
- war
- </packaging>
- <version>
- 1.2.2-SNAPSHOT
- </version>
- <name>
- mavenweb Maven Webapp
- </name>
- <url>
- http://maven.apache.org
- </url>
- <dependencies>
- <dependency>
- <groupId>
- junit
- </groupId>
- <artifactId>
- junit
- </artifactId>
- <version>
- 4.12
- </version>
- <scope>
- test
- </scope>
- </dependency>
- </dependencies>
- <build>
- <finalName>
- mavenweb
- </finalName>
- <plugins>
- <!--这里用到jetty的插件,在官网中可以找到坐标-->
- <plugin>
- <groupId>
- org.eclipse.jetty
- </groupId>
- <artifactId>
- jetty-maven-plugin
- </artifactId>
- <version>
- 9.4.1.v20170120
- </version>
- </plugin>
- </plugins>
- </build>
- </project>
先使用 package 命令进行打包,可以看到 target 中出现了我们 webapp 文件夹下的内容,以及打包好的 war 文件。
复制使用这个 war 文件也可完成部署。但我们这里使用 jetty 插件,在命令框中输入 jetty:run 命令, 观察到
说明服务器启动完成。
接下来在浏览器使用 localhost:8080 即可看到我们的项目中的 index.jsp
至此就完成了我们规范目录的 web 项目构建。
使用 maven 的 web 项目结构,可能会有少许的不习惯,或者我们要将以前开发的项目转为 mavenweb 项目的话,那要怎么办呢?这里就介绍下非规范目录的 web 项目要如何构建。
首先,这是我们的项目目录结构,java 等文件还是放在 main/java 下,而页面等其他资源文件放在 WebContent 下:
看看 pom 文件中的配置方法:
- <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/maven-v4_0_0.xsd">
- <modelVersion>
- 4.0.0
- </modelVersion>
- <groupId>
- cn.edu
- </groupId>
- <artifactId>
- mavenweb
- </artifactId>
- <packaging>
- war
- </packaging>
- <version>
- 1.2.2-SNAPSHOT
- </version>
- <name>
- mavenweb Maven Webapp
- </name>
- <url>
- http://maven.apache.org
- </url>
- <dependencies>
- <dependency>
- <groupId>
- junit
- </groupId>
- <artifactId>
- junit
- </artifactId>
- <version>
- 4.12
- </version>
- <scope>
- test
- </scope>
- </dependency>
- </dependencies>
- <build>
- <finalName>
- mavenweb
- </finalName>
- <!-- 资源集 -->
- <resources>
- <!-- 非规范资源文件目录打包 -->
- <resource>
- <!-- 指定资源存放的目录(必需,不写会报错),即resources目录的变更。以下配置中的的相对目录改为该目录 -->
- <directory>
- src/main/java
- </directory>
- <includes>
- <include>
- *.xml
- </include>
- </includes>
- <!-- 是否替换资源文件中的属性,如${username},替换为pom中指定的properties-->
- <filtering>
- false
- </filtering>
- </resource>
- </resources>
- <plugins>
- <!--这里使用到war plugin,同样的,详细介绍及坐标在官网中可以找到-->
- <plugin>
- <groupId>
- org.apache.maven.plugins
- </groupId>
- <artifactId>
- maven-war-plugin
- </artifactId>
- <version>
- 3.0.0
- </version>
- <configuration>
- <!-- 指定web.xml的文件位置 -->
- <webXml>
- WebContent/WEB-INF/web.xml
- </webXml>
- <!-- war的源目录,由哪个文件夹打包成war文件,用于更改页面样式等的资源目录 -->
- <warSourceDirectory>
- WebContent
- </warSourceDirectory>
- </configuration>
- </plugin>
- <plugin>
- <groupId>
- org.eclipse.jetty
- </groupId>
- <artifactId>
- jetty-maven-plugin
- </artifactId>
- <version>
- 9.4.1.v20170120
- </version>
- </plugin>
- </plugins>
- </build>
- </project>
完成配置后,使用 package 命令进行打包。看到 target 中的打包结果,确实更改了来源目录并打包成功:
接下来使用 jetty:run 或 jetty:deploy 等运行命令即可成功运行项目。
使用 tomcat 时,会遇上许多的问题,在这里整理,希望能帮上一些朋友。
问题一:tomcat 插件版本问题
tomcat 这个插件在官网的描述中是这样的:
那么我这里使用的是 tomcat7, 我就使用了下面的那份坐标,但是在使用 tomcat:run 命令是发现:
也是找了好久才发现这个问题,我明明使用的是 tomcat7 的插件,但是运行起来却是不知道哪里来的 6.0 版本。
正确的方式是:运行 tomcat7:run 命令,其实这点在官网中也有提到,怪自己没认真看了。
tomcat:run 默认使用的是 6.0 版本的 tomcat,但是奇怪的一点,我机子上并没有 6.0 版本的 tomcat,那么这里的是哪来的呢?希望有大神知晓的能够解答,先谢过了!
问题二:Cannot invoke Tomcat manager: Server rened HTTP response code: 403 for URL
这个问题,第一是要打开 tomcat 的 Manage 权限,在百度有许多相关的解决方法,我就不多说了。这里贴几个我觉得写的还不错的帖子:
第二个点,也是我遇上的主要问题:Eclipse 的 tomcat 的 webapp 目录为 workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps,而并非 $CATALINA_HOME/webapp,这也就导致了 Eclipse 中启动 tomcat 的话,是没有 Root、Manage 等项目的,更不用说 Manage 权限了。
解决方式:
最后,贴上最终我的 pom 文件,供大家做个参考:
pom.xml
- <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/maven-v4_0_0.xsd">
- <modelVersion>
- 4.0.0
- </modelVersion>
- <groupId>
- cn.edu
- </groupId>
- <artifactId>
- mavenweb
- </artifactId>
- <packaging>
- war
- </packaging>
- <version>
- 1.2.2-SNAPSHOT
- </version>
- <name>
- mavenweb Maven Webapp
- </name>
- <url>
- http://maven.apache.org
- </url>
- <dependencies>
- <dependency>
- <groupId>
- junit
- </groupId>
- <artifactId>
- junit
- </artifactId>
- <version>
- 4.12
- </version>
- <scope>
- test
- </scope>
- </dependency>
- <dependency>
- <groupId>
- javax.servlet
- </groupId>
- <artifactId>
- javax.servlet-api
- </artifactId>
- <version>
- 3.1.0
- </version>
- <scope>
- provided
- </scope>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.apache.struts/struts2-core
- -->
- <dependency>
- <groupId>
- org.apache.struts
- </groupId>
- <artifactId>
- struts2-core
- </artifactId>
- <version>
- 2.5.8
- </version>
- </dependency>
- </dependencies>
- <build>
- <finalName>
- mavenweb
- </finalName>
- <!-- 资源集 -->
- <resources>
- <!-- 非规范资源文件目录打包 -->
- <resource>
- <!-- 指定资源存放的目录(必需,不写会报错)基础目录,以下目录全在该目录下 -->
- <directory>
- src/main/java
- </directory>
- <includes>
- <include>
- *.xml
- </include>
- </includes>
- <!-- 是否替换资源文件中的属性,如${username},替换为pom中指定的properties-->
- <filtering>
- false
- </filtering>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>
- org.apache.maven.plugins
- </groupId>
- <artifactId>
- maven-war-plugin
- </artifactId>
- <version>
- 3.0.0
- </version>
- <configuration>
- <!-- 指定web.xml的文件位置 -->
- <webXml>
- WebContent/WEB-INF/web.xml
- </webXml>
- <!-- war的源目录,由哪个文件夹打包成war文件,用于更改资源目录 -->
- <warSourceDirectory>
- WebContent
- </warSourceDirectory>
- <!-- <webappDirectory>WebContent</webappDirectory> 打包的目标目录-->
- </configuration>
- </plugin>
- <plugin>
- <groupId>
- org.apache.tomcat.maven
- </groupId>
- <artifactId>
- tomcat7-maven-plugin
- </artifactId>
- <version>
- 2.1
- </version>
- <configuration>
- <url>
- http://localhost:8080/manager/html
- </url>
- <server>
- tomcat7
- </server>
- <!-- 此处的名字必须和setting.xml中配置的ID一致 -->
- <username>
- admin
- </username>
- <password>
- root
- </password>
- <path>
- /mavenweb
- </path>
- <!-- 此处的名字是项目发布的工程名 -->
- </configuration>
- </plugin>
- <plugin>
- <groupId>
- org.eclipse.jetty
- </groupId>
- <artifactId>
- jetty-maven-plugin
- </artifactId>
- <version>
- 9.4.1.v20170120
- </version>
- </plugin>
- </plugins>
- </build>
- </project>
来源: http://www.cnblogs.com/qbzf-Blog/p/6539161.html