0

0

SOAP与消息中间件?ActiveMQ集成示例?

小老鼠

小老鼠

发布时间:2025-08-27 13:12:02

|

710人浏览过

|

来源于php中文网

原创

SOAP与消息中间件结合,可实现异步解耦和可靠传输。通过将SOAP消息作为有效载荷封装进ActiveMQ的JMS消息中,系统能在高并发下实现削峰填谷、提升容错能力。发送方将SOAP请求序列化后发送至队列,接收方异步消费并处理,再通过响应队列返回结果。该模式适用于对实时性要求不高但需高可靠性的场景,如订单处理。Spring Boot集成ActiveMQ时,使用JAXB进行XML绑定,JmsTemplate发送消息,@JmsListener接收消息,实现SOAP over JMS的轻量级异步通信。尽管增加了幂等、顺序等复杂性,但整体提升了系统韧性与可扩展性。

soap与消息中间件?activemq集成示例?

SOAP和消息中间件,乍一听像是分属两个不同领域的技术概念,一个关乎服务接口的定义与消息的严谨格式,另一个则侧重于消息的可靠传输、异步解耦和削峰填谷。但深入思考,它们并非互不相干,反而能在特定场景下形成一种互补,尤其当我们需要为传统的SOAP服务引入异步处理能力、提升系统韧性或应对高并发挑战时,消息中间件就能作为SOAP消息的幕后推手,提供额外的价值。简单来说,SOAP定义了“说什么”以及“怎么说”(消息结构),而消息中间件则解决了“怎么高效、可靠地传递”这个问题。

解决方案

将SOAP消息与消息中间件结合,核心思路是将原本通常通过HTTP同步传输的SOAP XML内容,作为消息体放入消息队列中进行异步传递。这意味着,SOAP不再仅仅依赖于传统的HTTP/HTTPS作为传输协议,而是可以借助消息中间件(如ActiveMQ)提供的JMS(Java Message Service)接口,实现消息的发送与接收。这种做法的优势在于,它能有效解耦服务提供方和消费方,将同步调用转变为异步处理流程,从而提升系统的响应速度、容错能力和可扩展性。服务请求方只需将SOAP请求“扔”进队列,无需等待即时响应,可以继续处理其他任务;而服务提供方则从队列中按需拉取消息进行处理,即使高峰期请求量激增,也能通过队列进行缓冲,避免直接压垮后端服务。

为什么要在SOAP服务中使用消息队列?

我个人觉得,这主要出于对系统韧性和性能的考量。传统的SOAP服务,特别是基于HTTP的同步调用,一旦服务提供方响应慢或者暂时不可用,调用方就得一直阻塞等待,这在分布式系统中是很大的风险点。想象一下,一个关键的订单处理服务,如果每次都得同步调用库存检查的SOAP服务,而库存服务又偶尔卡顿,那整个订单流程都会被拖慢。

引入消息队列后,情况就不一样了。首先,异步解耦是最大的好处。订单服务只管把“请检查库存”的SOAP请求包装成消息发到队列里,然后就可以直接返回,无需等待库存服务的即时响应。库存服务什么时候有空,就去队列里取消息处理。这样,即使库存服务短暂宕机,订单服务也能正常工作,消息只是在队列里排队,等库存服务恢复后会自动处理,这大大提高了系统的容错能力

其次是削峰填谷。在业务高峰期,比如大促活动,瞬间涌入的SOAP请求可能会让后端服务不堪重负。消息队列就像一个蓄水池,能把这些突发的请求暂时存储起来,后端服务可以按照自己的处理能力匀速消费,避免系统过载崩溃。这对于那些处理时间较长、但又不需要即时反馈的SOAP操作尤其适用。

当然,这种模式也不是没有代价,它增加了系统的复杂性,比如你需要处理消息的幂等性(确保重复消费消息不会导致业务错误)、消息顺序性(如果业务对消息处理顺序有严格要求)以及最终一致性的问题。但权衡之下,对于那些对实时性要求不高、但对可靠性和吞吐量有较高要求的SOAP场景,消息队列的价值是显而易见的。

ActiveMQ如何作为SOAP消息的传输层?

ActiveMQ作为一款成熟的消息中间件,通过JMS规范提供了非常灵活的消息传输机制。它本身并不“理解”SOAP协议,它只负责可靠地传输消息体。所以,当我们将SOAP与ActiveMQ结合时,我们实际上是将SOAP XML字符串作为ActiveMQ消息的有效载荷(payload)进行传输。

具体来说,在发送端,你需要做的是:

  1. 构建SOAP请求的XML字符串。这通常可以通过JAXB(Java Architecture for XML Binding)将Java对象序列化为XML,或者直接手动构造XML。
  2. 获取一个JMS连接工厂(
    ConnectionFactory
    )和连接(
    Connection
    )。
  3. 创建一个JMS会话(
    Session
    )。
  4. 根据需要,创建一个JMS目标(
    Destination
    ),可以是队列(
    Queue
    )或主题(
    Topic
    )。队列适用于点对点通信,消息只被一个消费者消费;主题适用于发布/订阅模式,消息可以被多个消费者同时接收。
  5. 创建一个JMS消息生产者(
    MessageProducer
    )。
  6. 将SOAP XML字符串封装成一个
    TextMessage
    对象。
  7. 使用
    MessageProducer
    TextMessage
    发送到目标。

