本文是开发工具篇第三讲:maven 从入门到实战
Maven是一款服务于Java平台的自动化构建工具。
maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。它包含了一个项目对象模型,一组标准集合,一个项目生命周期,一个依赖管理系统和用来运行定义在生命周期阶段中插件目标的逻辑。当使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自于一组共享的(或自定义的)插件。
优点
缺点
Maven其中一个核心的作用就是管理项目的依赖,引入我们所需的各种jar包等。为了能自动化的解析任何一个Java构件,Maven必须将这些Jar包或者其他资源进行唯一标识,这是管理项目的依赖的基础,也就是我们要说的坐标。包括我们自己开发的项目,也是要通过坐标进行唯一标识的,这样才能才其它项目中进行依赖引用。
maven的坐标通过groupId,artifactId,version唯一标志一个构件。groupId通常为公司或组织名字,artifactId通常为项目名称,versionId为版本号。
Maven的 生命周期:从我们的项目构建,一直到项目发布的这个过程
mvn archetype:generate 创建Maven项目
mvn compile 编译源代码
mvn deploy 发布项目
mvn test-compile 编译测试源代码
mvn test 运行应用程序中的单元测试
mvn site 生成项目相关信息的网站
mvn clean 清除项目目录中的生成结果
mvn package 根据项目生成的jar
mvn install 在本地Repository中安装jar
mvn eclipse:eclipse 生成eclipse项目文件
mvnjetty:run 启动jetty服务
mvntomcat:run 启动tomcat服务
mvn clean package -Dmaven.test.skip=true:清除以前的包后重新打包,跳过测试类
问题:
解决方案:重新升级item-standard项目jar包,然后im项目和ip项目依赖is最新的jar包,即可。
第二种解决方案:可通过dependency的exclusion元素排除掉依赖
最短路径原则
pom文件申明顺序优先
覆写原则
当依赖的范围是 system 的时候,Maven 直接从本地文件系统中解析构件。
与依赖的构件一样,插件也是基于坐标保存在Maven仓库中。在用到插件的时候会先从本地仓库查找插件,如果本地仓库没有则从远程仓库查找插件并下载到本地仓库。与普通的依赖构件不同的是,Maven会区别对待普通依赖的远程仓库与插件的远程仓库。前面提到的配置远程仓库只会对普通的依赖有效果。当Maven需要的插件在本地仓库不存在时是不会去我们以前配置的远程仓库查找插件的,而是需要有专门的插件远程仓库。
常见的做法:
商品中心的做法:
上传到测试环境:
使用的shell脚本,如下所示:
#! bin/sh
echo "********** SNAPSHOT打包上传操作开始 **********"
# deploy的module列表,多个用逗号隔开,将会deploy以下module及其依赖module(含parent)
deployModules=batch-job-api,drds-transaction,item-microservice-agreement-api,item-microservice-api\
,item-microservice-common,item-microservice-external-api
deployParam="-pl $deployModules -am"
# deployParam=
if [[ -n "$deployParam" ]]
then
echo "********** 将会deploy的module及其依赖module(含parent):"
arr=(${deployModules//,/ })
for var in ${arr[@]}
do
echo "${var}"
done
fi
# 获取当前住pom里面的maven version
currentMvnVersion=`awk '/[^<]+<\/version>/{gsub(/|<\/version>/,"",$1);print $1;exit;}' pom.xml`
echo "********** 当前version为:【" $currentMvnVersion "】"
read -p "********** 是否需要变更当前version?不需要请输入n,需要请输入指定version(格式*.*.*-SNAPSHOT): " selectVersion
if [[ $selectVersion == "n" ]]
then
if [[ $currentMvnVersion == *"-RELEASE" ]]
then
echo "********** 格式错误!当前为版本格式为-RELEASE,请输入以-SNAPSHOT结尾的版本号"
else
read -p "********** 是否需要把SNAPSHOT包【"$currentMvnVersion"】上传到dev环境?【y/n】" selectDev
if [ $selectDev = "y" ]
then
echo "********** 开始打包并deploy到dev"
mvn -Pdev clean deploy $deployParam -DskipTests=true -U
else
echo "********** 你没有deploy到dev"
fi
read -p "********** 是否需要把SNAPSHOT包【"$selectVersion"】上传到【真线】环境?【y/n】" selectProd
if [ $selectProd = "y" ]
then
echo "********** 开始打包并deploy到prod"
mvn -P \!dev -Pprod clean deploy -pl $deployModules -am -DskipTests=true -U
else
echo "********** 你没有deploy到prod"
fi
fi
else if [[ $selectVersion == *"-SNAPSHOT" ]]
then
echo "********** 开始更新pom文件 ********** \n"
mvn versions:set -DnewVersion=$selectVersion
echo "********** 更新pom完成 ********** "
read -p "********** 是否需要把SNAPSHOT包【"$selectVersion"】上传到dev环境?【y/n】" selectDev
if [ $selectDev = "y" ]
then
echo "********** 开始打包并deploy到dev"
mvn -Pdev clean deploy $deployParam -DskipTests=true -U
else
echo "********** 你没有deploy到dev"
fi
read -p "********** 是否需要把SNAPSHOT包【"$selectVersion"】上传到【真线】环境?【y/n】" selectProd
if [ $selectProd = "y" ]
then
echo "********** 开始打包并deploy到prod"
mvn -P \!dev -Pprod clean deploy -pl $deployModules -am -DskipTests=true -U
else
echo "********** 你没有deploy到prod"
fi
read -p "********** 是否保存更新后的version【"$selectVersion"】在代码里?【y/n】建议选y " selectRevert
if [ $selectRevert = "y" ]
then
echo "********** 保存更新后的version【"$selectVersion"】在代码里了"
else
mvn versions:set -DnewVersion=$currentMvnVersion
fi
else
echo "********** 格式错误!请输入以-SNAPSHOT结尾的版本号"
fi
fi
echo "********** SNAPSHOT打包上传操作结束 **********"
com.taobao.jstorm
或 com.alibaba.dubbo.register
说明:注意起始版本号必须为:1.0.0,而不是 0.0.1。
反例:仓库内某二方库版本号从 1.0.0.0 开始,一直默默“升级” 成 1.0.0.64,完全失去版本的语义信息。
说明:不依赖 SNAPSHOT 版本是保证应用发布的幂等性。另外,也可以加快编译时的打包构建
说明:在升级时,进行 dependency:resolve
前后信息比对,如果仲裁结果完全不一致,那么通过 dependency:tree
命令,找出差异点,进行
排除 jar 包。
说明:fastjson 给 SCM 定制的版本号: 1.0.0-SCM1。注:请尽可能在应用端来解决类冲突和加载问题,避免随意发布此类定制包。
说明:依赖 springframework-core, -context, -beans
,它们都是同一个版本,可以定义一个变量来保存版本:${spring.version}
,定义依赖的时候,引用该版本。
说明:在本地调试时会使用各子项目指定的版本号,但是合并成一个 war,只能有一个版本号出现在最后的 lib 目录中。曾经出现过线下调试是正确的,发布到线上却出故障的先例。
语句块中,所有版本仲裁放在
语句块中。说明:
里只是声明版本,并不实现引入,因此子项目需要显式的声明依赖,version 和 scope 都读取自父 pom。而
所有声明在主 pom 的
里的依赖都会自动引入, 并默认被所有的子项目继承。
说明: 不稳定指的是提供方无法做到向下兼容,在编译阶段正常,但在运行时产生异常,因此,尽量使用业界稳定的二方工具包
1)精简可控原则:移除一切不必要的 API 和依赖,只包含 Service API、必要的领域模型对象、Utils 类、常量、枚举
等。如果依赖其它二方库,尽量是 provided 引入,让二方库使用者去依赖具体版本号;无 log 具体实现,只依赖日志框架。
2)稳定可追溯原则:每个版本的变化应该被记录,二方库由谁维护,源码在哪里,都需要能方便查到。除非用户主动升级版本,否则公共二方库的行为不应该发生变化。