一个小时学会Maven
一、为什么要Maven
在开发中经常需要依赖第三方的包,包与包之间存在依赖关系,版本间还有兼容性问题,有时还里要将旧的包升级或降级,当项目复杂到一定程度时包管理变得非常重要。
Maven是当前最受欢迎的Java项目管理构建自动化综合工具,类似以前Java中的Ant、node.js中的npm、dotNet中的nuget、PHP中的Composer。
Maven这个单词来自于意第绪语(犹太语),意为知识的积累。
Maven提供了开发人员构建一个完整的生命周期框架。开发团队可以自动完成项目的基础工具建设,Maven使用标准的目录结构和默认构建生命周期。Maven让开发人员的工作更轻松,同时创建报表,检查,构建和测试自动化设置。Maven简化和标准化项目建设过程。处理编译,分配,文档,团队协作和其他任务的无缝连接。 Maven增加可重用性并负责建立相关的任务。
每个Java项目的目录结构都没有一个统一的标准,配置文件到处都是,单元测试代码到底应该放在那里也没有一个权威的规范。
因此,我们就要用到Maven(使用Ant也可以,不过编写Ant的xml脚本比较麻烦)----一个项目管理工具。
Maven主要做了两件事:
- 统一开发规范与工具
- 统一管理jar包
如果没有Maven,你可能不得不经历下面的过程:
1 如果使用了spring,去spring的官网下载jar包;如果使用hibernate,去hibernate的官网下载Jar包;如果使用Log4j,去log4j的官网下载jar包..... 2 当某些jar包有依赖的时候,还要去下载对应的依赖jar包 3 当jar包依赖有冲突时,不得不一个一个的排查 4 执行构建时,需要使用ant写出很多重复的任务代码 5 当新人加入开发时,需要拷贝大量的jar包,然后重复进行构建 6 当进行测试时,需要一个一个的运行....检查
有了Maven,它提供了三种功能:
1 依赖的管理:仅仅通过jar包的几个属性,就能确定唯一的jar包,在指定的文件pom.xml中,只要写入这些依赖属性,就会自动下载并管理jar包。 2 项目的构建:内置很多的插件与生命周期,支持多种任务,比如校验、编译、测试、打包、部署、发布... 3 项目的知识管理:管理项目相关的其他内容,比如开发者信息,版本等等
官网:http://maven.apache.org/
教程:https://www.yiibai.com/maven/
Maven库:http://repo2.maven.org/maven2/
中央仓库资源:
http://mvnrepository.com/
https://search.maven.org/
二、安装与配置
其实主流的开发工具如IDEA、Eclipse都集成了Maven(可见重要性),但为了更加深刻的学习与管理该工具(比如多个IDE共享的问题),个人建议还是单独安装比较好。
2.1、官网下载安装包
在浏览器中打开下载地址:http://maven.apache.org/download.cgi
2.2、配置环境变量
注意:安装maven之前,必须先确保你的机器中已经安装了JDK,如果是Maven3则必须JDK1.7以上。
1.解压压缩包
2.添加环境变量MAVEN_HOME,值为apache-maven的安装路径(没有中文)
3.在Path环境变量的变量值末尾添加%MAVEN_HOME%\bin;
4.在cmd输入mvn –version,如果出现maven的版本信息,说明配置成功。
2.3、本地仓储配置
如果您不配置,默认会在如下位置存放从远程下载到的包:
从中央仓库下载的jar包,都会统一存放到本地仓库中。我们需要配置本地仓库的位置。
打开maven安装目录,打开conf目录下的setting.xml文件。
可以参照下图配置本地仓储位置。
你还可以在运行时指定本地仓库位置:
mvn clean install -Dmaven.repo.local=d:\yourpath
2.4、中央仓库配置
当构建一个Maven项目时,首先检查pom.xml文件以确定依赖包的下载位置,执行顺序如下:
1、从本地资源库中查找并获得依赖包,如果没有,执行第2步。 2、从Maven默认中央仓库中查找并获得依赖包(http://repo1.maven.org/maven2/),如果没有,执行第3步。 3、如果在pom.xml中定义了自定义的远程仓库,那么也会在这里的仓库中进行查找并获得依赖包,如果都没有找到,那么Maven就会抛出异常。
修改默认中央仓库地址
常用地址:
1、http://www.sonatype.org/nexus/ 私服nexus工具使用 2、http://mvnrepository.com/ (推荐) 3、http://repo1.maven.org/maven2 4、http://maven.aliyun.com/nexus/content/groups/public/ 阿里云 (强力推荐) 5、http://repo2.maven.org/maven2/ 私服nexus工具使用 6、http://uk.maven.org/maven2/ 7、http://repository.jboss.org/nexus/content/groups/public 8、http://maven.oschina.net/content/groups/public/ 9、http://mirrors.ibiblio.org/maven2/ 10、http://maven.antelink.com/content/repositories/central/ 11、http://nexus.openkoala.org/nexus/content/groups/Koala-release/ 12、http://maven.tmatesoft.com/content/groups/public/
完整配置文件:
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>H:\InstallFiles\javaKit\mavenReslocalRepository> <pluginGroups> pluginGroups> <proxies> proxies> <servers> <server> <id>adminid> <username>adminusername> <password>adminpassword> server> servers> <mirrors> <mirror> <id>nexus-aliyunid> <mirrorOf>*,!jeecg,!jeecg-snapshotsmirrorOf> <name>Nexus aliyunname> <url>http://maven.aliyun.com/nexus/content/groups/publicurl> mirror> mirrors> <profiles> <profile> <id>jdk1.7id> <activation> <activeByDefault>trueactiveByDefault> <jdk>1.7jdk> activation> <properties> <maven.compiler.source>1.7maven.compiler.source> <maven.compiler.target>1.7maven.compiler.target> <maven.compiler.compilerVersion>1.7maven.compiler.compilerVersion> properties> profile> profiles> settings>
2.5、命令行创建maven项目
方法一:
输入命令 mvn archetype:generate,按回车,根据提示输入参数,如果是第一次使用,需要下载插件,稍等几分钟即可。
切换目录,输入指令
选择骨架(模板):
输入座标:
确认后下载骨架,成功后的提示如下:
将项目转换成IDEA项目:
成功后可以看到增加了项目信息:
在IDEA中就可以直接打开项目了:
将项目打包
输入指令:mvn package
打包成功后:
方法二:
在命令中指定参数
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
执行结果:
在命令行输入:
mvn archetype:generate -DgroupId=com.zhangguo.mvntest04 -DartifactId=MvnTest04 -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
在命令行输入指令时请注意当前目录:
成功提示:
新建一个简单web项目
mvn archetype:generate -DgroupId=com.zhangguo -DartifactId=webappdemo -Dpackage=com.zhangguo.webappdemo -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0 -DinteractiveMode=No
如果下载骨架的速度太慢,可以用-DarchetypeCatalog=指定下载位置,如下所示:
mvn archetype:generate \ -DgroupId=com.mycom.helloworld \ -DartifactId=helloworld \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false \ -DarchetypeCatalog=http://maven.aliyun.com/nexus/content/groups/public/
更多解决方法:https://www.cnblogs.com/del88/p/6286887.html
2.6、Jetty运行Web项目
是一个开源的servlet容器,它为基于Java的web容器,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。
官网:http://www.eclipse.org/jetty/
jetty的特点:
//易用性 易用性是 Jetty 设计的基本原则,易用性主要体现在以下几个方面: 通过 XML 或者 API 来对Jetty进行配置;默认配置可以满足大部分的需求;将 Jetty 嵌入到应用程序当中只需要非常少的代码; //可扩展性 在使用了 Ajax 的 Web 2.0 的应用程序中,每个连接需要保持更长的时间,这样线程和内存的消耗量会急剧的增加。这就使得我们担心整个程序会因为单个组件陷入瓶颈而影响整个程序的性能。但是有了 Jetty: 即使在有大量服务请求的情况下,系统的性能也能保持在一个可以接受的状态。利用 Continuation 机制来处理大量的用户请求以及时间比较长的连接。 另外 Jetty 设计了非常良好的接口,因此在 Jetty 的某种实现无法满足用户的需要时,用户可以非常方便地对 Jetty 的某些实现进行修改,使得 Jetty 适用于特殊的应用程序的需求。 //易嵌入性 Jetty 设计之初就是作为一个优秀的组件来设计的,这也就意味着 Jetty 可以非常容易的嵌入到应用程序当中而不需要程序为了使用 Jetty 做修改。从某种程度上,你也可以把 Jetty 理解为一个嵌入式的Web服务器。 Jetty 可以作为嵌入式服务器使用,Jetty的运行速度较快,而且是轻量级的,可以在Java中可以从test case中控制其运行。从而可以使自动化测试不再依赖外部环境,顺利实现自动化测试。
maven项目直接在jetty中运行
2.6.1、修改pom,增加jetty插件:
<plugins> <plugin> <groupId>org.mortbay.jettygroupId> <artifactId>maven-jetty-pluginartifactId> <version>6.1.26version> <configuration> <webAppSourceDirectory>src/main/webappwebAppSourceDirectory> <scanIntervalSeconds>3scanIntervalSeconds> <contextPath>/jettycontextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>4000port> connector> connectors> configuration> plugin> plugins>
2.6.2、将项目部署到jetty中运行:
mvn jetty:run //运行项目于jetty上,
2.6.3、在浏览器中输入访问地址:
http://127.00.0.1:4000/jetty
结束运行使用ctrl+c
2.6.4、idea中使用maven方式使用jetty
配置好后可直接点击idea中右边的maven选项卡,在plugins下有jetty选项,展开随便点那个都可以启动jetty,启动好后就可以在浏览器中输入地址访问web应用了。
2.7、在tomcat中运行
添加插件:
<plugin> <groupId>org.codehaus.mojogroupId> <artifactId>tomcat-maven-pluginartifactId> <version>1.1version> <configuration> <path>/wppath> <port>8080port> <uriEncoding>UTF-8uriEncoding> <url>http://localhost:8080/manager/htmlurl> <server>tomcat6server> configuration> plugin>
执行命令:
tomcat:deploy --部署一个web war包 tomcat:reload --重新加载web war包 tomcat:start --启动tomcat tomcat:stop --停止tomcat tomcat:undeploy--停止一个war包 tomcat:run 启动嵌入式tomcat ,并运行当前项目
三、Maven概要
Maven 是一个Java项目管理工具,主要功能是统一开发规范与包的依赖管理。
3.1、Maven名词解释
1. POM(Project Object Model)项目对象模型
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。
POM 与 Java 代码实现了解耦,当需要升级版本时,只需要修改POM,而不需要更改Java代码,而在POM稳定后,日常的Java代码开发基本不涉及POM的修改。
2. 坐标
groupId , artifactId , version 三个元素是项目的坐标,唯一的标识这个项目。
groupId 项目所在组,一般是组织或公司
artifactId 是当前项目在组中的唯一ID;
version 表示版本,SNAPSHOT表示快照,表示此项目还在开发中,不稳定。
groupId 和实际项目不一定是一一对应的,maven 有模块的概念,例如 spring-core, spring-context...;groupId 也不应该只对应公司或组织名,建议具体到项目名,因为公司或者组织下有多个项目,而artifactId只能代表模块名。
<dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.11version> <scope>testscope> dependency>
3.依赖范围
1. compile : 编译,测试,运行都有效,默认的选择
2. test : 测试有效,例如junit
3. provided : 编译,测试有效,例如 servlet ,运行时容器会提供实现
4. runtime : 运行和测试有效,例如 jdbc,编译时只需相应的接口,测试和运行时才需要具体的实现
5. system : 编译,测试有效。使用此范围的依赖必须通过systemPath元素显式的指定依赖文件,因而
此类依赖是不通过Maven仓库解析的,一般适合于本机测试环境下,依赖本地起的服务。
构建
maven支持许多种的应用程序类型,对于每一种支持的应用程序类型都定义好了一组构建规则和工具集。
输出管理
maven可以管理项目构建的产物,并将其加入到用户库中。这个功能可以用于项目组和其他部门之间的交付行为
依赖关系
maven对依赖关系的特性进行细致的分析和划分,避免开发过程中的依赖混乱和相互污染行为
文档和构建结果
maven的site命令支持各种文档信息的发布,包括构建过程的各种输出,javadoc,产品文档等。
项目关系
一个大型的项目通常有几个小项目或者模块组成,用maven可以很方便地管理
移植性管理
maven可以针对不同的开发场景,输出不同种类的输出结果
- Project: 项目
- 任何你想 build 的事物,Maven都会把它们当作是一个 Project。
- 这些 Project 被定义为 POM(Project Object Model)。
- 一个 Project 可以依赖其他的project,一个 project 也可以有多个子project组成。
POM:文档对象模型
- POM(pom.xml) 是 Maven 的核心文件,它是指示 Maven 如何工作的元数据文件,类似 ant 的 build.xml 文件。
- pom.xml 文件应该位于每个 Project 的根目录。
- 顾名思义,这个应该是公司名或组织名。
- ArtifactId:项目名
- 构建出来的文件名,一般来说或,这个也是project名。
- Packaging:打包
- 项目打包的类型,可以是将jar、war、rar、ear、pom,默认是jar。
- Version:版本
- 项目的版本,项目的唯一标识由 groupId+artifactId+packaging+versionz 组成。
- Dependency: 依赖
- 为了能够 build 或运行,一个典型的java project会依赖其他的包,在Maven中,这些被依赖的包就被称为 dependency。
- Plug-in:插件
- Maven是有插件组织的,它的每一个功能都是由插件提供的,主要的插件是由 java 来写的,但是他也支持 beanshell 和 ant 脚本编写的插件。
- Repository:仓库
- 仓库用来存放artifact的,可以是本地仓库,也可以是远程仓库,Maven是由一个默认的仓库
- Snapshot:快照
- 工程中可以(也应该)有这样一个特殊的版本:这个版本可以告诉Maven,该工程正在处于开发阶段,会经常更新(但还为发布)。当其他工程依赖此类型的artifact时,Maven会在仓库中寻找该artifact的最新版本,并自动下载、使用该最新版本。
3.2、Maven的生命周期
maven把项目的构建划分为不同的生命周期(lifecycle)。粗略一点的话,它这个过程(phase)包括:编译、测试、打包、集成测试、验证、部署。maven中所有的执行动作(goal)都需要指明自己在这个过程中的执行位置,然后maven执行的时候,就依照过程的发展依次调用这些goal进行各种处理。
这个也是maven的一个基本调度机制。一般来说,位置稍后的过程都会依赖于之前的过程。当然,maven同样提供了配置文件,可以依照用户要求,跳过某些阶段。
三种生命周期
- Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
- Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
- Site Lifecycle 生成项目报告,站点,发布站点。
下面列出了default、clean和site生命周期的所有构建阶段,这些阶段按照指定的顺序执行。
clean生命周期
执行阶段 | 描述说明 |
---|---|
pre-clean | 在实际的项目清理之前执行所需的过程 |
clean | 删除前一个构建生成的所有文件 |
post-clean | 执行完成项目清理所需的过程 |
Default生命周期
执行阶段 | 描述说明 |
---|---|
validate | 验证项目是正确的,所有必要的信息都是可用的。 |
initialize | 初始化构建状态,例如设置属性或创建目录。 |
generate-sources | 生成包含在编译中的任何源代码。 |
process-sources | 处理源代码,例如过滤任何值。 |
generate-resources | 生成包含在包中的资源。 |
process-resources | 将资源复制并处理到目标目录中,准备打包。 |
compile | 编译项目的源代码。 |
process-classes | 从编译后生成生成的文件,例如在Java类上执行字节码增强。 |
generate-test-sources | 生成包含在编译中的任何测试源代码。 |
process-test-sources | 处理测试源代码,例如过滤任何值。 |
generate-test-resources | 为测试创建资源。 |
process-test-resources | 将资源复制并处理到测试目标目录中。 |
test-compile | 将测试源代码编译到测试目标目录 |
process-test-classes | 从测试编译后post-process生成文件,例如在Java类上执行字节码增强。对于Maven 2.0.5和以上。 |
test | 使用合适的单元测试框架运行测试。这些测试不应该要求打包或部署代码。 |
prepare-package | 在实际包装前执行必要的准备工作。这通常会导致包的一个未打包的、经过处理的版本。(Maven 2.1及以上) |
package | 使用已编译的代码,并将其打包成可部署格式,例如JAR。 |
pre-integration-test | 执行集成测试之前需要执行的操作。这可能涉及到设置所需的环境等问题。 |
integration-test | 在需要集成测试的环境中,处理并部署包。 |
post-integration-test | 执行集成测试后所需要的操作。这可能包括清理环境。 |
verify | 运行任何检查以验证包是否有效,并满足质量标准。 |
install | 将该包安装到本地存储库中,作为本地其他项目的依赖项。 |
deploy | 在集成或发布环境中完成,将最终包复制到远程存储库中,以便与其他开发人员和项目共享。 |
Site生命周期
执行阶段 | 描述说明 |
---|---|
pre-site | 在实际的项目站点生成之前执行过程 |
site | 生成项目的站点文档 |
post-site | 执行确定站点生成的过程,并为站点部署做好准备 |
site-deploy | 将生成的站点文档部署到指定的web服务器 |
注意:执行某个生命周期的某个阶段不会影响其它的生命周期!
如果要同时执行多个生命周期的阶段可在命令行输入多个命令,中间以空格隔开,例如: clean package 该命令执行clean生命周期的clean阶段和default生命周期的package阶段。
3.3、Maven标准工程结构
Maven的标准工程结构如下:
3.4、Maven的"约束优于配置"
所谓的"约束优于配置",在maven中并不是完全不可以修改的,他们只是一些配置的默认值而已。但是除非必要,并不需要去修改那些约定内容。maven默认的文件存放结构如1.3所示。
每一个阶段的任务都知道怎么正确完成自己的工作,比如compile任务就知道从src/main/java下编译所有的java文件,并把它的输出class文件存放到target/classes中。
对maven来说,采用"约定优于配置"的策略可以减少修改配置的工作量,也可以降低学习成本,更重要的是,给项目引入了统一的规范。
3.5、Maven的版本规范
maven有自己的版本规范,一般是如下定义
maven在版本管理时候可以使用几个特殊的字符串 SNAPSHOT,LATEST,RELEASE。比如"1.0-SNAPSHOT"。各个部分的含义和处理逻辑如下说明:
SNAPSHOT
这个版本一般用于开发过程中,表示不稳定的版本。
LATEST
指某个特定构件的最新发布,这个发布可能是一个发布版,也可能是一个snapshot版,具体看哪个时间最后。
RELEASE
是指仓库中最后的一个非快照版本
规范:
1、同一项目中所有模块版本保持一致
2、子模块统一继承父模块的版本
3、统一在顶层模块Pom的
4、开发测试阶段使用SNAPSHOT
5、生产发布使用RELEASE
6、新版本迭代只修改顶层POM中的版本
3.6、项目骨架Maven Archetype
什么是Maven Archetype? 简单的说就是一个Maven项目的基础模板,利用这个模板我们就可快速的建立一个新的该类型项目,同时也可以建立自己的项目骨架。
Maven所提供的archetype功能都是由插件Maven Archetype Plugin完成的
官网地址:http://maven.apache.org/archetype/maven-archetype-plugin/
主要命令:
- archetype:generate 从项目骨架创建一个maven项目,老版本里使用的是archetype:create
- archetype:create-from-project 根据一个项目创建项目骨架
使用archetype:generate创建项目
mvn archetype:generate命令参数解释
项目相关参数:
参数 |
含义 |
groupId |
当前应用程序隶属的Group的ID |
artifactId |
当前应用程序的ID |
package |
代码生成时使用的根包的名字,如果没有给出,默认使用archetypeGroupId |
原型有关参数表
参数 | 含义 |
archetypeGroupId |
原型(archetype)的Group ID |
archetypeArtifactId |
原型(archetype)ID |
archetypeVersion |
原型(archetype)版本 |
archetypeRepository |
包含原型(archetype)的资源库 |
archetypeCatalog |
archetype分类,这里按位置分类有: |
filter |
查找时过滤artifactId or groupId:artifactId |
package |
代码生成时使用的根包的名字,如果没有给出,默认使用archetypeGroupId |
命令示例:
新建一个简单web项目
mvn archetype:generate -DgroupId=com.domain
-DartifactId=webappdemo
-Dpackage=com.domain.webappdemo
-DarchetypeArtifactId=maven-archetype-webapp
-Dversion=1.0 -DinteractiveMode=No
新建一个struts2 web项目
mvn archetype:generate -B -DgroupId=com.mycompany.mysystem
-DartifactId=myWebApp
-DarchetypeGroupId=org.apache.struts
-DarchetypeArtifactId=struts2-archetype-convention
-DarchetypeVersion=
-DremoteRepositories=http://struts.apache.org
maven默认提供的archetype类型可以参考http://maven.apache.org/guides/introduction/introduction-to-archetypes.html
从一个已有项目生成一个archetype
mvn clean archetype:create-from-project -Darchetype.properties=./archetype.properties -Darchetype.filteredExtentions=java,xml,jsp,properties,sql
这里首先定义了一个archetype.properties文件在命令行被执行的目录,里面的内容是
tablePrefix是QucikStart项目里用到的,想在新项目中替换掉的内容。
-DfilteredExtentions,因为maven默认不会扫描sql文件,而这里是希望修改tablePrefix的.
properties参考http://maven.apache.org/archetype/maven-archetype-plugin/create-from-project-mojo.html
3.7、maven的项目对象模型
Maven包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
项目对象模型 (Project Object Model)
一个maven工程都有一个pom.xml文件,通过pom.xml文件定义项目的坐标、项目依赖、项目信息、插件目标等。
依赖管理系统(Dependency Management System)
通过maven的依赖管理对项目所依赖的jar 包进行统一管理。 比如:项目依赖junit4.9,通过在pom.xml中定义junit4.9的依赖即使用junit4.9,如下所示是junit4.9的依赖定义:
<dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.9version> <scope>testscope> dependency> dependencies>
一个项目生命周期(Project Lifecycle)
使用maven完成项目的构建,项目构建包括:清理、编译、测试、部署等过程,maven将这些过程规范为一个生命周期,如下所示是生命周期的各各阶段:
maven通过执行一些简单命令即可实现上边生命周期的各各过程,比如执行mvn compile执行编译、执行mvn clean执行清理。
一组标准集合
maven将整个项目管理过程定义一组标准,比如:通过maven构建工程有标准的目录结构,有标准的生命周期阶段、依赖管理有标准的坐标定义等。
插件(plugin)目标(goal)
maven 管理项目生命周期过程都是基于插件完成的。
Maven坐标是一组可以惟一标识构件的三元组值
- groupId,代表构件的实体或组织例如:org.inspur.loushang
- artifactId,实际的构件的名称,例如framework
- version,该构件件的版本号
-
packaging :定义Maven项目打包的方式,首先,打包方式通常与所生成构件的文件扩展名对应,如上例中的packaging为jar,最终的文件名为my-app-0.0.1-SNAPSHOT.jar。也可以打包成war, ear等。当不定义packaging的时候,Maven 会使用默认值jar
classifier: 该元素用来帮助定义构建输出的一些附件。附属构件与主构件对应,如上例中的主构件为my-app-0.0.1-SNAPSHOT.jar,该项目可能还会通过一些插件生成如my-app-0.0.1-SNAPSHOT-javadoc.jar,my-app-0.0.1-SNAPSHOT-sources.jar, 这样附属构件也就拥有了自己唯一的坐标
四、IDE中使用Maven(IDEA或Eclipse)
4.1、将现有项目转换成Maven项目
如果有一个非maven的项目想转换成maven管理的项目,只需如下操作即可:
在项目上右键,添加框架支持
选择maven与其它想添加的框架
选择允许自动导入
这样就成功转换成了一个maven项目
4.2、在IDEA中创建Maven项目
4.2.1、创建项目
4.1是一种创建maven项目的办法,但不推荐,因为没有使用统一的骨架,可以一开始就选择创建maven项目,步骤如下:
步骤一:首先先创建一个project,上次我说过了创建一个project就是一个工作空间,在这里就是创建一个maven的工作空间
步骤二:选择maven项目,指定骨架,这里选择的是一个webapp,当然webapp骨架有非常多,这里选择apache提供的
步骤三:填写项目的座标,公司编号(一般倒置域名),项目名称,版本:
步骤四:因为IDEA内置了Maven,可以选择默认内置的Maven;当然最好是选择自己安装并配置好的环境,让所有的IDE统一:
这里可以点绿色的小加号添加参数
步骤五:选择项目名称,位置,一般默认
点击Finish项目就创建完成了,如下图所示:
4.2.2、配置Tomcat
点击右上角下拉框,选择Edit Configurations,编辑配置
添加tomcat的配置
配置tocat服务器,命名,选择tomcat版本,等想配置的信息;最关键的是需要将项目部署出去,可以直接击fix
选择war explored,他们的区别
当然也可以手动选择要部署出去的项目,特别是有多个项目的情况
配置项目结构,特别是要注意依赖的包需要部署到WEB-INF的lib目录下
完成后可以启服务器,效果如下:
当然可以直接使用插件让项目部署到jetty中通过maven运行,不需tomcat。
4.2.3、war和war exploded的区别
是选择war还是war exploded 这里首先看一下他们两个的区别:
(1)war模式这种可以称之为是发布模式,看名字也知道,这是先打成war包,再发布;
(2)war exploded模式是直接把文件夹、jsp页面 、classes等等移到Tomcat 部署文件夹里面,进行加载部署。因此这种方式支持热部署,一般在开发的时候也是用这种方式。
(3)在平时开发的时候,使用热部署的话,应该对Tomcat进行相应的设置,这样的话修改的jsp界面什么的东西才可以及时的显示出来。
两种方式得部署方式是不一样的,在获取项目的路径的时候得到的结果是不一样的
String contextPath = request.getSession().getServletContext().getRealPath("/");
4.2.4、修改项目结构
maven有一个很重要的功能是规范项目,标准的项目结构如下所示:
但是你会发现默认创建的项并非是完整的,如写源代码的目录没有,添加方法如下
当前项目结构如下:
添加相应的目录,选择打开项目结构:
项目结构如下:
蓝色:源代码
绿色:测试
资源文件(配置信息)
测试资源文件
被排除的(打包里被忽视)
目标位置右键添加目录:
添加后的目录结构如下:
4.2.5、不能添加Servlet的解决方法
打开项目描述文件,指定源代码目录:
<sourceRoots> <root url="file://$MODULE_DIR$/src/main/java" /> sourceRoots>
修改方法:
这样就可以了:
如果没有添加tomcat的配置信息或没有servet的核心包也可能出现该问题,建议修改pom加上:
<dependency> <groupId>javax.servletgroupId> <artifactId>jstlartifactId> <version>1.2version> dependency> <dependency> <groupId>javax.servletgroupId> <artifactId>javax.servlet-apiartifactId> <version>3.0.1version> <scope>providedscope> dependency> <dependency> <groupId>javax.servlet.jspgroupId> <artifactId>jsp-apiartifactId> <version>2.1version> <scope>providedscope> dependency>
4.3、在Eclipse中创建Maven工程
Maven插件
在Eclipse中创建Maven工程,需要安装Maven插件。
一般较新版本的Eclipse都会带有Maven插件,如果你的Eclipse中已经有Maven插件,可以跳过这一步骤。
点击Help -> Eclipse Marketplace,搜索maven关键字,选择安装红框对应的Maven插件。
Maven环境配置
点击Window -> Preferences
如下图所示,配置settings.xml文件的位置
创建Maven工程
File -> New -> Maven Project -> Next,在接下来的窗口中会看到一大堆的项目模板,选择合适的模板。
接下来设置项目的参数,如下:
groupId是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
artifactId就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
点击Finish,Eclipse会创建一个Maven工程。
4.4、使用Maven进行构建
Eclipse中构建方式
在Elipse项目上右击 -> Run As 就能看到很多Maven操作。这些操作和maven命令是等效的。例如Maven clean,等同于mvn clean命令。
你也可以点击Maven build,输入组合命令,并保存下来。如下图:
Maven命令构建方式
当然,你也可以直接使用maven命令进行构建。
进入工程所在目录,输入maven命令就可以了。
如下图
4.5、创建Maven多模块项目
多模块项目不一定要使用Maven,普通项目也可以。
4.5.1、maven多模块优点
1、复用,划分出来的模块可以供其他项目使用。
2、固化,划分出来的某个模块可让专人开发,沉淀技术,分工协作。
3、优化依赖,每个模块有各自的pom。
4、节省时间,可在单个模块上进行build。
4.5.2、在IDEA中创建多模块项目
1、创建父模块
创建一个普通的Maven项目,不需要选择骨架(archetype)
指定座标
完成后一个普通的Maven项目就创建好了
2、创建子模块
子模块可以有多个,相互间可以依赖
在父模块上右键创建一个Module(模块)
utils
创建普通maven项目没有骨架
指定模块名称
完成后如下:
entities
创建成一个非maven项目(当然可以是maven的)
指定项目名称
完成后
webapp
创建一个基于骨架的maven WebApp项目
设置名称
选择maven home
完成后的结果
3、模块间依赖
方法一:依赖class
打开项目结构
添加模块依赖
指定要依赖的模块
依赖成功
指定输出
最终项目结构
结果
方法一:通过座标直接依赖jar
hr-ui模块的pom文件
<?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"> <parent> <artifactId>HRartifactId> <groupId>com.zhangguo.hrgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>hr-uiartifactId> <packaging>warpackaging> <name>hr-ui Maven Webappname> <url>http://www.example.comurl> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <maven.compiler.source>1.7maven.compiler.source> <maven.compiler.target>1.7maven.compiler.target> properties> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.11version> <scope>testscope> dependency>dependencies> <build> <finalName>hr-uifinalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-pluginartifactId> <version>3.0.0version> plugin> <plugin> <artifactId>maven-resources-pluginartifactId> <version>3.0.2version> plugin> <plugin> <artifactId>maven-compiler-pluginartifactId> <version>3.7.0version> plugin> <plugin> <artifactId>maven-surefire-pluginartifactId> <version>2.20.1version> plugin> <plugin> <artifactId>maven-war-pluginartifactId> <version>3.2.0version> plugin> <plugin> <artifactId>maven-install-pluginartifactId> <version>2.5.2version> plugin> <plugin> <artifactId>maven-deploy-pluginartifactId> <version>2.8.2version> plugin> plugins> pluginManagement> build> project> com.zhangguo.hr hr-core 1.0-SNAPSHOT
结果
4.6、多模块项目依赖管理与依赖继承
4.6.1、指定父模块与默认继承
dependencies即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承)
父模块的pom
<?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.0modelVersion> <groupId>com.zhangguo.maven03groupId> <artifactId>Maven03artifactId> <packaging>pompackaging> <version>1.0-SNAPSHOTversion> <modules> <module>Maven03-Daomodule> <module>Maven03-Servicemodule> modules> <properties> <junit.version>4.12junit.version> <spring.version>RELEASEspring.version> properties> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>${junit.version}version> <scope>testscope> dependency> dependencies> project>
子模块的pom
<?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"> <parent> <artifactId>Maven03artifactId> <groupId>com.zhangguo.maven03groupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>Maven03-DaoartifactId> <dependencies> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-aspectsartifactId> <version>${spring.version}version> dependency> dependencies> project>
RELEASE表示最新的发布版本,结果如下:
4.6.2、依赖管理
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显式的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
当我把父项目中的依赖放到依赖管理中的效果如下所示:
<?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.0modelVersion> <groupId>com.zhangguo.maven03groupId> <artifactId>Maven03artifactId> <packaging>pompackaging> <version>1.0-SNAPSHOTversion> <modules> <module>Maven03-Daomodule> <module>Maven03-Servicemodule> modules> <properties> <junit.version>4.12junit.version> <spring.version>RELEASEspring.version> properties> <dependencyManagement> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>${junit.version}version> <scope>testscope> dependency> dependencies> dependencyManagement> project>
结果
这里的父模块与子模块都并没有依赖junit了,这时的依赖只是用于管理,并没有真正依赖。
使用
在子类中,依赖配置较原来就简单了。可以在子类中只配置groupId和artifactId ,省去了version。因为完整的依赖声明已经包含在父POM中。 这样可以统一项目范围中依赖的版本,帮助降低依赖冲突的几率。
如果子模块不声明依赖的使用,即使该依赖已经在父POM的dependencyManangement中声明了,也不会产生任何实际的效果。
如果想要在某个模块中使用和另一个模块中完全一样的dependencyManagement配置,除了赋值和继承外,还可以使用import范围依赖将这一配置导入。
我们要达到的目的是:父模块作版本管理不实际依赖,子模块按需依赖。
父模块pom
<?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.0modelVersion> <groupId>com.zhangguo.maven03groupId> <artifactId>Maven03artifactId> <packaging>pompackaging> <version>1.0-SNAPSHOTversion> <modules> <module>Maven03-Daomodule> <module>Maven03-Servicemodule> modules> <properties> <junit.version>4.12junit.version> <spring.version>RELEASEspring.version> properties> <dependencyManagement> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>${junit.version}version> <scope>testscope> dependency> dependencies> dependencyManagement> project>
子模块pom:
<?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"> <parent> <artifactId>Maven03artifactId> <groupId>com.zhangguo.maven03groupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>Maven03-ServiceartifactId> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> dependency> dependencies> project>
结果:
这样做的好处:统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,才能保证测试的和发布的是相同的成果,因此,在顶层pom中定义共同的依赖关系。同时可以避免在每个使用的子项目中都声明一个版本号,这样想升级或者切换到另一个版本时,只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个版本号时,只需要在dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。
五、Maven中常用指令使用
5.1、在命令行中使用Maven指令
1、 显示版本信息
mvn -version
mvn -v
结果:
2、使用互动模式创建项目
mvn archetype:generate
结果:
具体请看本文前面:https://www.cnblogs.com/best/p/9622472.html#_lab2_1_4
3、使用非互动模式(指定参数创建项目)
普通项目骨架:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Web项目骨架:
mvn archetype:generate -DgroupId=com.zhangguo -DartifactId=webappdemo -Dpackage=com.zhangguo.webappdemo -DarchetypeArtifactId=maven-archetype-webapp -Dversion=1.0 -DinteractiveMode=No
具体请看本文前面:https://www.cnblogs.com/best/p/9622472.html#_lab2_1_4
4、将项目转化为idea项目
mvn idea:idea
结果:
5、将项目转化为Eclipse项目
mvn eclipse:eclipse
结果:
6、编译,将Java 源程序编译成 class 字节码文件
mvn compile
结果:
7、测试,并生成测试报告
mvn test
导入到idea中,添加测试用例
结果:
8、将以前编译得到的旧的 class 字节码文件删除
mvn clean
结果:
9、打包,动态 web工程打 war包,Java工程打 jar 包
mvn pakage
结果:
10、将项目生成 jar 包放在仓库中,以便别的模块调用,安装到本地
mvn install
结果:
在其它项目中依赖
11. 生成项目相关信息的网站:mvn site
12. 编译测试的内容:mvn test-compile
13. 只打jar包:mvn jar:jar
14. 只打war包:mvn war:war
15. 清除eclipse的一些系统设置:mvn eclipse:clean
16. 运行项目于jetty上:mvn jetty:run
17. 生成Wtp插件的Web项目:mvn -Dwtpversion=1.0 eclipse:eclipse
18. 清除Eclipse项目的配置信息(Web项目):mvn -Dwtpversion=1.0 eclipse:clean
19、部署项目:
mvn deploy:deploy-file -DgroupId=com -DartifactId=client -Dversion=0.1.0 -Dpackaging=jar -Dfile=d:\client-0.1.0.jar -DrepositoryId=maven-repository-inner -Durl=ftp://xxxxxxx/opt/maven/repository/
其它指令:
mvn -e 显示详细错误 信息. mvn validate 验证工程是否正确,所有需要的资源是否可用。 mvn test-compile 编译项目测试代码。 mvn integration-test 在集成测试可以运行的环境中处理和发布包。 mvn verify 运行任何检查,验证包是否有效且达到质量标准。 mvn generate-sources 产生应用需要的任何额外的源代码,如xdoclet。 mvn help:describe -Dplugin=help 使用 help 插件的 describe 目标来输出 Maven Help 插件的信息。 mvn help:describe -Dplugin=help -Dfull 使用Help 插件输出完整的带有参数的目标列 mvn help:describe -Dplugin=compiler -Dmojo=compile -Dfull 获取单个目标的信息,设置 mojo 参数和 plugin 参数。此命令列出了Compiler 插件的compile 目标的所有信息 mvn help:describe -Dplugin=exec -Dfull 列出所有 Maven Exec 插件可用的目标 mvn help:effective-pom 看这个“有效的 (effective)”POM,它暴露了 Maven的默认设置 mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook 创建Maven的普通java项目,在命令行使用Maven Archetype 插件 mvn exec:java -Dexec.mainClass=org.sonatype.mavenbook.weather.Main Exec 插件让我们能够在不往 classpath 载入适当的依赖的情况下,运行这个程序 mvn dependency:resolve 打印出已解决依赖的列表 mvn dependency:tree 打印整个依赖树 mvn install -X 想要查看完整的依赖踪迹,包含那些因为冲突或者其它原因而被拒绝引入的构件,打开 Maven 的调试标记运行 mvn install -Dmaven.test.skip=true 给任何目标添加maven.test.skip 属性就能跳过测试 mvn install assembly:assembly 构建装配Maven Assembly 插件是一个用来创建你应用程序特有分发包的插件 mvn jetty:run 调用 Jetty 插件的 Run 目标在 Jetty Servlet 容器中启动 web 应用 mvn compile 编译你的项目 mvn clean install 删除再编译 mvn hibernate3:hbm2ddl 使用 Hibernate3 插件构造数据库
5.2、常用Maven命令
生命周期 |
阶段描述 |
mvn validate |
验证项目是否正确,以及所有为了完整构建必要的信息是否可用 |
mvn generate-sources |
生成所有需要包含在编译过程中的源代码 |
mvn process-sources |
处理源代码,比如过滤一些值 |
mvn generate-resources |
生成所有需要包含在打包过程中的资源文件 |
mvn process-resources |
复制并处理资源文件至目标目录,准备打包 |
mvn compile |
编译项目的源代码 |
mvn process-classes |
后处理编译生成的文件,例如对Java类进行字节码增强(bytecode enhancement) |
mvn generate-test-sources |
生成所有包含在测试编译过程中的测试源码 |
mvn process-test-sources |
处理测试源码,比如过滤一些值 |
mvn generate-test-resources |
生成测试需要的资源文件 |
mvn process-test-resources |
复制并处理测试资源文件至测试目标目录 |
mvn test-compile |
编译测试源码至测试目标目录 |
mvn test |
使用合适的单元测试框架运行测试。这些测试应该不需要代码被打包或发布 |
mvn prepare-package |
在真正的打包之前,执行一些准备打包必要的操作。这通常会产生一个包的展开的处理过的版本(将会在Maven 2.1+中实现) |
mvn package |
将编译好的代码打包成可分发的格式,如JAR,WAR,或者EAR |
mvn pre-integration-test |
执行一些在集成测试运行之前需要的动作。如建立集成测试需要的环境 |
mvn integration-test |
如果有必要的话,处理包并发布至集成测试可以运行的环境 |
mvn post-integration-test |
执行一些在集成测试运行之后需要的动作。如清理集成测试环境。 |
mvn verify |
执行所有检查,验证包是有效的,符合质量规范 |
mvn install |
安装包至本地仓库,以备本地的其它项目作为依赖使用 |
mvn deploy |
复制最终的包至远程仓库,共享给其它开发人员和项目(通常和一次正式的发布相关) |
使用参数
-Dmaven.test.skip=true: 跳过单元测试(eg: mcn clean package -Dmaven.test.skip=true)
mvn archetype:create | 创建Maven项目 |
mvn compile | 编译源代码 |
mvn test | 运行应用程序中的单元测试 |
mvn install | 在本地Respository中安装jar |
mvn eclipse:eclipse | 生成eclipse项目文件 |
mvn jetty:run | 启动jetty服务 |
mvn clean | 清除项目目录中的生成结果 |
mvn site | 生成项目相关信息的网站 |
mvn package | 根据项目生成的jar |
5.3、在IDE(集成开发工具)中使用指令
5.3.1、工具栏介绍
图标1:重新导入所有的maven项目,刷新
图标2:重新生成所有源代码并更新文件夹
图标3:下载源码或文件
图标4:添加一个外部的Maven项目
图标5:执行选择的指令
图标6:执行自定义的指令
图标7:切换离线模式
图标8:切换成跳过测试模式
图标9:显示依赖结构图
图标10:折叠所有
图标11:Maven设置
5.3.2、快捷执行Maven命令
选择命令后右键run
创建命令,可反复使用并指定名称与参数
定义细节
执行
六、使用指导
6.1、如何添加外部依赖jar包
在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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0modelVersion> <groupId>com.zp.mavengroupId> <artifactId>MavenDemoartifactId> <version>0.0.1-SNAPSHOTversion> <packaging>jarpackaging> <name>MavenDemoname> <url>http://maven.apache.orgurl> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <junit.version>3.8.1junit.version> properties> <dependencies> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>${junit.version}version> <scope>testscope> dependency> <dependency> <groupId>log4jgroupId> <artifactId>log4jartifactId> <version>1.2.12version> <scope>compilescope> dependency> dependencies> project>
groupId:项目组织唯一的标识符,实际对应JAVA的包的结构。
artifactId:项目唯一的标识符,实际对应项目的名称,就是项目根目录的名称。
version:jar包的版本号。可以直接填版本数字,也可以在properties标签中设置属性值。
scope:jar包的作用范围。可以填写compile、runtime、test、system和provided。用来在编译、测试等场景下选择对应的classpath
6.2、如何寻找jar包
可以在http://mvnrepository.com/站点搜寻你想要的jar包版本
6.3、如何使用Maven插件(Plugin)
要添加Maven插件,可以在pom.xml文件中添加<plugin>标签。
<plugins> <plugin> <groupId>org.mortbay.jettygroupId> <artifactId>maven-jetty-pluginartifactId> <version>6.1.26version> <configuration> <webAppSourceDirectory>src/main/webappwebAppSourceDirectory> <scanIntervalSeconds>3scanIntervalSeconds> <contextPath>/jettycontextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>4000port> connector> connectors> configuration> plugin> plugins>
6.4、如何一次编译多个工程
在Maven中,允许一个Maven Project中有多个Maven Module
1.创建maven父工程步骤:new-->other-->选择maven project-->next-->勾选create a simple project-->next-->填写Group Id、Artifact Id、Version --> packaging选择pom-->finish。
2.创建maven子工程步骤:选中刚才创建的父工程右键-->new-->other-->选择maven module-->next-->勾选create a simple project-->填写module name(其实就是artifact id)-->next-->GAV继承父工程-->packaging选择你需要的-->finish。
3.完成,刷新父工程;如有多个子工程,继续按照第二步骤创建。
这时打开XXX中的pom.xml可以看到其中有以下标签
<modules> <module>xxx1module> modules>
选择编译XXX时,会依次对它的所有Module执行相同操作。
6.5、常用Maven插件
Maven 是一个执行插件的框架,每一个任务实际上是由插件完成的。Maven 提供以下两种类型插件:构建插件,在生成过程中执行,并在 pom.xml 中的
maven-antrun-plugin
http://maven.apache.org/plugins/maven-antrun-plugin/
maven-antrun-plugin能让用户在Maven项目中运行Ant任务。用户可以直接在该插件的配置以Ant的方式编写Target,然后交给该插件的run目标去执行。在一些由Ant往Maven迁移的项目中,该插件尤其有用。此外当你发现需要编写一些自定义程度很高的任务,同时又觉得Maven不够灵活时,也可以以Ant的方式实现之。maven-antrun-plugin的run目标通常与生命周期绑定运行。
maven-archetype-plugin
http://maven.apache.org/archetype/maven-archetype-plugin/
Archtype指项目的骨架,Maven初学者最开始执行的Maven命令可能就是mvn archetype:generate,这实际上就是让maven-archetype-plugin生成一个很简单的项目骨架,帮助开发者快速上手。可能也有人看到一些文档写了mvn archetype:create,但实际上create目标已经被弃用了,取而代之的是generate目标,该目标使用交互式的方式提示用户输入必要的信息以创建项目,体验更好。 maven-archetype-plugin还有一些其他目标帮助用户自己定义项目原型,例如你由一个产品需要交付给很多客户进行二次开发,你就可以为他们提供一个Archtype,帮助他们快速上手。
maven-assembly-plugin
http://maven.apache.org/plugins/maven-assembly-plugin/
maven-assembly-plugin的用途是制作项目分发包,该分发包可能包含了项目的可执行文件、源代码、readme、平台脚本等等。 maven-assembly-plugin支持各种主流的格式如zip、tar.gz、jar和war等,具体打包哪些文件是高度可控的,例如用户可以按文件级别的粒度、文件集级别的粒度、模块级别的粒度、以及依赖级别的粒度控制打包,此外,包含和排除配置也是支持的。maven-assembly- plugin要求用户使用一个名为assembly.xml的元数据文件来表述打包,它的single目标可以直接在命令行调用,也可以被绑定至生命周期。
maven-dependency-plugin
http://maven.apache.org/plugins/maven-dependency-plugin/
maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列表,dependency:tree能进一步的描绘项目依赖树,dependency:analyze可以告诉你项目依赖潜在的问题,如果你有直接使用到的却未声明的依赖,该目标就会发出警告。maven-dependency-plugin还有很多目标帮助你操作依赖文件,例如dependency:copy-dependencies能将项目依赖从本地Maven仓库复制到某个特定的文件夹下面。
maven-enforcer-plugin
http://maven.apache.org/plugins/maven-enforcer-plugin/
在一个稍大一点的组织或团队中,你无法保证所有成员都熟悉Maven,那他们做一些比较愚蠢的事情就会变得很正常,例如给项目引入了外部的 SNAPSHOT依赖而导致构建不稳定,使用了一个与大家不一致的Maven版本而经常抱怨构建出现诡异问题。maven-enforcer- plugin能够帮助你避免之类问题,它允许你创建一系列规则强制大家遵守,包括设定Java版本、设定Maven版本、禁止某些依赖、禁止 SNAPSHOT依赖。只要在一个父POM配置规则,然后让大家继承,当规则遭到破坏的时候,Maven就会报错。除了标准的规则之外,你还可以扩展该插件,编写自己的规则。maven-enforcer-plugin的enforce目标负责检查规则,它默认绑定到生命周期的validate阶段。
maven-help-plugin
http://maven.apache.org/plugins/maven-help-plugin/
maven-help-plugin是一个小巧的辅助工具,最简单的help:system可以打印所有可用的环境变量和Java系统属性。help:effective-pom和help:effective-settings最为有用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了所有父POM(包括Super POM)后的XML,当你不确定POM的某些信息从何而来时,就可以查看有效POM。有效settings同理,特别是当你发现自己配置的 settings.xml没有生效时,就可以用help:effective-settings来验证。此外,maven-help-plugin的describe目标可以帮助你描述任何一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的Profile。
maven-release-plugin
http://maven.apache.org/plugins/maven-release-plugin/
maven-release-plugin的用途是帮助自动化项目版本发布,它依赖于POM中的SCM信息。release:prepare用来准备版本发布,具体的工作包括检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本至RELEASE版本、为项目打标签等等。release:perform则是签出标签中的RELEASE源码,构建并发布。版本发布是非常琐碎的工作,它涉及了各种检查,而且由于该工作仅仅是偶尔需要,因此手动操作很容易遗漏一些细节,maven-release-plugin让该工作变得非常快速简便,不易出错。maven-release-plugin的各种目标通常直接在命令行调用,因为版本发布显然不是日常构建生命周期的一部分。
maven-resources-plugin
http://maven.apache.org/plugins/maven-resources-plugin/
为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources,很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。此外,资源文件过滤也是Maven的一大特性,你可以在资源文件中使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就可以针对不同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。
maven-surefire-plugin
http://maven.apache.org/plugins/maven-surefire-plugin/
可能是由于历史的原因,Maven 2/3中用于执行测试的插件不是maven-test-plugin,而是maven-surefire-plugin。其实大部分时间内,只要你的测试类遵循通用的命令约定(以Test结尾、以TestCase结尾、或者以Test开头),就几乎不用知晓该插件的存在。然而在当你想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候,了解maven-surefire-plugin的一些配置选项就很有用了。例如 mvn test -Dtest=FooTest 这样一条命令的效果是仅运行FooTest测试类,这是通过控制maven-surefire-plugin的test参数实现的。
build-helper-maven-plugin
http://mojo.codehaus.org/build-helper-maven-plugin/
Maven默认只允许指定一个主Java代码目录和一个测试Java代码目录,虽然这其实是个应当尽量遵守的约定,但偶尔你还是会希望能够指定多个源码目录(例如为了应对遗留项目),build-helper-maven-plugin的add-source目标就是服务于这个目的,通常它被绑定到默认生命周期的generate-sources阶段以添加额外的源码目录。需要强调的是,这种做法还是不推荐的,因为它破坏了 Maven的约定,而且可能会遇到其他严格遵守约定的插件工具无法正确识别额外的源码目录。
build-helper-maven-plugin的另一个非常有用的目标是attach-artifact,使用该目标你可以以classifier的形式选取部分项目文件生成附属构件,并同时install到本地仓库,也可以deploy到远程仓库。
exec-maven-plugin
http://mojo.codehaus.org/exec-maven-plugin/
exec-maven-plugin很好理解,顾名思义,它能让你运行任何本地的系统程序,在某些特定情况下,运行一个Maven外部的程序可能就是最简单的问题解决方案,这就是exec:exec的用途,当然,该插件还允许你配置相关的程序运行参数。除了exec目标之外,exec-maven-plugin还提供了一个java目标,该目标要求你提供一个mainClass参数,然后它能够利用当前项目的依赖作为classpath,在同一个JVM中运行该mainClass。有时候,为了简单的演示一个命令行Java程序,你可以在POM中配置好exec-maven-plugin的相关运行参数,然后直接在命令运行mvn exec:java 以查看运行效果。
jetty-maven-plugin
http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin
在进行Web开发的时候,打开浏览器对应用进行手动的测试几乎是无法避免的,这种测试方法通常就是将项目打包成war文件,然后部署到Web容器中,再启动容器进行验证,这显然十分耗时。为了帮助开发者节省时间,jetty-maven-plugin应运而生,它完全兼容 Maven项目的目录结构,能够周期性地检查源文件,一旦发现变更后自动更新到内置的Jetty Web容器中。做一些基本配置后(例如Web应用的contextPath和自动扫描变更的时间间隔),你只要执行 mvn jetty:run ,然后在IDE中修改代码,代码经IDE自动编译后产生变更,再由jetty-maven-plugin侦测到后更新至Jetty容器,这时你就可以直接测试Web页面了。需要注意的是,jetty-maven-plugin并不是宿主于Apache或Codehaus的官方插件,因此使用的时候需要额外的配置settings.xml的pluginGroups元素,将org.mortbay.jetty这个pluginGroup加入。
versions-maven-plugin
http://mojo.codehaus.org/versions-maven-plugin/
很多Maven用户遇到过这样一个问题,当项目包含大量模块的时候,为他们集体更新版本就变成一件烦人的事情,到底有没有自动化工具能帮助完成这件事情呢?(当然你可以使用sed之类的文本操作工具,不过不在本文讨论范围)答案是肯定的,versions-maven- plugin提供了很多目标帮助你管理Maven项目的各种版本信息。例如最常用的,命令 mvn versions:set -DnewVersion=1.1-SNAPSHOT 就能帮助你把所有模块的版本更新到1.1-SNAPSHOT。该插件还提供了其他一些很有用的目标,display-dependency- updates能告诉你项目依赖有哪些可用的更新;类似的display-plugin-updates能告诉你可用的插件更新;然后use- latest-versions能自动帮你将所有依赖升级到最新版本。最后,如果你对所做的更改满意,则可以使用 mvn versions:commit 提交,不满意的话也可以使用 mvn versions:revert 进行撤销。
更多详情请参考https://maven.apache.org/plugins/
七、常见问题
7.1、dependencies和dependencyManagement,plugins和pluginManagement的区别?
dependencyManagement是表示依赖jar包的声明,即你在项目中的dependencyManagement下声明了依赖,maven不会加载该依赖,dependencyManagement声明可以被继承。
dependencyManagement的一个使用案例是当有父子项目的时候,父项目中可以利用dependencyManagement声明子项目中需要用到的依赖jar包,之后,当某个或者某几个子项目需要加载该插件的时候,就可以在子项目中dependencies节点只配置 groupId 和 artifactId就可以完成插件的引用。
dependencyManagement主要是为了统一管理插件,确保所有子项目使用的插件版本保持一致,类似的还是plugins和pluginManagement。
7.2、不能添加Servlet
1、修改项目文件.iml,添加如下内容
<sourceRoots> <root url="file://$MODULE_DIR$/src/main/java" /> sourceRoots>
2、添加Servlet-api核心包
八、综合示例
这里使用Maven+多模块项目+IDEA+Git+MySQL完成一个简单的综合示例,完成一个TaskList项目,实现任务管理功能。
8.1、创建项目
8.2、创建数据数据库与表
创建表
添加数据
8.3、编写实体模块
8.4、编写工具模块
8.5、数据访问模块
添加依赖
修改Pom
<?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"> <parent> <artifactId>TaskListartifactId> <groupId>com.zhangguo.tasklistgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>taskList-daoartifactId> <dependencies> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-entitiesartifactId> <version>1.0-SNAPSHOTversion> dependency> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-utilsartifactId> <version>1.0-SNAPSHOTversion> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.10version> dependency> dependencies> project>
编写任务表的数据访问类
package com.zhangguo.tasklist.dao; import com.zhangguo.tasklist.entities.Task; import com.zhangguo.tasklist.utils.JDBCUtils; import java.util.List; public class TaskDao { /**获得所有任务清单*/ public ListgetAllTasks(){ return JDBCUtils.queryForList("select id,title,status from task",Task.class); } }
8.6、单元测试
8.7、服务模块
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"> <parent> <artifactId>TaskListartifactId> <groupId>com.zhangguo.tasklistgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>taskList-servicesartifactId> <dependencies> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-daoartifactId> <version>1.0-SNAPSHOTversion> dependency> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-entitiesartifactId> <version>1.0-SNAPSHOTversion> dependency> dependencies> project>
代码:
8.8、Web项目
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"> <parent> <artifactId>TaskListartifactId> <groupId>com.zhangguo.tasklistgroupId> <version>1.0-SNAPSHOTversion> parent> <modelVersion>4.0.0modelVersion> <artifactId>taskList-uiartifactId> <packaging>warpackaging> <name>taskList-ui Maven Webappname> <url>http://www.example.comurl> <properties> <project.build.sourceEncoding>UTF-8project.build.sourceEncoding> <maven.compiler.source>1.7maven.compiler.source> <maven.compiler.target>1.7maven.compiler.target> properties> <dependencies> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-utilsartifactId> <version>1.0-SNAPSHOTversion> dependency> <dependency> <groupId>com.zhangguo.tasklistgroupId> <artifactId>taskList-servicesartifactId> <version>1.0-SNAPSHOTversion> dependency> <dependency> <groupId>javax.servletgroupId> <artifactId>jstlartifactId> <version>1.2version> dependency> <dependency> <groupId>javax.servletgroupId> <artifactId>javax.servlet-apiartifactId> <version>3.0.1version> <scope>providedscope> dependency> <dependency> <groupId>javax.servlet.jspgroupId> <artifactId>jsp-apiartifactId> <version>2.1version> <scope>providedscope> dependency> dependencies> <build> <finalName>taskList-uifinalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-pluginartifactId> <version>3.0.0version> plugin> <plugin> <artifactId>maven-resources-pluginartifactId> <version>3.0.2version> plugin> <plugin> <artifactId>maven-compiler-pluginartifactId> <version>3.7.0version> plugin> <plugin> <artifactId>maven-surefire-pluginartifactId> <version>2.20.1version> plugin> <plugin> <artifactId>maven-war-pluginartifactId> <version>3.2.0version> plugin> <plugin> <artifactId>maven-install-pluginartifactId> <version>2.5.2version> plugin> <plugin> <artifactId>maven-deploy-pluginartifactId> <version>2.8.2version> plugin> plugins> pluginManagement> build> project>
Servlet:
package com.zhangguo.tasklist.ui.controllers; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import com.zhangguo.tasklist.services.ITaskService; import com.zhangguo.tasklist.services.TaskService; import com.zhangguo.tasklist.utils.R; @WebServlet("/TaskServlet") public class TaskServlet extends HttpServlet { ITaskService service=new TaskService(); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码 response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); request.setCharacterEncoding("utf-8"); String json=R.ok(service.queryAllTask()).Json(); response.getWriter().write(json); } }
项目结构:
目录结构:
运行结果:
8.9、Git同步到远程仓库
Git位置:https://git.coding.net/zhangguo5/TaskListSys.git
九、视频
https://www.bilibili.com/video/av31623453/
十、作业
1、请下载、安装配置好maven,在控制台输出版本号
2、请配置本地仓库路径与远程仓库的镜像
3、请在命令行模式下新建一个maven普通项目,导入到IDEA中,运行,打包输出结果
4、请在命令行模式下新建一个webapp项目,使用jetty运行,要求输出服务器时间,注意添加相应的javaEE依赖
参数pom
"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"> 4.0.0 com.zhangguo ssm 0.0.1 war UTF-8 4.3.0.RELEASE org.springframework spring-context ${spring.version} org.springframework spring-webmvc ${spring.version} org.springframework spring-context-support ${spring.version} org.aspectj aspectjweaver 1.8.9 org.mybatis mybatis-spring 1.3.0 org.springframework spring-jdbc ${spring.version} mysql mysql-connector-java 5.1.38 org.apache.logging.log4j log4j-core 2.6.1 org.mybatis mybatis 3.4.1 junit junit 4.10 c3p0 c3p0 0.9.1.2 javax.servlet jstl 1.2 javax.servlet javax.servlet-api 3.0.1 provided javax.servlet.jsp jsp-api 2.1 provided com.fasterxml.jackson.core jackson-core 2.5.2 com.fasterxml.jackson.core jackson-databind 2.5.2 org.hibernate hibernate-validator 5.2.2.Final commons-io commons-io 2.4 commons-fileupload commons-fileupload 1.3.1 org.freemarker freemarker 2.3.23
5、个人项目功能需求列表,下周五前提交
下载地址
6、将考试的两个项目修改成Maven项目,管理所有的包,测试运行通过
7、预习Git,安装好环境,到coding.net上注册一个帐号
8、完成任务指导手册中所有的理论题
9、将考试中的两个项目合并成一个多模块的Maven项目,两个ui层,一个使用jstl一个使用纯HTML
10、熟练使用maven中常用的指令,自定义一个Maven项目,编写测试用例,部署到本地仓库并在其它项目中引用
2018-09-21
11、根据任务列表示例完成一个汽车管理系统CarSystem(车名,颜色,速度,车牌,详细描述),实现增加、修改、删除、查询功能;最终完成的项目要求同步到远程仓库;
12、完成Git中协同开发的8个场景,2人以上交叉扮演组长与组员
13、完成任务指导手册中的理论题
14、完成个人项目的功能需求,提交给学习委员
15、完成个人项目的数据库设计,提交给组长,组长给学习委员
16、补考的同学请下周二上课前完成试题,并通过学习委员的检查