在接收端,过程则相反:

  1. 同样获取JMS连接工厂、连接和会话。
  2. 创建一个JMS目标(与发送方一致)。
  3. 创建一个JMS消息消费者(
    MessageConsumer
    )。
  4. 通过同步(
    consumer.receive()
    )或异步(设置
    MessageListener
    )方式接收
    TextMessage
  5. TextMessage
    中提取出SOAP XML字符串。
  6. 将SOAP XML字符串反序列化回Java对象(同样可以用JAXB),然后进行业务逻辑处理。

ActiveMQ在这里扮演的角色,就是一个可靠的“邮递员”,它确保SOAP信件(XML)能够从寄件人(服务请求方)安全无误地送达收件人(服务提供方),即使路上有些颠簸(网络故障)或收件人暂时不在家(服务宕机),信件也不会丢失,会在邮局(队列)里妥善保管,直到能被成功投递。

一个基于Spring Boot和ActiveMQ的SOAP客户端/服务端集成示例

为了让概念更具体,我们来看一个简化版的Spring Boot应用如何利用ActiveMQ来异步传递SOAP消息。这里我们不会搭建一个完整的JAX-WS over JMS环境,而是直接通过Spring JMS的抽象来发送和接收SOAP XML字符串,这在实际项目中更常见且灵活。

万兴爱画
万兴爱画

万兴爱画AI绘画生成工具

下载

首先,确保你的

pom.xml
中包含了Spring Boot Starter for ActiveMQ和JAXB(如果需要XML与Java对象转换):


    org.springframework.boot
    spring-boot-starter-activemq


    org.springframework.boot
    spring-boot-starter-web-services 

application.properties
中配置ActiveMQ连接:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

1. SOAP消息的Java对象表示 (OrderRequest.java, OrderResponse.java)

为了简化,我们假设有如下的POJO,它们最终会被序列化/反序列化为SOAP XML的一部分。

// src/main/java/com/example/soapjms/model/OrderRequest.java
package com.example.soapjms.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "OrderRequest", namespace = "http://example.com/orders")
@XmlAccessorType(XmlAccessType.FIELD)
public class OrderRequest {
    @XmlElement(name = "orderId")
    private String orderId;
    @XmlElement(name = "productCode")
    private String productCode;
    @XmlElement(name = "quantity")
    private int quantity;

    // Getters and Setters
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    public String getProductCode() { return productCode; }
    public void setProductCode(String productCode) { this.productCode = productCode; }
    public int getQuantity() { return quantity; }
    public void setQuantity(int quantity) { this.quantity = quantity; }

    @Override
    public String toString() {
        return "OrderRequest{" +
               "orderId='" + orderId + '\'' +
               ", productCode='" + productCode + '\'' +
               ", quantity=" + quantity +
               '}';
    }
}

// src/main/java/com/example/soapjms/model/OrderResponse.java
package com.example.soapjms.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "OrderResponse", namespace = "http://example.com/orders")
@XmlAccessorType(XmlAccessType.FIELD)
public class OrderResponse {
    @XmlElement(name = "orderId")
    private String orderId;
    @XmlElement(name = "status")
    private String status;
    @XmlElement(name = "message")
    private String message;

    // Getters and Setters
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    public String getStatus() { return status; }
    public void setStatus(String status) { this.status = status; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }

    @Override
    public String toString() {
        return "OrderResponse{" +
               "orderId='" + orderId + '\'' +
               ", status='" + status + '\'' +
               ", message='" + message + '\'' +
               '}';
    }
}

2. SOAP XML序列化/反序列化工具

// src/main/java/com/example/soapjms/util/SoapMarshaller.java
package com.example.soapjms.util;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;

public class SoapMarshaller {

    public static  String marshal(T object) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 可选,格式化输出

        StringWriter sw = new StringWriter();
        marshaller.marshal(object, sw);
        return sw.toString();
    }

    @SuppressWarnings("unchecked")
    public static  T unmarshal(String xmlString, Class clazz) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        return (T) unmarshaller.unmarshal(new StringReader(xmlString));
    }
}

3. SOAP服务提供方 (ActiveMQ Listener)

这个Spring Boot应用会监听一个名为

order.request.queue
的队列,接收SOAP请求,处理后发送响应到
order.response.queue

// src/main/java/com/example/soapjms/service/OrderServiceListener.java
package com.example.soapjms.service;

import com.example.soapjms.model.OrderRequest;
import com.example.soapjms.model.OrderResponse;
import com.example.soapjms.util.SoapMarshaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

import javax.jms.TextMessage;
import javax.xml.bind.JAXBException;

@Component
public class OrderServiceListener {

    private static final Logger log = LoggerFactory.getLogger(OrderServiceListener.class);

