maven version 来进行版本管理。主要还是在分布式项目中模块众多的场景中使用,毕竟各个模块对外的版本需要保持统一。

versions-maven-plugin 。 具体用法以后有机会在赘述。batfhmerge.sh 和 batchgrade.sh 就搞定了。SNAPSHOT 版本来保证别人拉取到你最新的功能代码,但是有些公司会要求使用非 SNAPSHOT 版本进行管理也就是正式版本,这样做的好处就是容易找到之前的版本代码功能。# 该脚本主要用来升级发包期间修改各服务版本
FILEPATH=$1
GROUPID=$2
ARTIFACTID=$3
FILENAME=$4
while getopts ":f:g:a:" opt
do
case $opt in
f)
FILENAME=$OPTARG
echo "您输入的文件配置:$FILENAME"
;;
g)
GROUPID=$OPTARG
echo "您输入的groupid配置:$GROUPID"
;;
a)
ARTIFACTID=$OPTARG
echo "您输入的artifactid配置:$ARTIFACTID"
;;
ff)
FILENAME=$OPTARG
echo "您输入的带修改文件为:$FILENAME"
;;
?)
echo "未知参数"
exit 1;;
esac
done
echo "开始修改版本号"
NEWCONTENT=1.2.5.$(date +%Y%m%d)
LINE=`cat ${FILENAME} | grep -n -A 1 '' "${GROUPID}"'<\/groupId>'| grep -n '<artifactId>'"${ARTIFACTID}"'<\/artifactId>' | awk -F "[:-]+" '{print $2}'`
echo 具体行号:$LINE
if [[ -z $LINE ]]
then
echo 未匹配
exit
fi
VERSIONOLDCONTENT=`sed -n ''"$((LINE+1))"'p' ${FILENAME}| grep '[0-9a-zA-Z\.-]+' -Eo | sed -n '2p'`
echo ${VERSIONOLDCONTENT}
#gsed -i ''"$((LINE+1))"'c\'"${NEWCONTENT}"'' pom.xml
sed -i "" ''"$((LINE+1))"'s/'"${VERSIONOLDCONTENT}"'/'"${NEWCONTENT}"'/' ${FILENAME}
groupId 和 artifactId ,最后确定好 version 对应的行号将最新的日期后缀版本进行填充进去。SED 进行操作,那就需要先获取到以前的旧版本,然后进行替换操作。pom.xml 文件他是一个 XML 格式的文件, XML=eXtensible Markup Language 。即是一种可扩展的标记语言。它与 JSON 一样主要用来存储和传输数据。在之前的Springboot章节中我们也实现了如何实现接口传递 XML 数据结构。常见的 XML 编程接口有 DOM 和 SAX,这两种接口处理 XML 文件的方式不同,当然使用场合也不同。
Python 有三种方法解析 XML,SAX,DOM,以及 ElementTree:
### 1.SAX (simple API for XML )
Python 标准库包含 SAX 解析器,SAX 用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。
### 2.DOM(Document Object Model)
将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML。
### 3.ElementTree(元素树)
ElementTree 。ElementTree 在 python3中已经作为标准库存在了,所以这里不需要我们额外的安装。基于事件和基于文档的APID来解析XML,可以使用XPath表达式搜索已解析的文件,具有对文档的增删改查的功能,该方式需要注意大xml文件,因为是一次性加载到内存,所以如果是大xml文件,不推荐使用该模块解析,应该使用sax方式
- 1
pom.xml 文件不会很大的。ElementTree 通过 XPath 进行节点选择,所以关于xml 节点查找我们可以参考 xpath 语法即可。<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.0modelVersion>
<groupId>com.github.zxhTomgroupId>
<artifactId>bottomartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>bottomname>
<url>http://maven.apache.orgurl>
<description>最底层的繁琐封装description>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<log4j2.version>2.10.0log4j2.version>
properties>
<dependencies>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.7version>
dependency>
<dependency>
<groupId>commons-collectionsgroupId>
<artifactId>commons-collectionsartifactId>
<version>3.2.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.28version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>${log4j2.version}version>
dependency>
<dependency>
<groupId>org.reflectionsgroupId>
<artifactId>reflectionsartifactId>
<version>0.9.10version>
dependency>
dependencies>
project>
pom.xml 摘自于 com.github.zxhTom 的 bottom 项目中。里面的恰好出现了注释,方便我们后期测试。import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
print(tree)

ET.parse 即可解析出来 xml 。import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
# 根据tree进行遍历
for node in tree.iter():
print(node.tag)

