教程的源码请参考
https://gitee.com/blueboz/maven-learn
Maven 简述
Maven是apache 官方推出的一款项目自动构建工具。这款工具可以方便我们项目依赖的维护,构建,测试,发布。
不同构建工具的对比
Eclipse
使用eclipse进行项目构建,相对来说,步骤比较零散,不好操作
Ant
它是一个专门的项目构建工具,它可以通过一些配置来完成项目构建,这些配置要明确的告诉ant,源码包在哪?目标class文件应该存放在哪?资源文件应该在哪
Maven
它是一个项目管理工具,他也是一个项目构建工具,通过使用maven,可以对项目进行快速简单的构建,它不需要告诉maven很多信息,但是需要安装maven去的规范去进行代码的开发。也就是说maven是有约束的。
Gradle
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。
可以这样说,Gradle是一款替代Maven的工具,但是Gradle 又有很多方面与Maven共用。说以学习Maven与学习Gradle不冲突,并且主流的很多企业依然在使用Maven。
Maven 的安装
官方下载的地址是下面
http://maven.apache.org/download.cgi
解压下载后的zip 包后,结构如下图所示
windows环境下的安装
配置环境变量
MAVEN_HOME,这个环境变量的变量值,是我们解压的后maven 所在的路径
配置Maven的环境变量Path路径
这个Path主要是用于指向maven.exe路径,由于我们之前配置了MAVEN_HOME环境变量,所以,在Path环境变量后面,只要追加
;%MAVEN_HOME%/bin
即可
测试maven是否安装成功
如果可以看见输出版本号,证明maven 已经安装成功了。
Linux ->Ubuntu环境下的安装方法
参考另外的一篇博客关于maven 的安装
Maven 是跨平台的,所以他在任何一个平台都是可以运行的。这里讲介绍如何在Ubuntu14上安装maven 客户端。其他linux发行版本请参照这个。大同小异。
安装Jdk1.7
与window一样,maven 以来jdk,所以必须先安装jdk之后,才可以安装maven
请参考百度经验
http://jingyan.baidu.com/article/647f0115bb26817f2048a871.html
http://www.cnblogs.com/fordreamxin/p/4287706.html(Linux下jdk版本的切换)
安装maven
安装maven 方法很简单,只需要将下载的文件解压,并设置环境变量即可
1.找到我们下载的maven
2.解压这里是使用命令行的方式解压,不懂也可以通过7zip
3.将解压后的文件夹移动到合适的位置
因为笔者习惯是将软件安装在$HOME/bin目录下,所以在
/home/blueboz/bin/目录下新建了一个Maven目录,用于存放我们的maven
blueboz@BLUEBOZ:~/下载$
mv apache-maven-3.3.9 /home/blueboz/bin/maven/
4.设置环境变量
blueboz@BLUEBOZ:~$
export M2_HOME=/home/blueboz/bin/maven/
5.在Path 环境变量中追加Mavan bin目录
blueboz@BLUEBOZ:~$
export PATH=$PATH:$M2_HOME/bin
6.检验maven是否安装成功
输入mvn -v 就可以看到Maven的版本了
注意
在如果是使用export 命令在终端进行环境变量的设置的话,会出现这样的问题,就是在系统重启之后或者新开的终端,所有的刚刚配置的环境变量都将会失效,如何解决这个问题,那么就是类似与windows,在专门配置文件中写入即可
修改系统环境变量
1.通過修改/etc/enviroment這個配置文件即可.
gedit /etc/enviroment
2.文件内容
只需要在后面添加所需要配置的环境变量信息即可
修改前
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
修改后
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:$MAVEN_HOME/bin:$JAVA_HOME/bin"
MAVEN_HOME="/user/home/blueboz/bin/maven"
JAVA_HOME="/usr/lib/jvm/jdk1.8.0_121/"
修改用户环境变量
1.通过修改用户目录下的 .bashrc
这个文件,如果没有就自己新建一个就可以了.注意前面的 点不能少!
blueboz@BLUEBOZ:/etc$ gedit ~/.bashrc
Maven的常用配置信息
关于maven的配置文件,可以指定两种级别如下
用户级别, 这个settings.xml 文件为只为一个用户提供配置信息,(所谓一个用户,通常是我们正在登陆的用户。例如Administrator)并且经常放在~/.m2/settings.xml
全局级别 ,全局的settings.xml配置文件在 mavenHome目录下的/config/setting.xml 文件,也就是现在的这个我们安装maven 解压包的conf目录下。
通过在命令行模式下,输入下面指令,我已获得用户目录
echo %USERPROFILE%
配置信息详解
由于全局配置信息与单用户配置文件内容是一模一样的,所以,这里只将一种的配置方法.
全局配置信息在maven 解压目录下的conf目录下的setting.xml文件
在ubuntu下那么这个文件在$MAVEN_HOME/conf目录下的setting
打开这个配置文件,我们可以就可以进行配置了
配置文件结构
<?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>~/.m2/repository</localRepository>
<!--Maven是否与用户交互,默认值为true-->
<interactiveMode>true</interactiveMode>
<!--离线模式,默认值为false-->
<offline>false</offline>
<!--插件组-->
<pluginGroups></pluginGroups>
<!--代理-->
<proxies></proxies>
<!--下载与部署仓库的认证信息-->
<servers></servers>
<!--仓库镜像-->
<mirrors>
<mirror>
<id>bluebozRepo</id>
<mirrorOf>central</mirrorOf>
<name>Blueboz</name>
<url>http://bluebozpc:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<!--Settings Profile-->s
<profiles></profiles>
<!--激活Profile-->
<activeProfiles></activeProfile>
</settings>
mirrors的配置
由于maven库是在国外的,在下载构建的时候速度往往比较慢.因此可以配置国内的Nexus服或者直接使用自己的私服.
下面示例alibabaNexus服
<mirrors>
<mirror>
<id>Alibaba</id>
<mirrorOf>*</mirrorOf>
<name>AliyunMaven</name>
<url>
http://maven.aliyun.com/nexus/content/groups/public/
</url>
</mirror>
</mirrors>
在示例中,mirrorOf的值为central,表示该配置为中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像.另外三个元素id,name,url 与一般的仓库的配置无异,表示该镜像仓库的唯一标识.
如果mirrorOf 的值为星号.表示该配置是所有maven仓库的镜像,任何对于远程仓库的请求都会转到对应镜像.如果该仓库需要认证.那么配置一个id 为internal-repository的<server>即可.
1.<mirrorOf>*</mirrorOf>匹配所有远程仓库
2.<mirrorOf>external:*</mirrorOf>匹配所有不在本机上的的远程仓库
3.<mirrorOf>repo1,repo2</mirrorOf>匹配仓库repo1和repo2使用逗号分割多个远程仓库
4.<mirrorOf>*,!repo1</mirrorOf>匹配所有仓库,repo1除外.
Maven 命令的基本使用
使用mvn 指令创建java 项目
mvn archetype:generate -DgroupId=cn.blueboz -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
使用该指令之后生成的项目结构是
使用mvn 指令创建web项目
mvn archetype:generate -DgroupId=cn.blueboz -DartifactId=my-webapp -Darche
typeArtifactId=maven-archetype-webapp -DinteractiveMode=false
Maven中的坐标和依赖
Maven install
mvn install
的作用是将当前所在的项目安装到 localRepository中,也就是$HOME/.m2/repository 目录下
install 之后呢就会出现在本地仓库下面,如果本机的其他项目依赖到该项目的话,就可以通过parent属性进行引用
例如下面
这是我的artifact为base的项目
<groupId>cn.boz.security</groupId>
<artifactId>base</artifactId>
<version>1.0-SNAPSHOT</version>
现在有一个子项目basechild需要引用到这个base 项目,那么子项目的Pom文件中有一段
<parent>
<artifactId>base</artifactId>
<groupId>cn.boz.security</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--
-因为是子项目,所以可以忽略GAV中的G(Group)V(Version)
-默认继承父类属性
-->
<artifactId>base-child</artifactId>
我们知道,base-child项目依赖base,项目,那么假如这个base-chlid不在同一目录下,那么maven 将通过GAV去找父项目。但是找呀找,没有找到,本地仓库(未部署)没找到,远程仓库更不用说,这时候,就会报错。解决方法有两个
一是在base 项目下,使用mvn install 将base项目安装到localRepository中。
二是,在base-child项目下,pom文件的parent节点,再加一段,相对论
<relativePath>../base/pom.xml</relativePath>
这段相对路径是告诉basechild项目,应该如何去查找到自己的父项目。
从而避免了找不多构件的错误的发生
如何将构建部署到私服(deploy)
部署的命令是,如果没有进行配置,一定会报错的。因为你还没有配置远程私服的路径,以及认证用户名密码,会报401错误
mvn install
对于公司内部,采用私服的方式进行开发,你开发了一个功能需要提供给B 使用,这时候,B通过GAV定位你的资源,会去私服上查找你的资格构件,所以我们必须将这个构件上传上去。
首先必须明确两点
1.上传到那里去
先要有个maven私服吧,私服在nexus官网找那个社区版本
https://www.sonatype.com/nexus-repository-oss
提供大家一个链接去下载一个私服
https://sonatype-download.global.ssl.fastly.net/repository/repositoryManager/3/nexus-3.10.0-04-win64.zip
这个链接是windows x64的
下载完成之后直接解压,解压后可以看到如下的目录结构
下载之后是一个已经集成了Jettty的服务了。打开bin目录
注意,是需要使用终端进入的cmd
使用
>nexus /run
才能启动,具体的方法请参照官网给出的提示进行操作,下面是官网的文档,纯英文的,建议大家用谷歌翻译看下大概。
https://help.sonatype.com/repomanager3
注意,Nexus 私服是需要jdk环境的,如果没有jdk,运行是会报错的,请记得配置好JAVA_HOME环境变量以及Path环境变量
如何修改服务的端口
\nexus-3.2.1-01\etc\nexus-default.properties
这个文件下修改如下的配置即可
application-port=8081
application-host=0.0.0.0
配置完启动之后,通过浏览器就能直接进行访问了
看到这个图,也就说明私服搭建已经成功了。
但是管理的话需要用户名密码,
查看官网文档,可以知道默认用户名密码如下
也就是admin/admin123
那么私服启动之后,就需要打开我们的Maven项目,pom.xml文件,
<distributionManagement>
<repository>
<id>releases</id>
<name>Internal Release</name>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>Internal Snapshot</name>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
需要注意的是 <id> 配置的Id 必须是唯一的。而且不能够重复,这个ID可以是随意的。
这里配置了两个服务地址
一个是发布版,一个是snapshot版
maven 通过我们当前的版本,判别是属于Release版还是SNAPSHOT版
也就是通过<version>中是否有SNAPSHOT来判断。
这里引用百度知道上的一段说明
maven2会根据模块的版本号(pom文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本。如果是快照版本,那么在mvn
deploy时会自动发布到快照版本库中,而使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。如果是正式发布版本,那么在mvn
deploy时会自动发布到正式版本库中,而使用正式版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载。
知道本地的版本之后,部署的时候,就会去轮询好已经配置了repository
根据snapshotRepository还是repository,来进行上传
如果下是远程仓库的配置项
2. 怎么认证
你总不可以说无论谁都可以上传吧。总得进行权限控制
用户名密码实在我们的maven安装路径下的settings.xml文件,或者用户目录下的.m2/settings.xml文件
如果有那么一点linux常识的人应该也会知道,全局配置(Maven 安装目录下的settings.xml)是要被用户配置所覆盖的,所以一般建议配置在用户目录下。但这也不是必须的。但是要记住,全局配置有动一发而牵动全身的缺点。不废话。直接配置文件。
<servers>
<server>
<id>releases</id>
<username>blueboz</username>
<password>chenchen</password>
</server>
<server>
<id>snapshots</id>
<username>blueboz</username>
<password>chenchen</password>
</server>
</servers>
这里强调一点,ID必须与刚刚配置的pom文件中的ID要一致,否则会导致认证失败!
Maven的profile
开发中有一个需求就是,根据当前的操作系统的类型,jdk版本号,去执行那个配置文件,跟着根据命令去启动配置信息
实现方式可以在pom文件中的profiles节点进行配置。
该节点允许你配置依赖,插件。等pom文件根节点允许配置的内容。其目的就是条件覆盖。
如下。配置了一个ID为development的配置,下面配置了一个build节点,这个与pom根目录的作用一模一样。唯一的不同是,下面这部分配置如果正常运行时不生效的。需要使用
mvn compile -Pdevelopment
<profile>
<id>development</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>
false
</debug>
<optimize>true</optimize>
</configuration>
</plugin>
</plugins>
</build>
</profile>
同样,给出另外一个例子提供参考,跟你就jdk版本,系统版本,以及一些java SystemProperties进行判别,主要是在<activation>节点进行配置。
<!--执行mvn install 时候可以看到效果-->
<profile>
<id>jdk1.8</id>
<activation>
<jdk>1.8</jdk>
<os>
<name>Windows 7</name>
<family>Windows</family>
<arch>x64</arch>
<version>5.0</version>
</os>
<property>
<name>mavenVersion</name>
<value>3.4.5</value>
</property>
<file>
<exists>file1.properties</exists>
<!--!表示非-->
<missing>!file2.properties</missing>
</file>
</activation>
<!--只在jdk8的时候,引入某一个模块-->
<modules>
<module>../basechild</module>
</modules>
</profile>
Maven套件
有时候,我们想根据自己的意思,对当前项目进行不同方式的打包。例如打包一个zip、或者gzip等等。那么这时候,mvn assembly 就很有用了
教程的源码请参考
https://gitee.com/blueboz/maven-learn
如下图所示,分别是使用不同压缩模式进行压缩。
使用命令行的方式执行
assembly 这个插件有两个主要的目标(Goals) assembly/single
引用《Maven 权威指南》中的一段话。
所以一般执行命令是
mvn assembly:single
同时maven 提供了几种默认的套件描述符供我们使用,分别是
mvn assembly:single -DdescriptorId=jar-with-dependencies
mvn assembly:single -DdescriptorId=bin
mvn assembly:single -DdescriptorId=project
mvn assembly:single -DdescriptorId=src
分别对应到我们上面那张图片
bin
假设一个项目构建了一个jar作为它的主构件, bin 描述符用来包裹该主构件和 项目的 LICENSE , README , 和
NOTICE 文件。我们可以认为这是一个完全自包含项 目的最可能小的二进制分发包
这个指令要求有一个jar文件为基础才可以执行构建
![]()
jar-with-dependencies
jar-with-dependencies 描述符构建一个带有主项目jar文件和所有项目运行时依
赖未解开内容的JAR归档文件。外加上适当的 Main-Class Manifest条目(在下面
的“插件配置”讨论),该描述符可以为你的项目生成一个自包含的,可运行的 jar,即使该项目含有依赖。
![]()
project
project 描述符会简单的将你文件系统或者版本控制中的项目目录结构整个的归
档。当然,target目录会被忽略,目录中的版本控制元数据文件如 .svn 和 CVS 目
录也会被忽略。基本上,该描述符的目的是创建一个解开后就立刻能由Maven构
建的归档。
![]()
src
src 描述符生成一个包含你项目源码, pom.xml 文件,以及项目根目录中所
有 LICENSE , README ,和 NOTICE 文件的归档。它类似于 project 描述符,大部分情况下能生成一个可以被Maven构建的归档。然而,由于它假设所有的源文件和资
源文件都位于标准的 src 目录下,它就可能遗漏那些非标准的目录和文件,而这
些文件往往对构建起着关键作用。
在pom文件中,将我们的套件绑定到package阶段
参考我的代码中basechild项目代码,我们的主类在cn.boz.security.basechild.MyTester
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<id>create-executable-jar</id>
<phase>package</phase>
<goals>
<!--当执行pckage 会执行 assembly:single 这个命令-->
<goal>single</goal>
</goals>
<configuration>
<descriptorId>
jar-with-dependencies
</descriptorId>
<archive>
<manifest>
<mainClass>cn.boz.security.basechild.MyTester</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
主类代码
package cn.boz.security.basechild;
public class MyTester {
public static void main(String[] args){
System.out.println("The main method is running...");
System.out.println("The main method is stop");
}
}
执行打包命令
mvn package
由于在上面的代码中,将assembly:single -DprojectId=jar-with-dependencies 绑定了,所以package 之后,target目录会出现如下的文件
其中上面的jar包是package默认打包的jar包,仅仅是当前项目的源代码打包,不适于java -jar 执行,会报错,找不到主类的错误。
尝试执行后面的文件,见下图效果
可以看出,程序打印了我们在代码写的两句sysout
疑问,如何绑定多个套件
假设,我想project同时java-with-dependencies同时又src,又bin怎么办,如下代码所示即可。
<configuration>
<!--ref就是可以克服id 只能有一个的问题-->
<descriptorRefs>
<descriptorRef>project</descriptorRef>
<descriptorRef>src</descriptorRef>
<descriptorRef>bin</descriptorRef>
</descriptorRefs>
</configuration>
自定义套件
Plugins中Executions的讲解
通常,我们可以在mvn pluginID:goals进行插件的执行。例如mvn assembly:single
但是我们也可以不用使用命令行进行执行,通过将这些指令绑定到maven的特定生命周期的时候,才执行 ,如下例子表明了将assembly:single -DdescriptorId=jar-with-dependencies绑定到package,这样
在mvn package的时候,也会顺势执行我们所定义的这个插件
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
<executions>
<execution>
<id>create-executable-jar</id>
<phase>package</phase>
<goals>
<!--当执行package 会执行 assembly:single 这个命令-->
<goal>single</goal>
</goals>
<configuration>
<descriptorId>
jar-with-dependencies
</descriptorId>
<archive>
<manifest>
<mainClass>cn.boz.security.basechild.MyTester</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
执行效果如下
$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building base-child 1.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-assembly-plugin:2.2-beta-5:single (create-executable-jar) @ base-c
hild ---
[INFO] Building tar : E:\WebDev\CAS\securityproj\basechild\target\base-child-1.1-SN
APSHOT-project.tar.gz
[INFO] Building tar : E:\WebDev\CAS\securityproj\basechild\target\base-child-1.1-SN
APSHOT-project.tar.bz2
[INFO] Building zip: E:\WebDev\CAS\securityproj\basechild\target\base-child-1.1-SNA
PSHOT-project.zip
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.908 s
[INFO] Finished at: 2018-04-06T16:36:48+08:00
[INFO] Final Memory: 21M/155M
[INFO] ------------------------------------------------------------------------
查看插件的完整描述
我们知道,插件是由于Plugin+goal 组成,一个插件有多个目标。就好比如
jetty:run 表示我们执行的是jetty这个插件的run目标,但是如果想查看一个插件有多少目标,可以怎么插件,通过如下命令,可以查看
$ mvn help:describe -Dplugin=jetty -Dfull
执行之后,可以看到如下的
关于Maven中的继承与依赖
继承,也就是我们说的 pom文件的父子继承关于,多项目中可以书写一个parent,里面定义了本项目的所有依赖(dependency ),然后,子项目通过继承 <parent> 从而获得了父的所有依赖。
如何添加第三方骨架
我们知道,如果通过骨架来建立我们自己的项目 ,可以方便我们的开发。具体使用方法如下
mvn archetype:generate -DarchetypeGroupId=? -DarchetypeArtifactId=? [-DgroupId=? -DartifactId=? -Dversion=?]
//后面部分可选内容。如果不填,后续会提示填写的。
$ mvn archetype:generate -DgroupId=cn.boz -DartifactId=boz-maven-plugin -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-plugin
点击Configure
All Remote Catalog
录入
http://maven.aliyun.com/nexus/content/groups/public/archetype-catalog.xml
就可以了。
下图是添加之后的效果,多了很多骨架。同时我们也可以自己写一些骨架,帮助我们创建自己的骨架,方便创建项目。
注意,如果是通过命令行创建,必须保证使用的mirror服务器是aliyun ,或者是自己配置的URL指定的地址所在的私服。否则可能会找不到骨架报错。
例如我们录入
$ mvn archetype:generate -DgroupId=cn.boz -DartifactId=boz-maven-plugin -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee7
那么就会去指定服务器,寻找骨架。
[INFO] Archetype [org.codehaus.mojo.archetypes:webapp-javaee7:1.1 ->
http://maven.aliyun.com/nexus/content/groups/public] found in catalog remote
关于war插件的自定义配置
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- 指定webapp目录下有哪些文件是需要的,一旦需要的才会被打包过去。一般是** -->
<warSourceIncludes>
**
</warSourceIncludes>
<webResources>
<resource>
<directory>src/sit/lib/</directory>
<!-- 指定打包到的目标的目录 -->
<targetPath>WEB-INF/lib/</targetPath>
<include>*.jar</include>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
关于Maven 执行jar:jar 之后,打包文件无xml
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.js</include>
<include>**/*.css</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.eot</include>
<include>**/*.svg</include>
<include>**/*.ttf</include>
<include>**/*.woff</include>
<include>**/*.woff2</include>
<include>**/*.png</include>
</includes>
<excludes>
<exclude>aaa/fff/eef/console/xxx/sql/*</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
附录
maven 常用指令
https://blog.csdn.net/xiaxiaorui2003/article/details/52062216