Maven学习笔记
基本概念
概述
Maven是Apache软件基金会组织维护的一款自动化构建工具,专注服务于Java平台的项目构建和依赖管理。是目前最流行的自动化构建工具,对于生产环境下多框架、多模块整合开发有重要作用,是一款在大型项目开发过程中不可或缺的重要工具。类似自动化构建工具还有:Ant、Maven、Gradle。
作用
- Maven可以整合多个项目之间的引用关系,我们可以根据业务和分层需要任意拆分一个项目;
- Maven提供规范的管理各个常用jar包及其各个版本,并且可以自动下载和引入项目中;
- Maven可以根据指定版本自动解决jar包版本兼容问题;
- Maven可以把jar包所依赖的其它jar包自动下载并引入项目。
功能/核心概念
概念
构建(build),是面向过程的(从开始到结尾的多个步骤),涉及到多个环节的协同工作。
构建过程的几个主要环节:
- 清理:删除以前的编译结果,为重新编译做好准备。
- 编译:将Java源程序编译为字节码文件。
- 测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
- 报告:在每一次测试后以标准的格式记录和展示测试结果。
- 打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java工程对应jar包,Web
工程对应war包。 - 安装:在Maven环境下特指将打包的结果——jar包或war包安装到本地仓库中。
- 部署:将打包的结果部署到远程仓库或将war包部署到服务器上运行。
核心概念
Maven能够实现自动化构建是和它的内部原理分不开的,这里可以从Maven的九个核心概念入手,
看看Maven是如何实现自动化构建的:
- POM
- 约定的目录结构
- 坐标
- 依赖管理
- 仓库管理
- 生命周期
- 插件和目标
- 继承
- 聚合
安装Maven
- 确保安装了Java环境:maven本身就是java写的,所以要求必须安装JDK。
- 查看Java环境变量:echo%JAVA_HOME%
- 下载并解压maven安装程序:http://maven.apache.org/download.cgi
- 配置Maven的环境变量:MAVEN_HOME=Maven路径或M2_HOME=路径(路径须在Maven安装文件bin的父文件下)
- 配置path变量:path=%MAVEN_HOME%/bin;或者%M2_HOME%/bin
- 验证是否安装成功:
- mvn–v(显示Maven版本号)
目录结构
Maven目录结构:
Hello
|—src()
|—|—main
|—|—|—java
|—|—|—resources
|—|—test
|—|—|—java
|—|—|—resources
|—pom.xml
说明:
Hello:根目录,也就是工程名。
src:源代码。
main:主程序。
java:主程序的java源码。
resources:主程序的配置文件。
test:测试程序。
java:测试程序的Java源码。
resources:测试程序的配置文件。
pom.xml:Maven工程的核心配置文件。
Maven的pom.xml记录的关于构建项目的各个方面的设置,maven从pom.xml文件开始,按照助约定的
工程目录编译,测试,打包,部署,发布项目。
POM文件
POM即ProjectObjectModel项目对象模型。Maven把一个项目的结构和内容抽象成一个模型,在xml文件中进行声明,以方便进行构建和描述,pom.xml是Maven的灵魂。所以,Maven环境搭建好之后,所有的学习和操作都是关于pom.xml的。
命令 | 说明 |
---|---|
modelVersion | Maven模型的版本,对于Maven2和Maven3来说,它只能是4.0.0 |
groupId | 组织id,一般是公司域名的倒写。格式可以为:1.域名倒写。例如com.baidu2.域名倒写+项目名。例如com.baidu.appolo |
artifactId | 项目名称,也是模块名称,对应groupId中项目中的子项目。 |
version | 项目的版本号。如果项目还在开发中,是不稳定版本,通常在版本后带-SNAPSHOTversion使用三位数字标识,例如1.1.0 |
packaging | 项目打包的类型,可以是jar、war、rar、ear、pom,默认是jar |
dependencies/dependency(依赖) | Maven的一个重要作用就是管理jar包,为了一个项目可以构建或运行,项目中不可避免的,会依赖很多其他的jar包,在Maven中,这些jar就被称为依赖,使用标签dependency来配置。而这种依赖的配置正是通过坐标来定位的,由此可以看出,maven把所有的jar包也都视为项目存在了。 |
properties(配置属性) | properties是用来定义一些配置属性的,例如project.build.sourceEncoding(项目构建源码编码方式),可以设置为UTF-8,防止中文乱码,也可定义相关构建版本号,便于日后统一升级。 |
build(构建) | build表示与构建相关的配置,例如设置编译插件的jdk版本。 |
parent(继承) | 在Maven中,如果多个模块都需要声明相同的配置,例如:groupId、version、有相同的依赖、或者相同的组件配置等,也有类似Java的继承机制,用parent声明要继承的父工程的pom配置。 |
modules(聚合) | 在Maven的多模块开发中,为了统一构建整个项目的所有模块,可以提供一个额外的模块,该模块打包方式为pom,并且在其中使用modules聚合的其它模块,这样通过本模块就可以一键自动识别模块间的依赖关系来构建所有模块,叫Maven的聚合。 |
仓库
概述
现在我们对maven工程有一个大概的认识了,那现在思考一个问题,maven怎么就这么神奇,我们写完的工程交给他之后,他就能够自动帮我们管理,我们依赖的jar包它从哪儿获取呢?有同学说已经安装了,在它的安装包里啊,大家可以看一下maven下载下来才几M,我们需要的jar包有时候都几百兆甚至几个G,它从哪儿弄去呢?其实,maven有仓库的概念。在Maven中,任何一个依赖、插件或者项目构建的输出,都可以称之为构件。Maven核心程序仅仅定义了自动化构建项目的生命周期,但具体的构建工作是由特定的构件完成的。而且为了提高构建的效率和构件复用,maven把所有的构件统一存储在某一个位置,这个位置就叫做仓库。
存放类型
Maven仓库存放的为:
- Maven的插件,插件也是一些jar,这些jar可以完成一定的功能。
- 我们自己开发项目的模块。
- 第三方框架或工具的jar包。
仓库的类别
根据仓库存储的位置,把仓库分为本地仓库和远程仓库。
本地仓库
存在于当前电脑上,默认存放在.m2\repository中,为本机上所有的Maven工程服务。你也可以通过Maven的配置文件Maven_home/conf/settings.xml中修改本地仓库所在的目录。是用户的主目录,windows系统中是c:/user/登录系统的用户名。
私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用。当Maven需要下载构件的时候,它从私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,缓存在私服上之后,再为Maven的下载请求提供服务。我们还可以把一些无法从外部仓库下载到的构件上传到私服上。
远程仓库
远程仓库又名(镜像仓库)就是中央仓库的备份,在各大洲和重要的城市都有镜像源,负责帮中央仓库减轻负担。
中央仓库
中央仓库,包含了绝大多数流行的开源Java构件,以及源码、作者信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载得到。
中央仓库地址:https://mvnrepository.com/
分类说明
- 本地仓库:本机当前电脑上的资源存储位置,为本机上所有Maven工程提供服务。
- 远程仓库:不在本机上,通过网络才能使用。多电脑共享使用的。
- 中央仓库:通过Internet访问,为全世界所有Maven工程服务。最权威的。
- 中央仓库的镜像:架设在不同位置,欧洲,美洲,亚洲等每个洲都有若干的服务器,为中央仓库分担流量。减轻中央仓库的访问,下载的压力。所在洲的用户首先访问的是本洲的镜像服务器。
- 私服:在局域网环境中部署的服务器,为当前局域网范围内的所有Maven工程服务。公司中常常使用这种方式。
Maven对仓库的使用:
在Maven构建项目的过程中如果需要某些插件,首先会到Maven的本地仓库中查找,如果找到则可以直接使用;如果找不到,它会自动连接外网,到远程中央仓库中查找;如果远程仓库中能找到,则先把所需要的插件下载到本地仓库,然后再使用,并且下次再用到相同的插件也可以直接使用本地仓库的;如果没有外网或者远程仓库中也找不到,则构建失败。
生命周期
对项目的构建是建立在生命周期模型上的,它明确定义项目生命周期各个阶段,并且对于每一个阶段提供相对应的命令,对开发者而言仅仅需要掌握一小堆的命令就可以完成项目各个阶段的构建工作。构建项目时按照生命周期顺序构建,每一个阶段都有特定的插件来完成。不论现在要执行生命周期中的哪个阶段,都是从这个生命周期的最初阶段开始的。对于我们程序员而言,无论我们要进行哪个阶段的构建,直接执行相应的命令即可,无需担心它前边阶段是否构建,Maven都会自动构建。这也就是Maven这种自动化构建工具给我们带来的好处。
Maven常用命令
Maven提供一个项目构建的模型,把编译、测试、打包、部署等都对应成一个个的生命周期阶段,并对每一个阶段提供相应的命令,程序员只需要掌握一小堆命令,就可以完成项目的构建过程。
命令 | 说明 |
---|---|
mvn clean | 清理(会删除原来编译和测试的目录,即target目录,但是已经install到仓库里的包不会删除) |
mvn compile | 编译主程序(会在当前目录下生成一个target,里边存放编译主程序之后生成的字节码文件) |
mvn test-compile | 编译测试程序(会在当前目录下生成一个target,里边存放编译测试程序之后生成的字节码文件) |
mvn test | 测试(会生成一个目录surefire-reports,保存测试结果) |
mvn package | 打包主程序(会编译、编译测试、测试、并且按照pom.xml配置把主程序打包生成jar包或者war包) |
mvn install | 安装主程序(会把本工程打包,并且按照本工程的坐标保存到本地仓库中) |
mvn deploy | 部署主程序(会把本工程打包,按照本工程的坐标保存到本地库中,并且还会保存到私服仓库中。还会自动把项目部署到web容器中)。 |
注意:执行以上命令必须在命令行进入pom.xml所在目录。
插件
maven过程构建周期,由maven的插件plugin来执行完成(官网插件说明:http://maven.apache.org/plugins/)。
在项目根目录下执行:mvncleaninstall
常用插件说明:
插件 | 说明 |
---|---|
maven-clean-plugin | clean阶段是独立的一个阶段,负责清除工程目前下的target目录。 |
maven-resources-plugin | resource插件负责把项目需要的配置文件拷贝到指定的目当,默认是拷贝src\main\resources目录下的件到classes目录下。 |
maven-compiler-plugin | compile插件执行时先调用resouces插件,功能就是把src\mainjava源码编译成字节码生成class文件,并把编译好的class文件输出到target\classes目录下。 |
test | 单元测试所用的compile和resources插件和主代码是相同的,但执行的目标不行,目标testCompile和testResources是把src\test\java下的代码编译成字节码输出到target\test-classes,同时把src\test\resources下的配置文件拷贝到target\test-classes。 |
maven-jar-plugin | jar插件负责把class文件、配置文件打成一个jar(war或其它格式)包。 |
maven-install-plugin | install负责发布插件的功能就是把构建好的artifact部署到本地仓库,还有一个deploy插件是将构建好的artifact部署到远程仓库。 |
坐标(gav)
Maven把任何一个插件都作为仓库中的一个项目进行管理,用一组(三个)向量组成的坐标来表示。坐标在仓库中可以唯一定位一个Maven项目。
坐标名 | 说明 |
---|---|
groupId | 组织名,通常是公司或组织域名倒序+项目名。 |
artifactId | 模块名,通常是工程名/项目名。 |
version | 版本号。 |
注意:项目在仓库中的位置是由坐标来决定的:groupId、artifactId和version决定项目在仓库中的路径,artifactId和version决定jar包的名称。
依赖(dependency)
一个Maven项目正常运行需要其它项目的支持,Maven会根据坐标自动到本地仓库中进行查找。对于程序员自己的Maven项目需要进行安装,才能保存到仓库中。不用Maven时候依赖需要去各个地方下载、导入,使用Maven直接将所需要的依赖在POM中写入,所需依赖的坐标Maven会自动下载导入相关依赖。
语法
<!--log4j 日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit 单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
依赖管理范围
依赖的范围: compile、 test、 provided,默认采用 compile。
compile | test | provided | |
---|---|---|---|
对主程序是否有效 | 是 | 否 | 是 |
对测试程序是否有效 | 是 | 是 | 是 |
是否参与打包 | 是 | 否 | 否 |
是否参与部署 | 是 | 否 | 否 |
Maven常用设置
全局变量
在 Maven 的 pom.xml 文件中,
作用:
在一个框架中不可能只有一个依赖,它会包含很多依赖,但是每个版本号不同在使用时候会产生BUG或未知错误,所以为了便于统一管理使用全局变量来管理每个框架依赖的版本号,以保证每个框架版本号是统一的。
语法
<!--定义spring.version版本号-->
<properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<!--引用全局变量-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Maven 系统采用的变量-->
<properties>
<maven.compiler.source>11</maven.compiler.source> <!--源码编译 jdk 版本-->
<maven.compiler.target>11</maven.compiler.target> <!--运行代码的 jdk 版本-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--项目构建使用的编码,避免中文乱码-->
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!--生成报告的编码-->
</properties>
指定资源位置
作用
src/main/java 和 src/test/java 这两个目录中的所有*.java 文件会分别在 comile 和 test-comiple 阶段被编译,编译结果分别放到了 target/classes 和 targe/test-classes 目录中,但是这两个目录中的其他文件都会被忽略掉,如果需要把 src 目录下的文件包放到 target/classes 目录,作为输出的 jar 一部分。需要指定资源文件位置。 以下内容放到
语法
<resources>
<resource>
<!--需要不被过滤的目录-->
<directory>src/main/resources</directory>
<includes>
<!--需要不被过滤的文件-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--filtering:是否启用过滤器:true(启用)/false(禁用)-->
<filtering>true</filtering>
</resource>
<resource>
<!--需要不被过滤的目录-->
<directory>src/main/java</directory>
<includes>
<!--需要不被过滤的文件-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!--filtering:是否启用过滤器:true(启用)/false(禁用)-->
<filtering>true</filtering>
</resource>
</resources>
Idea使用Maven原型创建项目
基本项目常用配置
JavaSE项目配置
<dependencies>
<!-- JDBC依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
</dependencies>
JavaWEB项目配置
<dependencies>
<!-- Servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jsp依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- Jackson(JSON工具包) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<!-- JDBC依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<!-- JSTL依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
常用项目
- internal -> appfuse-basic-jsf (创建一个基于Hibernate,Spring和JSF的Web应用程序的原型)
- internal -> appfuse-basic-spring (创建一个基于Hibernate,Spring和Spring MVC的Web应用程序的原型)
- internal -> appfuse-basic-struts (创建一个基于Hibernate,Spring和Struts 2的Web应用程序的原型)
- internal -> appfuse-basic-tapestry (创建一个基于Hibernate, Spring 和 Tapestry 4的Web应用程序的原型)
- internal -> appfuse-core (创建一个基于 Hibernate and Spring 和 XFire的jar应用程序的原型)
- internal -> appfuse-modular-jsf (创建一个基于 Hibernate,Spring和JSF的模块化应用原型)
- internal -> appfuse-modular-spring (创建一个基于 Hibernate, Spring 和 Spring MVC 的模块化应用原型)
- internal -> appfuse-modular-struts (创建一个基于 Hibernate, Spring 和 Struts 2 的模块化应用原型)
- internal -> appfuse-modular-tapestry (创建一个基于 Hibernate, Spring 和 Tapestry 4 的模块化应用原型)
- internal -> maven-archetype-j2ee-simple (一个简单的J2EE的Java应用程序)
- internal -> maven-archetype-marmalade-mojo (一个Maven的 插件开发项目 using marmalade)
- internal -> maven-archetype-mojo (一个Maven的Java插件开发项目)
- internal -> maven-archetype-portlet (一个简单的portlet应用程序)
- internal -> maven-archetype-profiles ()
- internal -> maven-archetype-quickstart (javaSE项目)
- internal -> maven-archetype-site-simple (简单的网站生成项目)
- internal -> maven-archetype-site (更复杂的网站项目一般用来做父工程)
- internal -> maven-archetype-webapp (一个简单的Java Web应用程序)
- internal -> jini-service-archetype (Archetype for Jini service project creation)
- internal -> softeu-archetype-seam (JSF+Facelets+Seam Archetype)
- internal -> softeu-archetype-seam-simple (JSF+Facelets+Seam (无残留) 原型)
- internal -> softeu-archetype-jsf (JSF+Facelets 原型)
- internal -> jpa-maven-archetype (JPA 应用程序)
- internal -> spring-osgi-bundle-archetype (Spring-OSGi 原型)
- internal -> confluence-plugin-archetype (Atlassian 聚合插件原型)
- internal -> jira-plugin-archetype (Atlassian JIRA 插件原型)
- internal -> maven-archetype-har (Hibernate 存档)
- internal -> maven-archetype-sar (JBoss 服务存档)
- internal -> wicket-archetype-quickstart (一个简单的Apache Wicket的项目)
- internal -> scala-archetype-simple (一个简单的scala的项目)
- internal -> lift-archetype-blank (一个 blank/empty liftweb 项目)
- internal -> lift-archetype-basic (基本(liftweb)项目)
- internal -> cocoon-22-archetype-block-plain ([http://cocoapacorg2/maven-plugins/])
- internal -> cocoon-22-archetype-block ([http://cocoapacorg2/maven-plugins/])
- internal -> cocoon-22-archetype-webapp ([http://cocoapacorg2/maven-plugins/])
- internal -> myfaces-archetype-helloworld (使用MyFaces的一个简单的原型)
- internal -> myfaces-archetype-helloworld-facelets (一个使用MyFaces和Facelets的简单原型)
- internal -> myfaces-archetype-trinidad (一个使用MyFaces和Trinidad的简单原型)
- internal -> myfaces-archetype-jsfcomponents (一种使用MyFaces创建定制JSF组件的简单的原型)
- internal -> gmaven-archetype-basic (Groovy的基本原型)
- internal -> gmaven-archetype-mojo (Groovy mojo 原型)