import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
# tree遍历
for node in tree.findall('.//dependency'):
print(node.tag)
pom.xml 中的命名空间,在跟节点 project 标签中设置的xmlns 属性。至于为什么需要这个呢?每个xml 标签内容都是自定义的,比如你可以将dependency用来做版本号的作用,只要你自己解析的时候注意就行了。而maven中将dependency作为引入坐标的概念,每个人的想法不一,所以引入命名空间,在指定的命名空间中标签的作用是唯一的,这就是 xmlns 存在的意义。import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
# tree遍历
for node in tree.findall('.//{http://maven.apache.org/POM/4.0.0}dependency'):
print(node.tag)

通过上面的内容我们知道在定位节点时候需要加入命名空间。
首先我们知道 com.alibaba.fastjson 的版本号是 1.2.28
import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
# tree遍历
for node in tree.findall('.//{http://maven.apache.org/POM/4.0.0}dependency'):
groupIdNode=node.find('.{http://maven.apache.org/POM/4.0.0}groupId')
artifactNode=node.find('.{http://maven.apache.org/POM/4.0.0}artifactId')
if(artifactNode.text=='fastjson' and groupIdNode.text=='com.alibaba'):
print(node.find('.{http://maven.apache.org/POM/4.0.0}version').text)
python3 upgrade.py 即可打印出 1.2.28 。com.alibaba.fastjson的版本号升级为1.2.29 吧。import xml.etree.ElementTree as ET
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)
# tree遍历
for node in tree.findall('.//{http://maven.apache.org/POM/4.0.0}dependency'):
groupIdNode=node.find('.{http://maven.apache.org/POM/4.0.0}groupId')
artifactNode=node.find('.{http://maven.apache.org/POM/4.0.0}artifactId')
if(artifactNode.text=='fastjson' and groupIdNode.text=='com.alibaba'):
node.find('.{http://maven.apache.org/POM/4.0.0}version').text='1.2.29'
tree.write('pom.xml')
pom.xml 好像并不是只改了version标签的内容。

API追踪
def write(self, file_or_filename,
encoding=None,
xml_declaration=None,
default_namespace=None,
method=None, *,
short_empty_elements=True):
/Lib/xml/etree/ElementTree.py 源码就能够看到在写会 xml 文件的时候我们一共有7个参数可选,其中第一个self 没啥好说的。| 属性 | 作用 |
|---|---|
| file_or_filename | 文件 |
| encoding | 输出的编码格式;默认US-ASCII |
| xml_declaration | 将XML声明添加到文件中: True添加;False不添加;None在非US-ASCII 或 UTF-8 或 Unicode时添加; 默认None |
| default_namespace | 默认的命名空间 |
| method | xml、 html 、 text。默认 xml |
| short_empty_elements | 空内容的标签时的处理 |
tree.write('pom.xml',default_namespace='http://maven.apache.org/POM/4.0.0')
UTF-8 的。tree.write('pom.xml',default_namespace='http://maven.apache.org/POM/4.0.0',encoding='UTF-8')
xml_declaration 就是控制是否生成标准申明的。
with open('pom.xml', 'tr', encoding='utf-8') as rf:
tree = ET.parse(rf)




TreeBuilder 进行渲染的,其中 CommentHandler 就是 TreeBuilder.comment 进行的。那么我们继续查看下 TreeBuilder 的源码来查看为什么默认的 parser 没有保留下注释。
_comment_factory , 而这个类就是产生 Comment 。 因为insert_comments=False , 所以默认的TreeBuilder对于注释只会产生一个空的Comment对象,所以我们通过ET.write出来的pom.xml中关于注释部分就是空白代替,就是因为这个原因。class CommentedTreeBuilder (ET.TreeBuilder):
def comment(self,data):
self.start(ET.Comment,{})
self.data(data)
self.end(ET.Comment)
上述代码类似于 Java中继承了 TreeBuilder 并且重写了 comment方法。主要的逻辑就是开头一个注释标签属性为空,结尾是一个注释标签结尾,中间的内容是我们注释的内容,所以综上就是保留下来注释。
重写了类之后我们还需要在ET中指定我们自定义的TreeBuilder 。
parser = ET.XMLParser(target=CommentedTreeBuilder())
tree = ET.parse(xml_path,parser=parser)

# tree遍历
for node in tree.findall('.//{http://maven.apache.org/POM/4.0.0}dependency'):
print(node.tag)
ns = {'real_mvn': 'http://maven.apache.org/POM/4.0.0',
'vistual': 'http://characters.zxhtom.com'}
# tree遍历
for node in tree.findall('.//real_mvn:dependency',ns):
print(node.tag)
| 文件 | dependency数量 |
|---|---|
| knife4j-spring-ui-1.9.6.pom | 0 |
| spring-context-support-1.0.6.pom | 3 |
| spring-core-5.1.7.RELEASE.pom | 10 |
| springfox-swagger-common-3.0.0.pom | 11 |