文章目录
一、release and snapshot
Maven中建立的依赖管理方式基本已成为Java语言依赖管理的事实标准,Maven的替代者Gradle也基本沿用了Maven的依赖管理机制。在Maven依赖管理中,唯一标识一个依赖项是由该依赖项的三个属性构成的,分别是groupId、artifactId以及version。这三个属性可以唯一确定一个组件(Jar包或者War包)。
其实在Nexus仓库中,一个仓库一般分为public(Release)仓和SNAPSHOT仓,前者存放正式版本,后者存放快照版本。如果在项目配置文件中(无论是build.gradle还是pom.xml)指定的版本号带有’-SNAPSHOT’后缀,比如版本号为’Junit-4.10-SNAPSHOT’,那么打出的包就是一个快照版本。
快照版本和正式版本的主要区别在于,本地获取这些依赖的机制有所不同。假设你依赖一个库的正式版本,构建的时候构建工具会先在本次仓库中查找是否已经有了这个依赖库,如果没有的话才会去远程仓库中去拉取。所以假设你发布了Junit-4.10.jar到了远程仓库,有一个项目依赖了这个库,它第一次构建的时候会把该库从远程仓库中下载到本地仓库缓存,以后再次构建都不会去访问远程仓库了。所以如果你修改了代码,向远程仓库中发布了新的软件包,但仍然叫Junit-4.10.jar,那么依赖这个库的项目就无法得到最新更新。你只有在重新发布的时候升级版本,比如叫做Junit-4.11.jar,然后通知依赖该库的项目组也修改依赖版本为Junit-4.11,这样才能使用到你最新添加的功能。
这种方式在团队内部开发的时候会变的特别蛋痛。假设有两个小组负责维护两个组件,example-service和example-ui,其中example-ui项目依赖于example-service。而这两个项目每天都会构建多次,如果每次构建你都要升级example-service的版本,那么你会疯掉。这个时候SNAPSHOT版本就派上用场了。每天日常构建时你可以构建example-service的快照版本,比如example-service-1.0-SNAPSHOT.jar,而example-ui依赖该快照版本。每次example-ui构建时,会优先去远程仓库中查看是否有最新的example-service-1.0-SNAPSHOT.jar,如果有则下载下来使用。即使本地仓库中已经有了example-service-1.0-SNAPSHOT.jar,它也会尝试去远程仓库中查看同名的jar是否是最新的。有的人可能会问,这样不就不能充分利用本地仓库的缓存机制了吗?别着急,Maven比我们想象中的要聪明。在配置Maven的Repository的时候中有个配置项,可以配置对于SNAPSHOT版本向远程仓库中查找的频率。频率共有四种,分别是always、daily、interval、never。当本地仓库中存在需要的依赖项目时,always是每次都去远程仓库查看是否有更新,daily是只在第一次的时候查看是否有更新,当天的其它时候则不会查看;interval允许设置一个分钟为单位的间隔时间,在这个间隔时间内只会去远程仓库中查找一次,never是不会去远程仓库中查找(这种就和正式版本的行为一样了)
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>nexus-public</id>
<url>http://localhost:8081/nexus/content/groups/public/</url>
<releases><enabled>true</enabled></releases>
<!-- daily(默认) always interval:10(10分钟一次) never-->
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
所以一般在开发模式下,我们可以频繁的发布SNAPSHOT版本,以便让其它项目能实时的使用到最新的功能做联调;当版本趋于稳定时,再发布一个正式版本,供正式使用。当然在做正式发布时,也要确保当前项目的依赖项中不包含对任何SNAPSHOT版本的依赖,保证正式版本的稳定性。
二、手动部署jar
# 手动安装本地jar到本地库
mvn install:install-file -Dfile={Path/to/your/xx.jar} -DgroupId=com.oracle -DartifactId=ojdbc6
-Dversion=11.2.0 -Dpackaging=jar
三、生命周期 和 插件
2.1 LifeCycle 概述
1> 生命周期:是指项目构建的生命周期,一个项目构建要经过的各个阶段 ==> PHASE
Maven的生命周期(
LifeCycle
),idea中会显示部分,其实如上显示的是只是maven项目构建时生命周期(lifecycle)的一部分阶段(phase):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EWLvNBja-1569678650726)(mdpic/life.jpg)]
`早期项目构建,方式各不相同,maven抽取了大量的经验,总结了一套规范的项目构建过程,即构建的各个 阶段(phase)
`【pre-clean,clean,post-clean,validate,initialize,generate-sources,process-sources,generate-resources,process-resources,compile,process-classes,generate-test-sources,process-test-sources,generate-test-resources,process-test-resources,test-compile,process-test-classes,test,prepare-package,package,pre-integration-test,integration-test,post-integration-test,verify,install,deploy,pre-site,site,post-site,site-deploy】
2> 生命周期分为3套:【clean周期】、【default周期】、【site周期】
`clean周期:负责清理项目 (清理上次编译的文件)
`default周期:主体周期,负责完成项目构建主体过程
`site周期:建立站点( 生成站点文档,发送站点到服务器 )
3> 每个生命周期都分为一些阶段(phase)
`clean周期:分为【pre-clean、clean、post-clean】3个 phase
: pre-clean负责清理前的准备工作,clean负责清理工作,post-clean负责清理后的善后工作
`default周期:分为【valiedate、initialize、generate-source、...、generate-resources、process-resources、
` compile、...、package、...、install、deploy】多个 phase
:compile负责编译,package负责打包,install负责安装到本地仓库,deploy负责安装到远程仓库
`site周期:分为【pre-site、site、post-site、site-deploy】4个 phase
:site负责生成站点 文档,site-deploy负责将站点发送到服务器
4> 执行方式:mvn phase名
`mvn clean 清理上次编译的文件
`mvn package 打包
`mvn compile 编译
`mvn clean compile 清理并编译(多个phase同时执行)
5> 执行原则:周期独立,阶段顺序依赖
`周期独立:三个周期可以单独执行任意一个,没有顺序依赖,即不执行clean也可以执行default,site亦然。
`: 执行clean周期内的phase对其他周期没任何影响。
`phase顺序依赖:在执行周期内的阶段时是顺序依赖的,如【pre-clean、clean、post-clean】,执行 clean时,其实会依次执行pre-clean和clean;执行post-clean时会一次执行pre-clean,clean,post-clean
`执行compile时,会先依次执行compile之前的所有phase。
`总结:应为一个周期内的多个phase之间是具有逻辑关联的,类似是一个流水线,必须一步接一步的做。
2.2 Plugin 概述
Maven中的生命周期都是抽象的,真正的工作都有插件来完成。比如:
package阶段
由maven-jar-plugin
插件实现
complie阶段
由maven-compiler-plugin
实现。类似于接口和实现类的关系,这样就提供了很好的扩展性。在有限的生命周期上可以定制无限的插件实现。Maven为大多数的阶段,绑定了默认插件。比如 package阶段和compile阶段
生命周期和插件密不可分,密切配合。
每个插件,都有很多目标(
goal
),则如此则有一个对应关系:goal of plugin ==>phase of lifecycle
示例插件如下,插件除了有很多 goal之外,还有自己的前缀,如下的插件前缀是“
dependency
”,其中有goal “tree
”则tree的调用方式为
mvn dependency:tree
【前缀:goal】
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
生命周期与插件绑定,或者说是 阶段和目标绑定。
比如,编译过程:对应的是default周期的compile阶段,而插件 maven-compiler-plugin的compile目标可以完成此任务。
maven为了方便用户使用,已经为一些主要的阶段绑定了目标,比如:
【凡是
maven-xx-plugin
如此模式命名的都是maven官方插件,自定义的插件命名:xx-maven-plugin
】pre-clean 没有目标
clean maven-clean-plugin:clean
post-clean 没有目标
process-resources maven-resources-plugin:resources ( 拷贝主资源文件到输出目录 )
compile maven-compile-plugin:compile
package maven-jar-plugin:jar
install maven-install-plugin:install
deploy maven-deploy-plugin:deploy
执行:mvn compile
输出:
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring01 ---
[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ spring01 ---
[INFO] Changes detected - recompiling the module!
可以看到插件的执行情况,目标和阶段的绑定可见
四、自定义骨架
Maven项目有自己的目录结构,手动创建比较麻烦。
骨架:archetype ==> 约定一套通用的项目目录,帮助快速初始化项目中的目录结构
1. 建web项目
首先创建一个maven web项目,此项目在创建时,可以先用默认的webapp骨架。
并更改目录结构如下:
项目结构: |
---|
<!-- web.xml改动如下 -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
</web-app>
<!-- 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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhj.test</groupId>
<artifactId>webapp_zhj</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<!-- jstl 支持 -->
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<!-- servlet编译环境 -->
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- jsp编译环境 -->
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- mysql驱动 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
2. 生成骨架
在项目目录下执行:
mvn archetype:create-from-project
会产生 “target ”目录。务必删除其中一些无用目录,其中是当前项目的状态,会影响基于此骨架创建的项目。 |
---|
再删除 xxx.iml 文件 |
3. 安装骨架
注意:
在
target > generated-sources > archetype
目录下执行:
mvn install
即可将骨架安装到本地maven仓库
骨架位置,groupid 和 artifactid |
---|
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uG9n6LFw-1569678650738)(mdpic_pro/自定义骨架5.jpg)] |
4. 使用骨架
添加自己的骨架,基于自己的骨架创建项目 |
---|
项目结构: |
5. 自定义骨架移除
如果自定义骨架出现问题,或不再需要,即可如下
C:\Users\zhj\.IntelliJIdea2017.3\system\Maven\Indices\UserArchetypes.xml
其中记录了idea中会显示在骨架列表中的 自定义骨架内容
从中删除自定义骨架配置,在IDEA中就不再出现自定义骨架。
五、安装和部署
5.1 安装
安装指,将项目打包安装到本地仓库中,供本地的其他项目使用
# 打包并安装到本地仓库
mvn install
5.2 部署
部署指,将项目打包安装到远程仓库中,供所有可以访问远程仓库的项目使用
<!--pom.xml: 配置私服仓库地址 -->
<distributionManagement>
<!-- 稳定版本发布地址 -->
<repository>
<id>nexus-public</id>
<url>http://localhost:8081/nexus/content/repositories/releases/</url>
</repository>
<!-- snapshot版本发布地址 -->
<snapshotRepository>
<id>nexus-public</id>
<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<build>
......
</build>
#打包并安装到远程仓库中,远程仓库的地址需要配置在项目的 “pom” 中
mvn deploy
如果
<version>1.0-SNAPSHOT</version>
则自动部署到snapshotRepository
中反之部署到
repository
中
六、filtering
在配置文件中可以定义变量:
# src/main/java/config9/test.properties
# ${xx} 是动态取值
username9=${username}
name9=${name}
url9=${url}
finalName9=${build.finalName}
basedir9=${basedir}
pom中定义 filtering=true,则配置文件中的 ${xx} 会填充数据
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.txt</exclude>
</excludes>
<!-- 导入的配置中如果有 ${xx} 表达式,则解析并填充值 -->
<filtering>true</filtering>
</resource>
pom文件中的标签和properties中的值可以获取
<!-- pom.xml -->
<artifactId>my-web</artifactId>
...
<name>my-web Maven Webapp</name> <!-- ${name} -->
<url>http://www.example.com</url> <!-- ${url} -->
<properties>
...
<username>zhj9</username> <!-- ${username} -->
</properties>
<build>
<finalName>my-web</finalName> <!-- ${build.finalName} -->
...
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.txt</exclude>
</excludes>
<!-- 导入的配置中如果有 ${xx} 表达式,则解析并填充值 -->
<filtering>true</filtering>
</resource>
</build>
七、filter
定义一个properties文件
# src/main/java/config/param.properties
p1=111
p2=222
<build>
...
<!-- 导入外部文件,${xx} 可以从中获取数据 -->
<filters>
<filter>src/main/java/config/param.properties</filter>
</filters>
...
</build>
# 配置文件中获取参数
pp=${p1}
ppp=${p2}
lombok
lombok
插件使用:1> 安装 settings> Plugins 搜索 lombok 安装
2>在
settings > Build,Execution > Compiler > Annotation Processors
中勾选Enable annotation processing
3>项目中导入依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency>
4> 自动生成
set/get 无参构造 有参构造 toString equals hashCode
@Data @AllArgsConstructor @NoArgsConstructor public class Test { private Integer id; private String name; }