Maven的学习
Maven是Apache的一个项目,它使用对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。它集项目的构建,清理,编译等于一体,以前我们在使用IDE时,基本上一键就可以完成很多功能(编译,运行),而对其内部并不了解,虽然Maven不是作为让我们了解这些过程的工具,但其带来了一些好处却很有意义:比如说以前我们构建项目时,需要拷贝大量的jar包,虽然挺方便,复制粘贴,但是存在潜在问题,多个版本的冲突问题,不同开发者版本不一致的问题等等,而Maven可以帮助我们解决这些问题
Maven的下载与安装
我们在Maven官网(https://maven.apache.org/)下载之后,直接解压缩即可,是免安装的,我个人其实挺喜欢免安装的。下来是配置环境变量:
配置MAVEN_HOME到其解压缩的目录,值得注意的一点是:Maven需要JDK的支持,所以在使用之前一定要有JAVA_HONE的配置。
最后一步是在path中配置:(以便可以在cmd中使用Maven命令)
验证是否配置完成的方法是:在cmd中输入:mvn -v 可以输出版本信息就表示配置完成了,这也是我学到的第一个Maven命令
Maven的目录结构
了解一下Maven的目录结构,是有好处的:
conf文件夹中有一个settings.xml文件,我们一会要修改一下其中的配置
Maven的工作方式
Maven项目的是非常小的,因为web项目中占大头的就是jar包,Maven就对这一部分进行采用依赖的概念,所谓依赖就是只根据jar包的坐标信息就可以了,而不使用复制jar的方式。这就引发了另一个概念——坐标:坐标就是标识一个jar包的信息,通过这些信息表示jar
坐标信息由:groupId和artifactId,version信息构成。基本上我们的Maven项目也是根据这三者进行标识的,groupid表示公司域名反写,artifactid表示项目名,version表示版本
web项目中的jar都根据配置信息表示了,那是不是说我们不需要jar包就可以运行项目了?
并不是这样的,Maven需要在你的本地仓库中查找jar,如果没有就在你的Maven私服中的查找,如果还没有就去Maven的中央仓库中查找并下载到你的本地仓库。仓库就是存放jar的地方
虽然我们并不是通过复制/导入的方式使用jar包,但你在本地测试时还是需要jar的支持,不然怎么运行
构建本地仓库
这是时候就需要我们修改那个settings.xml文件了,打开找到下面的标签,修改为你的本地仓库:
本地仓库也不是说放一个jar包就可以了,还需要一些配置信息(这是一个mysql连接驱动)
我们再来看一个Maven项目的目录,注意是项目的目录,不是Maven的目录(这个pom.xml很重要,我们配置jar坐标就要在这里)
target目录就是我们编译过后class文件,配置文件以及最后打包后的文件所在了
常见Maven命令
Maven命令都是使用 mvn开头的 ,如 mvn clean,命令也可以组合使用 mvn clean package
1. clean:清理命令。将项目下的target目录删除
2. compile:编译命令。将.java文件编译为.class文件,同时生成target目录
3. test:测试命令。会运行所有单元测试类
4. package:打包命令。在target目录下生成jar/war
5. install:安装命令。安装打包的项目到本地仓库,以供其他项目使用
6. site:生成站点命令。会生成项目站点文档
7. deploy:发布命令。拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程
8. validate:验证命令。验证项目是否正确且所有必须信息是可用的
Maven常见的生命周期
1. 清理生命周期:执行clean命令
2. 默认生命周期:执行validate compile test package install deploy命令
3. 站点生命周期:执行 site命令
可以看到,因为clean单独作为一个生命周期,所以一般都会在执行其他命令之前先执行clean,例如:mvn clean package
Maven在IDE中的使用(这里使用Eclipse)
首先保证你使用Eclipse的JRE是JDK中的JRE,如果使用的是普通的jre是会有一个关于JDK的异常出现,在外面的jre和jdk中的jre还是有一些区别的,因为Maven要使用JDK,所以一定要使用JDK中的JRE
1.配置成我们下载的Maven
对了,如果你使用的Eclipse版本太低,设置中是没有Maven选项的,需要先安装一个Maven插件
2.配置User settings
配置成我们修改过的Maven中的settings.xml文件,同时下面也会找到我们的本地仓库
3.生成一个Maven项目
3.1右键new一个Maven项目
选择Maven Project就可以了
3.2然后就到了下面的页面:
勾选第一个选项,表示使用一个简易设置生成Maven项目,即使不勾选,自己去选一个Maven设置,其生成的Maven项目也不完整,还不如简单点
3.3填写一些Maven信息,这里可以看到要填写的是这个Maven项目的坐标
之后final就可以了
生成Maven项目出现的问题
1.web.xml文件的缺失
Maven自动生成的项目没有web.xml文件,我们需要添加:
这里使用了Eclipse的工具添加,当然,你也可以自己进行添加,添加到src/main/webapp下,记得web.xml文件要在WEB-INF文件夹中,也就是说要先添加WEB-INF,再在WEB-INF中添加web.xml
2.JDK版本不一致
自动生成的Maven项目中使用的JDK虽然是我们在Eclipse中配置的,但显示的名称却不一致,我们需要改一致(我是用的JDK1.8)。在pom.xml文件中配置maven-compiler-plugin这个插件:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin>
我们可以在pom.xml文件右键添加插件
3.配置了1.8这么高的版本,还需要我们配置一下编译的Tomcat
添加tomcat7-maven-plugin插件:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin>
可以使用右键添加插件的方式
一会我们要使用tomcat7:run命令(如果使用tomcat8会不会去下载tomcat8?)来执行,tomcat7就可以使用JDK1.8了,而如果使用tomcat:run默认使用的tomcat6的版本,不支持1.8,只支持到1.7
4.xml文件竟然不会找不到
我们还需要添加配置指定我们的xml文件复制到编译的target\classes,不然SSH整合时会找不到那些xml文件
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources>
不论resources还是plugin节点都需要放在build节点下
5.拓展-多环境打包
Spring/SpringBoot应用可以配置多个环境下的配置文件
可以在application.yml中配置启用的配置文件,但是打包的时候还是会将所有的application-xxx.yml打包进去,可以使用Maven的resources标签解决这个问题
<build> <resources> <resource> <directory>src/main/resources</directory> <!--filtering表示开启文件过滤, 会对${}进行选择过滤--> <filtering>true</filtering> <includes> <include>application.yml</include> <include>application-${profileActive}.yml</include> <include>**/*.properties</include> <include>**/*.xml</include> </includes> </resource> </resources> </build> <profiles> <profile> <id>dev</id> <properties> <profileActive>dev</profileActive> </properties> </profile> <profile> <id>dev2</id> <activation> <!--当未指定启用配置文件时, 默认启用的配置文件--> <activeByDefault>true</activeByDefault> </activation> <properties> <profileActive>dev2</profileActive> </properties> </profile> <profile> <id>prod</id> <properties> <profileActive>prod</profileActive> </properties> </profile> </profiles>
执行Maven命令
mvn clean package -DskipTest -P配置文件profile标识(profile-id)
6. 打包指定模块
在多module的maven项目中,如果每次打包整个工程显得有些冗余和笨重,可以指定打包所需的模块
执行Maven命令
mvn clean package -pl 模块的名称 -am -DskipTests
解决了这么多问题,开始运行
可以运行了嘛?很遗憾还没有,因为可能存在找不到Servlet和jsp的jar,下来我们需要添加这两个jar的坐标:
<!-- Servlet&JSP --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.2-b02</version> <scope>provided</scope> </dependency>
jar的坐标都需要放在dependencies节点下,可以使用右键的方式,方法和添加插件类似,只不过使用的是Add Dependency选项。
这里Servlet和JSP的jar都使用了scope指定其范围,可以指定的范围有:
Servlet和JSP的jar包不需要在运行时使用,因为Tomcat中有相应jar,会冲突。我们可以根据要添加的jar选择其范围,默认是compile
到现在我们竟然还不知道Java代码和xml文件,web页面放到哪里?
java代码放在src/main/java
xml可以放在src/main/resources
测试java代码放在src/test/java
测试资源和文件放在src/test/resources
web页面可以放在src/main/webapp
在运行之前update一下Maven项目,这是倒数第二步哦:
开始使用tomcat7:run运行吧
在这里也可以使用clean 或package等命令
如果使用Debug还需要在Source视图中把我们的项目添加进去,不然断点是不起作用的:
处理版本冲突
Maven是如何处理的jar包版本冲突的?
Maven使用两条原则:
1.选择路径最短的:比如两条路径A-B-C D-C 第一条路径的C版本为1.0,第二条路径的C版本是1.1,就会使用路径最短的1.1版本
2.谁先声明,就是使用谁
会优先使用原则1,如果无法解决则尝试使用原则2解决,还是无法解决就需要我们去处理了,这就是Maven自动处理冲突的规则
如果还是不能解决版本冲突,也可以使用版本锁定:
<dependencyManagement> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </dependencyManagement>
锁定为要使用的版本坐标
项目的拆分与聚合
把我们的web项目拆分为Dao,Service,Web三层,便于开发和维护,同时也降低了耦合性
1.这个时候就要使用父工程了,我们在新建工程的时候要把打包方式设置为pom
我们来看看父工程的结构:
整个结构非常简单,可以知道父工程的作用就是来约束我们项目中使用的jar包,并组织子模块。我们把pom.xml文件添加需要的jar坐标就好了(父项目一般是做依赖管理的,将所需的jar坐标都添加到父项目的pom.xml),接着将父工程打包到本地仓库:
2.在将父工程打包之后,在父工程右键新建一个子模块(注意:选择的是Maven Module)
打包方式选择jar,因为我们的Dao都是一些Java代码,之后的Service模块也需要我们打成jar包:
之后编写相应的Dao层代码就好了(不要忘了那些xml文件,我把spring的XML文件,Log4j的配置文件也放到了Dao层,后面层可以继承)。编写完成后打包发布
3.Service层类似,不过需要在其pom文件中添加Dao的坐标信息,存在引用关系嘛。完成后打包发布
4.Web层有些特殊,因为web层有Html页面,所以记得要打成war包:
需要添加Service的坐标信息,完成后打包发布。
这是一个war包,我们可以使用tomcat7:run的命令运行,也可以使用在Eclipse中配置的Tomcat运行,推荐使用后者,因为运行和调试都很方便
来看一张表示拆分之后项目的依赖范围的图:
私服的搭建
Maven会先在本地仓库中寻找jar,没有找到,如果配有私服,就会到私服中查找,还没有才到中央仓库。可能有些公司都不提供外网给项目组人员,因此就不能使用maven访问远程的仓库地址,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库
1.首先确定我们的环境安装好maven,jdk等必须的环境
2.这些都准备好之后,去下载最新版本的nexus 下载地址:http://www.sonatype.org
我本地安装的是 nexus-2.14,直接解压缩即可
3.使用管理员权限打开cmd,并cd进入该解压目录,输入命令nexus install ,安装成功后输入nexus start开启服务
看到nexus started之后就可以访问http://localhost:8081/nexus/ 启动之后,在右上角有个Log in 的超链接,点击登录,不登陆的话,一些操作无法进行
默认的用户名是 admin 密码是 admin123
来看一下仓库的类型,nexus又对仓库类型进行了细分
可能需要注意一下的,就是3rd party、Snapshots、Releases这三个,分别用来保存第三方jar(典型的oracle数据库的驱动包),项目组内部的快照、项目组内部的发布版
私服中jar包的上传与下载
上传
1.需要在maven的conf/settings.xml文件中配置认证:就是用户名和密码
2.在需要上传的maven项目中的pom.xml文件中设置上传的路径:上传到哪个仓库
<distributionManagement> <repository> <id>releases</id> <url>http://localhost:8081/nexus/content/repositories/releases/</url> </repository> <snapshotRepository> <id>snapshots</id> <url>http://localhost:8081/nexus/content/repositories/snapshots/</url> </snapshotRepository> </distributionManagement>
这里上传到releases和snapshots仓库中。配置完成后,在maven build命令窗口输入deploy就可以上传了
mvn clean deploy
下载
之前没有使用私服构建maven项目,我们只需要给出jar的坐标信息即可,本地没有就从中央仓库下载,现在有了私服,如果本地仓库没有,应该先到私服中寻找,还没有再到外网仓库中下载
1.所以需要在maven的conf/settings.xml中的profiles节点配置一个模板:
<profile> <!--配置文件ID为dev--> <id>dev</id> <repositories> <repository> <!--仓库id repositories可以配置多个仓库,保证id不重复--> <id>nexus</id> <!--仓库地址,这里使用nexus组仓库地址--> <url>http://localhost:8081/nexus/content/groups/public/</url> <!--是否下载releases构件--> <releases> <enabled>true</enabled> </releases> <!--是否下载snapshots构件--> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <!--插件地址 nexus需要依赖的插件--> <pluginRepositories> <pluginRepository> <!--插件id不允许重复,如果重复,后面的会覆盖前面--> <id>public</id> <name>Public Repository</name> <url>http://localhost:8081/nexus/content/groups/public</url> </pluginRepository> </pluginRepositories> </profile>
指定从组仓库中下载,因为组仓库基本上包括所有的其他仓库
2.激活这个模板
<!--激活dev配置文件--> <activeProfiles> <activeProfile>dev</activeProfile> </activeProfiles>
之后的使用只需要添加jar的GAV信息就可以了
替换成阿里云Maven仓库镜像
Maven默认的远程仓库(https://repo.maven.apache.org/maven2,解压Maven安装目录下lib/maven-model-builder-xxx.xx.jar中org/apache/maven/model/pom-4.0.0.xml文件中Central Repository),无奈有时下载jar会很慢,可以替换成阿里云的Maven仓库镜像,提升下载速度。只需要在conf\settings.xml 文件中添加如下配置:
<mirror> <id>nexus-aliyun</id> <mirrorOf>*</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
配置在 mirrors 标签下即可。私服也是通过配置镜像的方式配置的,方法如上
mirrorOf元素高级配置:
<mirrirOf>*</mirrirOf>:表示该镜像是所有Maven仓库的镜像,任务对于远程仓库的访问都会转到镜像的url
<mirrirOf>external: *</mirrirOf>:匹配远程仓库,所有不是本机上的仓库
<mirrirOf>repo1, repo2</mirrirOf>:匹配多个远程仓库id,使用逗号分隔
<mirrirOf>*, ! repo1</mirrirOf>:匹配所有远程仓库,repo1除外
需要注意,有于镜像仓库完全屏蔽了被镜像的仓库,当镜像仓库出现问题,Maven将无法下载构件