[Python学习笔记-006] 使用stomp.py校验JMS selector的正确性
了解Jenkins的人都知道,JMS selector是基于SQL92语法实现的,本文将介绍使用stomp.py和ActiveMQ来校验JMS selector的正确性。
Q: 什么是stomp.py?
A: stomp.py是一个基于STOMP(Simple (or Streaming) Text Orientated Messaging Protocol)协议实现的Python的客户端函数库,用来访问诸如ActiveMQ,RabbitMQ之类的消息服务器。
那么,为了使用stomp.py函数库,我们先安装一个ActiveMQ服务。
1. 下载ActiveMQ
$ export TGZBALL=5.15./apache-activemq-5.15.-bin.tar.gz
$ wget https://archive.apache.org/dist/activemq/$TGZBALL
2. 安装ActiveMQ
$ tar zxvf apache-activemq-5.15.-bin.tar.gz
$ sudo mv apache-activemq-5.15. /opt
$ cd /opt
$ sudo ln -s apache-activemq-5.15. activemq
3. 启动ActiveMQ
$ cd /opt/activemq/bin/linux-x86-
$ sudo ./activemq start
Starting ActiveMQ Broker...
注意ActiveMQ默认的监听端口是8161,
$ netstat -an | egrep
tcp6 ::: :::* LISTEN
如果要关闭ActiveMQ,
$ cd /opt/activemq/bin/linux-x86-
$ sudo ./activemq stop
Stopping ActiveMQ Broker...
Stopped ActiveMQ Broker.
一旦ActiveMQ, 我们可以访问其web界面,默认的登录用户名/密码是admin/admin, 例如:

4. 克隆stomp.py的源代码
$ mkdir /var/tmp/sp
$ cd /var/tmp/sp
$ git clone https://github.com/jasonrbriggs/stomp.py.git
5. 准备一个Python脚本foo.py
#!/usr/bin/python3
import sys
import json
import collections
import time
import stomp g_rcvmsg_cnt = 0 # counter of received messages class MyListener(stomp.ConnectionListener):
def on_error(self, headers, message):
global g_rcvmsg_cnt
g_rcvmsg_cnt = 0 print('Oops!! received an error "%s"' % message) def on_message(self, headers, message):
global g_rcvmsg_cnt
g_rcvmsg_cnt += 1 print('Bingo! received a message, rcv_cnt = %d' % g_rcvmsg_cnt)
print('o message headers :\n%s' % json.dumps(headers, indent=4))
print('o message body : %s\n' % message) def validate():
if g_rcvmsg_cnt > 0:
print(">>> PASS")
return 0
else:
print(">>> FAIL")
return 1 def usage(argv0):
sys.stderr.write("Usage: %s <JMS selector> <message headers>\n" % argv0) def main(argc, argv):
if argc != 3:
usage(argv[0])
return 1 jms_selector = argv[1]
msg_headers = argv[2] d_sub_headers = dict()
d_sub_headers['selector'] = jms_selector
print('>>> SUB HEADERS', d_sub_headers) d_snd_headers = json.loads(msg_headers,
object_pairs_hook=collections.OrderedDict)
print('>>> SND HEADERS', d_snd_headers)
print() conn = stomp.Connection()
conn.set_listener('', MyListener())
conn.start() # Note default user/password of ActiveMQ is admin/admin
user = 'admin'
password = 'admin'
conn.connect(user, password, wait=True) conn.subscribe(destination='/queue/test', id=1, ack='auto',
headers=d_sub_headers) s_body = ' '.join(argv[1:])
conn.send(destination='/queue/test', body=s_body, headers=d_snd_headers) time.sleep(2)
conn.disconnect() return validate() if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))
在上面的代码中,
67 conn.subscribe(destination='/queue/test', id=1, ack='auto',
68 headers=d_sub_headers)
L67-68: 根据用户输入的JMS selector进行订阅,
71 conn.send(destination='/queue/test', body=s_body, headers=d_snd_headers)
L71: 将用户输入的JSON文本作为消息头发送。
6. 使用foo.py测试JMS selector
hdan$ export PYTHONPATH=/var/tmp/sp/stomp.py:$PYTHONPATH
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "tag", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'tag'), ('foo', )]) >>> FAIL
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "Tag", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'Tag'), ('foo', )]) Bingo! received a message, rcv_cnt =
o message headers :
{
"subscription": "",
"content-length": "",
"timestamp": "",
"destination": "/queue/test",
"message-id": "ID:huangdan-40431-1550639739706-3:131:-1:1:1",
"foo": "",
"Type": "Tag",
"expires": "",
"priority": ""
}
o message body : Type LIKE 'Tag%' {"Type": "Tag", "foo": } >>> PASS
hdan$
hdan$ ./foo.py "Type LIKE 'Tag%'" '{"Type": "Tag123", "foo": 123}'
>>> SUB HEADERS {'selector': "Type LIKE 'Tag%'"}
>>> SND HEADERS OrderedDict([('Type', 'Tag123'), ('foo', )]) Bingo! received a message, rcv_cnt =
o message headers :
{
"message-id": "ID:huangdan-40431-1550639739706-3:132:-1:1:1",
"destination": "/queue/test",
"timestamp": "",
"expires": "",
"priority": "",
"subscription": "",
"content-length": "",
"foo": "",
"Type": "Tag123"
}
o message body : Type LIKE 'Tag%' {"Type": "Tag123", "foo": } >>> PASS
hdan$
附录: SQL92的LIKE操作符 (来源戳这里)
A like string consists of a set of characters where the percent (%),
underscore (_) and escape character, such as backslash (\) are
treated differently. * The percent (%) matches any number of characters including
zero characters
* The underscore (_) matches only one character e.g.
+-------------+---------------------------------------+
| Like string | Meaning |
+-------------+---------------------------------------+
| Topic% | All strings starting with Topic |
| %/abc/% | Any string containing /abc/ |
| Name_ | Any string starting with Name and |
| | having exactly one more character |
| Name\_2 | Only the string Name_2 |
+-------------+---------------------------------------+
参考资料:
[Python学习笔记-006] 使用stomp.py校验JMS selector的正确性的更多相关文章
- Python学习笔记006
		算术运算符 加+ 减- 乘* 除/ 整除//,地板除 取余% 指数** ()区分 优先级 比较运算符 赋值 = 等于 == 不等于 != 大于等于 >= 小于等于 <= 