    @Autowired
    private JmsTemplate jmsTemplate;

    @JmsListener(destination = "order.request.queue")
    public void receiveOrderRequest(TextMessage message) {
        try {
            String soapRequestXml = message.getText();
            log.info("接收到SOAP订单请求: {}", soapRequestXml);

            // 模拟SOAP Envelope解析,实际中可能更复杂
            // 这里我们假设直接从消息体获取业务对象XML
            String orderRequestPayloadXml = extractPayloadFromSoapEnvelope(soapRequestXml);
            OrderRequest orderRequest = SoapMarshaller.unmarshal(orderRequestPayloadXml, OrderRequest.class);

            log.info("解析后的订单请求对象: {}", orderRequest);

            // 模拟业务处理
            OrderResponse response = new OrderResponse();
            response.setOrderId(orderRequest.getOrderId());
            if (orderRequest.getQuantity() > 0) {
                response.setStatus("SUCCESS");
                response.setMessage("订单 " + orderRequest.getOrderId() + " 已成功处理。");
            } else {
                response.setStatus("FAILED");
                response.setMessage("订单 " + orderRequest.getOrderId() + " 数量无效。");
            }

            // 构建SOAP响应XML
            String orderResponsePayloadXml = SoapMarshaller.marshal(response);
            String soapResponseXml = wrapPayloadInSoapEnvelope(orderResponsePayloadXml);

            log.info("发送SOAP订单响应: {}", soapResponseXml);
            jmsTemplate.convertAndSend("order.response.queue", soapResponseXml);

        } catch (JAXBException e) {
            log.error("SOAP消息解析或序列化失败: {}", e.getMessage());
            // 实际生产中可能需要发送错误响应
        } catch (Exception e) {
            log.error("处理订单请求时发生未知错误: {}", e.getMessage());
        }
    }

    // 简化SOAP Envelope的包裹和提取,实际中可能需要更健壮的XML解析
    private String extractPayloadFromSoapEnvelope(String soapXml) {
        // 假设SOAP XML结构是 ...
        // 这里只是一个简单的字符串查找,实际应该用XML解析器
        int startIndex = soapXml.indexOf("") + "".length();
        if (startIndex != -1 && endIndex != -1) {
            return soapXml.substring(startIndex, endIndex);
        }
        return soapXml; // 如果找不到,就返回原始XML,可能不是标准的SOAP Envelope
    }

    private String wrapPayloadInSoapEnvelope(String payloadXml) {
        return "\n" +
               "  \n" +
               payloadXml + "\n" +
               "  \n" +
               "";
    }
}

4. SOAP客户端 (ActiveMQ Sender & Listener)

这个Spring Boot应用会发送SOAP请求到

order.request.queue
,并监听
order.response.queue
来接收响应。

// src/main/java/com/example/soapjms/client/OrderServiceClient.java
package com.example.soapjms.client;

import com.example.soapjms.model.OrderRequest;
import com.example.soapjms.model.OrderResponse;
import com.example.soapjms.util.SoapMarshaller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

import javax.jms.TextMessage;
import javax.xml.bind.JAXBException;
import java.util.UUID;

@Component
public class OrderServiceClient implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(OrderServiceClient.class);

    @Autowired
    private JmsTemplate jmsTemplate;

    @Override
    public void run(String... args) throws Exception {
        sendOrderRequest("PROD-001", 10);
        sendOrderRequest("PROD-002", 0); // 测试无效数量
    }

    public void sendOrderRequest(String productCode, int quantity) {
        OrderRequest request = new OrderRequest();
        request.setOrderId(UUID.randomUUID().toString());
        request.setProductCode(productCode);
        request.setQuantity(

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

116

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

37

2026.01.26

spring boot框架优点
spring boot框架优点

spring boot框架的优点有简化配置、快速开发、内嵌服务器、微服务支持、自动化测试和生态系统支持。本专题为大家提供spring boot相关的文章、下载、课程内容,供大家免费下载体验。

135

2023.09.05

spring框架有哪些
spring框架有哪些

spring框架有Spring Core、Spring MVC、Spring Data、Spring Security、Spring AOP和Spring Boot。详细介绍:1、Spring Core,通过将对象的创建和依赖关系的管理交给容器来实现,从而降低了组件之间的耦合度;2、Spring MVC,提供基于模型-视图-控制器的架构,用于开发灵活和可扩展的Web应用程序等。

390

2023.10.12

Java Spring Boot开发
Java Spring Boot开发

本专题围绕 Java 主流开发框架 Spring Boot 展开,系统讲解依赖注入、配置管理、数据访问、RESTful API、微服务架构与安全认证等核心知识,并通过电商平台、博客系统与企业管理系统等项目实战,帮助学员掌握使用 Spring Boot 快速开发高效、稳定的企业级应用。

70

2025.08.19

Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性

Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。

35

2025.12.22

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

180

2025.12.24

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

331

2023.08.11

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8万人学习

Java 教程
Java 教程

共578课时 | 53.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号