一、JMS
JMS(Java Message Service)是 Java 平台中的一种消息通信标准,它允许应用程序之间通过消息进行异步通信,是 企业级集成和松耦合架构中常用的技术。
1、JMS 的核心概念
1. 消息模型
JMS 定义了两种消息模型:
(1)点对点(Point-to-Point, P2P)
-
使用 Queue(队列) 实现消息传递。
-
特点:
-
一个消息只能被一个消费者接收。
-
有发送者(Sender)、接收者(Receiver)、队列(Queue)。
-
常用于任务分发,如打印任务、订单处理队列等。
-
(2)发布/订阅(Publish/Subscribe, Pub/Sub)
-
使用 Topic(主题)。
-
特点:
-
一个消息可以被多个订阅者接收。
-
有发布者(Publisher)、订阅者(Subscriber)、主题(Topic)。
-
常用于广播通知,如股票行情、新闻推送等。
-
2. JMS 元素
元素 | 说明 |
---|---|
ConnectionFactory | 创建连接对象的工厂,WAS 中由管理员配置 |
Destination | 消息目的地,Queue 或 Topic |
Connection | 与消息服务器的连接 |
Session | 通过连接创建的会话,线程不安全,一般每个线程一个 |
MessageProducer | 消息发送者,用于发送消息 |
MessageConsumer | 消息接收者 |
Message | 消息对象,如 TextMessage、ObjectMessage、MapMessage 等 |
2、JMS 消息类型
类型 | 用途说明 |
---|---|
TextMessage | 发送字符串消息(如 JSON、XML) |
ObjectMessage | 发送 Java 序列化对象 |
BytesMessage | 发送字节流 |
MapMessage | 键值对形式的数据结构 |
StreamMessage | 基于数据流的消息 |
3、JMS 与 WebSphere Application Server(WAS)的关系
WAS 内置对 JMS 的支持,允许配置和管理消息服务器、队列、主题等,主要用于:
-
企业应用异步解耦
-
消息驱动 Bean(MDB)处理异步逻辑
-
和 WebSphere MQ、ActiveMQ、SIB 等整合
在 WAS 中配置 JMS:
路径:资源 → JMS → 队列连接工厂 / 队列 / 主题 / 激活规范
配置步骤:
-
创建连接工厂(Connection Factory)
-
创建目标(Queue 或 Topic)
-
创建激活规范(用于 MDB)
-
绑定 JNDI 名称,供应用查找使用
4、JMS 编程模型(Java 代码示例)
Context ctx = new InitialContext();
ConnectionFactory factory = (ConnectionFactory) ctx.lookup("jms/ConnectionFactory");
Queue queue = (Queue) ctx.lookup("jms/Queue");
Connection conn = factory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("Hello JMS!");
producer.send(message);
5、与 IBM BAW 的整合
IBM BAW 通过 Service Integration Bus (SIBus) 内部集成了 JMS 实现,可以让流程或服务异步:
-
发送消息给外部系统(如调用 MQ)
-
监听消息队列并启动流程
-
与 MDB 协同处理业务逻辑
BAW 中相关的集成点有:
-
异步消息发送服务
-
JMS 触发器
-
SIB 消息引擎配置
6、JMS 应用场景
场景 | 说明 |
---|---|
订单处理异步入库 | 系统接收订单立即返回响应,入库任务通过 JMS 异步处理 |
系统日志异步写入 | 系统日志通过 JMS 分发给日志服务处理 |
支付系统通知 | 支付完成消息发送到多个系统(发货、积分、短信) |
消息驱动工作流触发 | 外部系统将消息发到 BAW 队列,由流程自动处理 |
7、与 Kafka 的比较
特性 | JMS(如 MQ、ActiveMQ) | Kafka |
---|---|---|
标准 | Java EE 标准 | Kafka 专有 |
消息模型 | P2P 和 Pub/Sub | 类似 Pub/Sub |
持久性 | 高 | 高(基于日志存储) |
性能 | 中 | 极高 |
事务支持 | 好 | 较弱(需单独设置) |
应用场景 | 企业应用、流程驱动 | 大数据、日志收集、实时分析 |
好的,我们继续深入讲解 JMS,重点在实际 WAS 配置 + Java 应用使用 + 和 BAW 结合的场景,分为以下几个部分:
8、JMS 在 WAS 中的配置实操示范
WAS(WebSphere Application Server)支持通过管理控制台配置 JMS 资源,通常用于集成 IBM MQ、ActiveMQ 或 WebSphere 内部的 SIB(Service Integration Bus)。下面以配置 内建 SIB JMS 队列 为例。
1. 启用服务集成总线(SIBus)
-
进入 WAS 控制台
-
路径:服务集成 > 总线 > 创建
-
名称:
SIBBus1
-
保持默认设置
-
2. 创建消息引擎
-
路径:服务集成 > 总线 > SIBBus1 > 代理(Messaging Engine)
-
添加一个代理,选择你的节点
-
选择持久化消息存储位置(文件系统或数据库)
-
3. 创建 JMS 目的地
-
路径:资源 > JMS > 队列
-
队列名称:
MyQueue
-
JNDI 名称:
jms/MyQueue
-
关联 SIB 总线和消息引擎
-
4. 创建 JMS 连接工厂
-
路径:资源 > JMS > 队列连接工厂
-
名称:
MyQueueCF
-
JNDI 名称:
jms/MyQueueCF
-
选择同一个总线
-
5. 创建激活规范(用于 MDB)
-
路径:资源 > JMS > 激活规范
-
名称:
MyQueueAS
-
JNDI 名称:
eis/MyQueueAS
-
选择 SIB 总线和队列
-
9、Java 应用中使用 JMS(示例代码)
使用 WAS 中的资源,我们可以在 Java EE 或 Spring 应用中使用 JMS 发送和接收消息。
1. 发送消息
@Resource(name = "jms/MyQueueCF")
private ConnectionFactory connectionFactory;
@Resource(name = "jms/MyQueue")
private Queue queue;
public void sendMessage(String msgContent) {
try (Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue)) {
TextMessage msg = session.createTextMessage(msgContent);
producer.send(msg);
} catch (JMSException e) {
e.printStackTrace();
}
}
2. 接收消息(同步方式)
public void receiveMessage() {
try (Connection conn = connectionFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer consumer = session.createConsumer(queue)) {
conn.start();
Message message = consumer.receive(10000); // 10秒超时
if (message instanceof TextMessage) {
System.out.println("Received: " + ((TextMessage) message).getText());
}
} catch (JMSException e) {
e.printStackTrace();
}
}
10、结合 BAW 使用 JMS 的方式
场景 1:BAW 流程结束时发送 JMS 消息
-
在 BAW 的集成服务中使用
Java 组件
或Web Service
调用上面的消息发送逻辑 -
示例用途:流程结束后发送消息通知财务系统入账
场景 2:通过 JMS 触发 BAW 流程
-
在 WAS 中配置 MDB(Message-Driven Bean)监听队列
-
接收到消息后调用 BAW REST API 启动流程或处理任务
11、集成建议与注意事项
建议 | 说明 |
---|---|
推荐使用 JNDI 绑定 | 避免硬编码队列名称与工厂名称 |
启用持久化存储 | 防止消息丢失 |
使用 MDB 消费 | 保证异步高并发处理能力 |
配置死信队列 | 捕捉处理失败的消息 |
开启连接池 | 提高性能(WAS 中默认启用) |
12、补充:JMS 与 Spring Boot 集成
如果你使用的是 Spring Boot + WAS/JMS,可以通过如下方式配置:
spring:
jms:
jndi-name: java:comp/env/jms/MyQueueCF
使用 Spring JmsTemplate:
@Autowired
private JmsTemplate jmsTemplate;
public void send(String message) {
jmsTemplate.convertAndSend("jms/MyQueue", message);
}
二、BAW 调用 JMS 的集成流程样例
下面是一个完整的 IBM BAW 调用 JMS 的集成流程样例,包括:
-
BAW 流程建模
-
WAS 中 JMS 配置
-
Java 服务集成实现
-
流程与服务的连接
-
测试和验证方法
1、业务场景描述
流程名称:发送消息流程(SendJMSMessageProcess)
目标:业务流程中调用一个 Java 集成服务,向指定 JMS 队列发送消息,消息将由下游系统消费。
2、WAS 中配置 JMS(使用内建 SIB)
1. 创建服务集成总线(SIB)
-
控制台路径:服务集成 > 总线 > 新建
-
名称:
BAWBus
-
2. 创建消息引擎(消息代理)
-
绑定节点/服务器,用于运行 SIBus 代理
3. 创建队列目的地
-
控制台路径:资源 > JMS > 队列
-
队列名称:
MyQueue
-
JNDI:
jms/MyQueue
-
指定 SIBus、代理名称
-
4. 创建连接工厂
-
路径:资源 > JMS > 队列连接工厂
-
名称:
MyQueueCF
-
JNDI:
jms/MyQueueCF
-
同样绑定 SIBus
-
3、开发 Java 集成服务(调用 JMS)
1. Java 代码(Maven 项目)
import javax.annotation.Resource;
import javax.jms.*;
import javax.naming.InitialContext;
public class JMSSender {
@Resource(name = "jms/MyQueueCF")
private ConnectionFactory connectionFactory;
@Resource(name = "jms/MyQueue")
private Queue queue;
public void sendMessage(String content) throws Exception {
try (Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage(content);
producer.send(message);
}
}
}
打包成 JAR 后部署到 BAW 支持的 classpath(例如共享库),或者封装为 EJB/JAX 服务。
4、BAW 中配置服务并建模
1. 在 Process Designer 中创建服务
-
类型:集成服务(Java Integration Service)
-
输入参数:
messageContent
(String) -
实现方式:调用
JMSSender.sendMessage(messageContent)
2. 创建业务流程
-
添加一个用户任务输入参数
-
调用上述集成服务节点发送消息
-
添加结束事件
3. 配置绑定与依赖
-
确保 WAS 的 classloader 包含 JMS Java 逻辑类
-
BAW 配置服务绑定至 JNDI 名称(WAS 控制台设置或 Server.xml)
5、测试方案
方法 1:在 BAW 流程中输入一条消息 → 队列中收到消息
-
使用 BAW Process Portal 启动流程,输入消息文本
-
使用 JMS 客户端(如 WebSphere MQ Explorer)监听队列
方法 2:配置 MDB 消费并打印日志
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/MyQueue"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class MessageConsumerMDB implements MessageListener {
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println("Received: " + ((TextMessage) message).getText());
} catch (JMSException e) { e.printStackTrace(); }
}
}
}
6、部署与验证说明文档(概要)
步骤 | 内容 |
---|---|
第一步 | 在 WAS 创建 SIB、队列、工厂资源 |
第二步 | 编写 Java 类并部署至共享库或包装成 EJB |
第三步 | 在 BAW 创建集成服务并建模流程 |
第四步 | 使用 Process Portal 发起流程测试 |
第五步 | 验证队列中是否收到消息,或通过 MDB 输出日志 |
7、BPMN 流程模板
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns="http://example.com/bpmn"
targetNamespace="http://example.com/bpmn">
<process id="SendJMSMessageProcess" name="发送JMS消息流程" isExecutable="true">
<startEvent id="StartEvent_1" name="开始"/>
<userTask id="UserTask_Input" name="输入消息内容">
<incoming>Flow_1</incoming>
<outgoing>Flow_2</outgoing>
</userTask>
<sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_Input"/>
<serviceTask id="ServiceTask_SendJMS" name="发送JMS消息">
<extensionElements>
<!-- 实现细节,如Java实现类绑定或调用的集成服务名 -->
</extensionElements>
<incoming>Flow_2</incoming>
<outgoing>Flow_3</outgoing>
</serviceTask>
<sequenceFlow id="Flow_2" sourceRef="UserTask_Input" targetRef="ServiceTask_SendJMS"/>
<endEvent id="EndEvent_1" name="结束"/>
<sequenceFlow id="Flow_3" sourceRef="ServiceTask_SendJMS" targetRef="EndEvent_1"/>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_SendJMS">
<bpmndi:BPMNPlane id="BPMNPlane_SendJMS" bpmnElement="SendJMSMessageProcess">
<!-- 图形布局信息略,可由 BAW Process Designer 自动生成 -->
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
上面是一个基础的 BPMN 流程模板,名为 发送JMS消息流程(SendJMSMessageProcess)。该流程包括:
-
开始事件
-
用户任务:输入消息内容
-
服务任务:发送 JMS 消息(将绑定集成服务)
-
结束事件
你可以将该模板导入 IBM BAW Process Designer(或转换为 .twx
文件进行导入)。
三、BAW中调用JMS服务并推送审批提醒至企业微信示例
1、场景说明
在企业的流程自动化系统中,审批流程的每个节点希望在完成后自动发送审批通知至企业微信(或其他 IM 工具),提醒下一个处理人或相关人员。此通知通过 JMS 中间件推送到消息服务网关,然后转发到企业微信。
2、流程模型设计(BPMN)
流程名:SendJMSMessageProcess
核心结构:
-
开始节点(Start)
-
用户任务(User Task: 填写审批信息)
-
系统服务任务(Service Task: 调用 JMS 推送消息)
-
结束节点(End)
3、输入输出变量配置(流程级)
在 BAW 的流程设计器中,为流程添加以下变量:
变量名 | 类型 | 用途 | 输入/输出 |
---|---|---|---|
messageContent | String | 审批通知消息内容 | 输入 |
jmsStatus | String | JMS 推送成功/失败的状态 | 输出 |
4、服务绑定(服务任务)
服务任务名称:Send JMS to WeChat
服务类型:
-
类型:集成服务
-
实现方式:调用 Java 组件或 Java 集成服务
接口参数定义:
参数名 | 类型 | 方向 |
---|---|---|
messageContent | String | 输入 |
jmsStatus | String | 输出 |
绑定服务实现(方法 1:Java 组件):
假设已创建 Java 类:
package com.example.jms;
import javax.jms.*;
import javax.naming.*;
public class WeChatJMSPublisher {
public String sendMessage(String messageContent) throws Exception {
InitialContext ctx = new InitialContext();
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("jms/WeChatConnectionFactory");
Queue queue = (Queue) ctx.lookup("jms/WeChatQueue");
QueueConnection conn = factory.createQueueConnection();
QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
TextMessage message = session.createTextMessage();
message.setText(messageContent);
sender.send(message);
sender.close();
session.close();
conn.close();
return "SUCCESS";
}
}
绑定方法可通过 Java 集成服务或 EJB 服务引用该类。
5、WAS JMS 配置说明
1.JMS 连接工厂:
-
名称:
jms/WeChatConnectionFactory
-
类型:QueueConnectionFactory
-
提供者类型:默认 SIBus 或外部 MQ 提供者
2.目标目的地(Destination):
-
名称:
jms/WeChatQueue
-
类型:Queue
3.JNDI 映射:确保在 WAS 中配置了 JNDI 名称和绑定。
6、企业微信 Webhook 示例
发送格式为:
{
"msgtype": "text",
"text": {
"content": "【审批提醒】张三已完成任务:请李四审批。"
}
}
如果 JMS 后端是一个支持 HTTP 网关服务(如 Spring Boot + Webhook 转发),则可按如下方式进行后续推送。
7、流程使用示例
用户在用户任务节点填写如下信息:
-
审批内容:
任务123审批通过,请处理下一个步骤。
提交后进入服务任务节点,调用 JMS 发送内容到 jms/WeChatQueue
,由监听器转发至微信。
8、错误处理建议
-
在服务任务中加入错误路径(例如 JMS 发送失败,走报警流程)
-
添加
try-catch
环绕服务逻辑 -
可在
jmsStatus
输出结果中返回错误详情
9、可选增强功能
-
节点后自动触发消息通知(监听流程变量变化)
-
消息内容模板化(结合业务数据与审批路径)
-
支持多平台提醒(微信、钉钉、邮件等)
-
异步推送与失败重试机制
10、完整示例
以下是一个完整的示例,包括:
-
Java JMS 消息发送类代码
-
IBM BAW 集成方式
-
如何将该 Java 类导入 BAW(手动导入)
-
消息示例及企业微信推送结构
1.Java JMS 消息发送类代码(独立组件)
你可以将以下代码打成 .jar
包导入到 BAW:
package com.example.jms;
import javax.jms.*;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class WeChatJMSPublisher {
public String sendMessage(String messageContent) {
try {
InitialContext ctx = new InitialContext();
// JNDI 名称需与你在 WAS 中配置的保持一致
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("jms/WeChatConnectionFactory");
Queue queue = (Queue) ctx.lookup("jms/WeChatQueue");
QueueConnection conn = factory.createQueueConnection();
QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
TextMessage message = session.createTextMessage();
message.setText(messageContent);
sender.send(message);
sender.close();
session.close();
conn.close();
return "SUCCESS";
} catch (NamingException | JMSException e) {
e.printStackTrace();
return "FAIL: " + e.getMessage();
}
}
}
2.打包为 .jar
文件(步骤)
使用命令行打包:
-
将上面代码保存为
WeChatJMSPublisher.java
,放入文件夹路径:src/com/example/jms/WeChatJMSPublisher.java
-
编译:
javac -d out src/com/example/jms/WeChatJMSPublisher.java
-
打包为 JAR:
jar cf WeChatJMSPublisher.jar -C out .
3.导入到 IBM BAW 环境中
1. 上传到 Process App 的 “实现” 目录:
-
打开 BAW Process Designer
-
在左侧导航栏中点击 “实现”
-
选择 “外部实现” → “添加”
-
上传
WeChatJMSPublisher.jar
2. 创建 Java 集成服务:
-
类型:Java 集成服务
-
类名:
com.example.jms.WeChatJMSPublisher
-
方法名:
sendMessage
-
输入参数:
String messageContent
-
输出参数:
String
,作为jmsStatus
返回
4.在流程中使用该服务
-
创建一个服务任务,绑定上面 Java 集成服务。
-
配置输入变量
messageContent
,如:【审批通知】用户 张三 已完成审批任务,请 李四 查看。
-
将输出绑定到变量
jmsStatus
,用于记录状态或走错误路径。
5.企业微信接收端建议设计
若你使用一个 HTTP Gateway 转发 JMS 消息至微信:
示例 Java 后端监听器(Spring):
@RestController
@RequestMapping("/jms/wechat")
public class WeChatReceiverController {
@PostMapping("/push")
public ResponseEntity<?> pushToWeChat(@RequestBody String message) {
// 调用企业微信 Webhook 推送
String webhook = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx";
RestTemplate restTemplate = new RestTemplate();
Map<String, Object> payload = new HashMap<>();
payload.put("msgtype", "text");
Map<String, String> text = new HashMap<>();
text.put("content", message);
payload.put("text", text);
ResponseEntity<String> response = restTemplate.postForEntity(webhook, payload, String.class);
return ResponseEntity.ok("Pushed to WeChat: " + response.getBody());
}
}
6.调试建议
-
在 WAS 控制台中启用 JMS Trace 级别日志。
-
BAW 中流程服务任务绑定异常路径用于捕获错误。
-
使用 Service Integration Bus 控制台监控消息流动。