- Python学习笔记:装饰器
		Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ... 
- VS2013中Python学习笔记[Django Web的第一个网页]
		前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ... 
- python学习笔记之module && package
		个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ... 
- python学习笔记(六)文件夹遍历,异常处理
		python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ... 
- python学习笔记--Django入门四 管理站点--二
		接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ... 
- python学习笔记--Django入门0 安装dangjo
		经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ... 
- Python学习笔记(十三)
		Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ... 
- Python学习笔记(十一)
		Python学习笔记(十一): 生成器,迭代器回顾 模块 作业-计算器 1. 生成器,迭代器回顾 1. 列表生成式:[x for x in range(10)] 2. 生成器 (generator o ... 
随机推荐
- (记忆化搜索)数塔 (zznu 1271)
			http://acm.zznu.edu.cn/problem.php?id=1271 1271: 数塔 时间限制: 1 Sec 内存限制: 128 MB提交: 109 解决: 78[提交][状态] ... 
- SSM_CRUD新手练习(6)分页后台控制器编写
			经过测试基础环境已经搭建好了,现在我们开始编写CRUD. 我们来看一下查询的逻辑该怎么写: 1.访问index.jsp页面 2.index.jsp页面发送查询员工的请求 3.EmployeeContr ... 
- web-day16
			第16章WEB16-Listener&Filter篇 今日任务 使用过滤器完成自动登录的案例 使用过滤器统一网站的字符集编码 教学导航 教学目标 了解常见的监听器 理解过滤器的生命周期 能够使 ... 
- bootstrap 图片切换
			<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ... 
- EBS中 EXCEL 格式报表输出的公用API
			http://blog.itpub.net/10359218/viewspace-752601/ 最近的项目上写了一个公用的API,很久以前就用EXCEL发布过报表,但从没想过写API来简化... ... 
- 实验4 IIC通讯与EEPROM接口
			1. 用C语言编程,利用定时器产生一个0~99秒变化的秒表,并且显示在数码管上,每过一秒将这个变化写入实验板上AT24C02,当关闭实验板电源,并再次打开实验板电源时,单片机从AT24C0 ... 
- python threading模块
			#coding=utf-8 import threading from time import ctime,sleep def music(func): for i in range(2): prin ... 
- python常用代码片段
			目录 Python3常用 文件处理 json处理 log日志 argparse使用 INIparser Python3常用 文件处理 class BaseMethod: @staticmethod d ... 
- C# 中 DataTable转换成IList
			在用C#作开发的时候经常要把DataTable转换成IList:操作DataTable比较麻烦,把DataTable转换成IList,以对象实体作为IList的元素,操作起来就非常方便. 注意:实体的 ... 
- vscode 学习笔记 —— 重构
			一.vscode 自带 1.提取变量 2.提取方法 上面都是通过选中文本后出现的小灯泡操作的: 3.全局替换(多个文件中的)某个变量 选中变量按 F2,输入完成后按回车 二.vscode 插件 js- ... 
