Message Processing With Spring Integration高级应用:自定义消息通道与端点
一、Spring Integration 简介
Spring Integration 是 Spring 框架的扩展,支持企业集成模式(EIP),提供轻量级的消息处理功能,帮助开发者构建可维护、可测试的企业集成解决方案。
核心目标:
- 提供简单的模型来实现复杂的企业集成。
- 支持与外部系统的集成。
- 提供模块化、松耦合的消息处理架构。
二、Spring Integration 核心组件
1. 消息(Message)
- 定义:消息是 Spring Integration 的核心,包含
payload
(负载)和header
(头部)。 - 创建消息:通过
MessageBuilder
创建消息。
代码示例:
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;Message<String> message = MessageBuilder.withPayload("Message Payload").setHeader("Message_Header1", "Header1_Value").setHeader("Message_Header2", "Header2_Value").build();
2. 消息通道(Message Channel)
- 定义:消息通道是消息传递的管道,连接消息的生产者和消费者。
- 类型:
- 点对点(Point-to-Point):每条消息最多被一个消费者接收。
- 发布/订阅(Publish/Subscribe):每条消息可以被多个订阅者接收。
- 常见实现:
DirectChannel
:默认点对点通道。NullChannel
:虚拟通道,用于测试和调试。- 其他:
PublishSubscribeChannel
、QueueChannel
、PriorityChannel
等。
3. 消息端点(Message Endpoint)
消息端点是应用程序代码与消息基础设施之间的桥梁,主要类型包括:
- Transformer:转换消息内容或结构。
- Filter:过滤不符合条件的消息。
- Router:根据条件将消息路由到不同的通道。
- Splitter:将消息拆分为多个子消息。
- Aggregator:将多个消息聚合为一个消息。
- Service Activator:连接服务实例到消息系统。
- Channel Adapter:连接消息通道与外部系统。
三、货物处理系统示例
1. 需求
实现一个货物处理系统,功能包括:
- 接收货物消息。
- 拆分货物列表为单个货物消息。
- 基于重量过滤货物。
- 根据运输类型(国内/国际)路由货物。
- 转换货物消息。
- 最终处理并记录货物信息。
2. 项目环境
- JDK:1.8
- Spring:4.1.2
- Spring Integration:4.1.0
- Maven:3.2.2
- 操作系统:Ubuntu 14.04
3. 完整代码实现
Step 1:添加依赖
在 pom.xml
中添加 Spring 和 Spring Integration 的依赖:
<properties><spring.version>4.1.2.RELEASE</spring.version><spring.integration.version>4.1.0.RELEASE</spring.integration.version>
</properties><dependencies><!-- Spring 核心依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- Spring Integration 核心依赖 --><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-core</artifactId><version>${spring.integration.version}</version></dependency>
</dependencies>
Step 2:配置类
创建 AppConfiguration
类,配置消息通道和启用 Spring Integration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.messaging.MessageChannel;@Configuration
@ComponentScan("com.onlinetechvision.integration")
@EnableIntegration
@IntegrationComponentScan("com.onlinetechvision.integration")
public class AppConfiguration {@Beanpublic MessageChannel cargoGWDefaultRequestChannel() {return new DirectChannel();}@Beanpublic MessageChannel cargoSplitterOutputChannel() {return new DirectChannel();}@Beanpublic MessageChannel cargoFilterOutputChannel() {return new DirectChannel();}@Beanpublic MessageChannel cargoTransformerOutputChannel() {return new DirectChannel();}
}
Step 3:消息网关
定义 CargoGateway
接口,作为消息系统的入口:
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.messaging.Message;import java.util.List;@MessagingGateway
public interface CargoGateway {@Gateway(requestChannel = "cargoGWDefaultRequestChannel")void processCargoRequest(Message<List<Cargo>> message);
}
Step 4:消息拆分器
实现 CargoSplitter
,将货物列表拆分为单个货物消息:
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Splitter;
import org.springframework.messaging.Message;import java.util.List;@MessageEndpoint
public class CargoSplitter {@Splitter(inputChannel = "cargoGWDefaultRequestChannel", outputChannel = "cargoSplitterOutputChannel")public List<Cargo> splitCargoList(Message<List<Cargo>> message) {return message.getPayload();}
}
Step 5:消息过滤器
实现 CargoFilter
,过滤重量超过限制的货物:
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.MessageEndpoint;@MessageEndpoint
public class CargoFilter {private static final double CARGO_WEIGHT_LIMIT = 1000.0;@Filter(inputChannel = "cargoSplitterOutputChannel", outputChannel = "cargoFilterOutputChannel", discardChannel = "cargoFilterDiscardChannel")public boolean filterCargo(Cargo cargo) {return cargo.getWeight() <= CARGO_WEIGHT_LIMIT;}
}
Step 6:服务激活器
实现 CargoServiceActivator
,处理最终的货物消息:
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.handler.annotation.Header;@MessageEndpoint
public class CargoServiceActivator {@ServiceActivator(inputChannel = "cargoTransformerOutputChannel")public void processCargo(Cargo cargo, @Header("CARGO_BATCH_ID") long batchId) {System.out.println("Processed Cargo: " + cargo + " in Batch: " + batchId);}
}
Step 7:运行主程序
创建 Application
类,初始化 Spring 容器并发送货物请求:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.messaging.support.MessageBuilder;import java.util.Arrays;
import java.util.List;public class Application {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class);CargoGateway gateway = context.getBean(CargoGateway.class);List<Cargo> cargos = Arrays.asList(new Cargo(1, "Receiver1", "Address1", 500, "Domestic"),new Cargo(2, "Receiver2", "Address2", 1500, "International"));gateway.processCargoRequest(MessageBuilder.withPayload(cargos).build());}
}
四、运行过程
- 启动
Application
类。 - 系统会根据配置:
- 拆分货物列表。
- 过滤重量超过限制的货物。
- 路由货物到不同的通道。
- 最终处理并记录货物信息。
- 控制台输出处理结果。
五、适用场景
Spring Integration 非常适合以下场景:
- 企业系统集成:如 ERP、CRM、供应链系统之间的数据交换。
- 消息驱动架构:如基于事件的微服务通信。
- 复杂消息处理:如批量处理、过滤、路由、转换等。
- 与外部系统交互:如文件系统、消息队列(RabbitMQ、Kafka)、数据库等。
通过 Spring Integration,可以轻松实现复杂的企业集成需求,同时保持代码的可维护性和扩展性。
参考链接:https://dzone.com/articles/message-processing-spring
相关文章:
Message Processing With Spring Integration高级应用:自定义消息通道与端点
一、Spring Integration 简介 Spring Integration 是 Spring 框架的扩展,支持企业集成模式(EIP),提供轻量级的消息处理功能,帮助开发者构建可维护、可测试的企业集成解决方案。 核心目标: 提供简单的模型…...

S32K324 MCAL中的Postbuild和PreCompile使用
文章目录 前言Postbuild和PreCompile的概念MCAL中配置差异总结 前言 之前一直看到MCAL配置中有这个Postbuild和PreCompile的配置,但是不太清楚这两个的区别和使用方法。最近在使用中出现了相关问题,本文介绍一下MCAL中这两种配置的区别和使用。 Postbu…...

kubeadm_k8s_v1.31高可用部署教程
kubeadm_k8s_v1.31高可用部署教程 实验环境部署拓扑图**部署署架构****Load Balance****Control plane node****Worker node****资源分配(8台虚拟机)**集群列表 前置准备关闭swap开启ipv4转发更多设置 1、Verify the MAC address and product_uuid are u…...

【AI日记】24.12.22 容忍与自由 | 环境因素和个人因素
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 内容:看 OpenAi 这周的发布会和其他 AI 新闻,大佬视频时间:3 小时 读书 书名:富兰克林自传时间:1 小时评估:读完,总体…...
【Java基础面试题030】Java和Go的区别?
回答重点 可以从语言的设计理念、并发模型、内存管理、生态系统与应用场景来说: 1)语言设计理念: Java:Java是一种面向对象编程语言,强调继承、多态和封装等OOP特性。它运行在Java虚拟机(JVM)…...
学习嵩山版《Java 开发手册》:编程规约 - 常量定义(P5)
概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南,对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...

洛谷 P1595 信封问题 C语言递归
题目描述 某人写了 n 封信和 n 个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。 输入格式 一个信封数 n,保证 n≤20。 输出格式 一个整数,代表有多少种情况。 输入输出样例 输入 #1 2 输出 #1 1 输入 #2 …...
QT创建一个模板槽和信号刷新UI
文章目录 信号与槽的声明work.cpp 信号与槽的连接 在Qt中,若您想设计一个仅含一个信号和槽函数框架,用以刷新UI上多个类型相同但可能属性各异的控件,我们可以借助QVariant的灵活性来传递不同种类的数据,同时利用控件的名称或某种标…...

【计算机视觉基础CV-图像分类】01- 从历史源头到深度时代:一文读懂计算机视觉的进化脉络、核心任务与产业蓝图
1.计算机视觉定义 计算机视觉(Computer Vision)是一个多学科交叉的研究领域,它的核心目标是使计算机能够像人类一样“看”并“理解”视觉信息。换句话说,它希望赋予计算机从图像、视频中自动提取、有意义地分析、理解并解释视觉场…...

C# cad启动自动加载启动插件、类库编译 多个dll合并为一个
可以通过引用costura.fody的包,编译后直接变为一个dll 自动加载写入注册表、激活码功能: 【CAD二次开发教程-实例18-启动加载与自动运行-哔哩哔哩】 https://b23.tv/lKnki3f https://gitee.com/zhuhao1912/cad-atuo-register-and-active...

Mybatis增删改查(配置文件版)
准备环境 1、数据库表tb_brand 2、实体类Brand 3、测试用例 3、1在test包中的java包中创建测试类com.xyy.test.MybatisTest.java 4、安装MyBatisX插件 添加插件后,因为在Mapper代理开发时,Mapper接口要和Mapper.xml映射文件放在同一个报下࿰…...

【Spring Security系列】5 次密码错误触发账号锁定?Spring Security 高效实现方案详解
作者:后端小肥肠 🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案 🍊 有疑问可私信或评论区联系我。 🥑 创作不易未经允许严禁转载。 姊妹篇: 【Spring Security系列…...
笔记day5
文章目录 1 复习2 最完美的解决方案,解决轮播图问题3 开发Floor组件4 把首页中的轮播图拆分为一个共用全局组件5 search模块开发 1 复习 完成商品分类三级列表路由跳转一级路由传参(合并参数)完成search模块中对于typeNav的使用(…...

Linux快速入门-兼期末快速复习使用
Linux快速入门-兼期末快速复习使用 一小时快速入门linux快速一:Linux操作系统概述1. Linux概述1.1 定义与特点1.2 起源与发展1.3 Linux结构1.4 版本类别1.5 应用和发展方向 2. 安装与启动2.1 Windows下VMware安装Linux2.2 安装Ubuntu 快速二:linux的桌面…...

浅谈文生图Stable Diffusion(SD)相关模型基础
1.U-Net模型基础 1.基础概念 UNet模型是一种基于卷积神经网络的图像分割算法,它采用了U型的网络结构,由编码器(下采样路径)和解码器(上采样路径)两部分组成。 编码器负责提取输入图像的特征,…...

Vivado使用VScode编译器
旧版Vivado使用Vscode编译器偶尔会出现VScode界面卡死的情况,在新版的Vivado中(我的是Vivado 2023.2),可以使用如下方式: 在设置中选择Text Editor,选择Custom Editor 在对话框中输入以下语句:…...

CEF127 编译指南 MacOS 篇 - 拉取 CEF 源码(五)
1. 引言 在完成了所有必要工具的安装和配置后,我们进入到获取 CEF 源码的阶段。对于 macOS 平台,CEF 的源码获取过程需要特别注意不同芯片架构(Intel 和 Apple Silicon)的区别以及版本管理。本文将详细介绍如何在 macOS 系统上获…...
Jenkins 中 写 shell 命令执行失败,检测失败问题
由于项目的 依赖复杂,随着版本的增多,人工操作,手误几率太大,我们选取kenins 来自动化发布、更新。 这里主要解决,发布 的 每个阶段,确保每个阶段执行成功。 比如: js 运行,…...

Java程序打包成exe,无Java环境也能运行
Java程序开发完成后,通常情况下以jar包的形式发布。但有时我们需要给非软件开发人员使用程序,如制作好窗体应用,把它发给没有java开发环境的人使用,此时就需要制作exe安装包。本文介绍如何将java程序制作成exe安装包,并…...

【java 正则表达式 笔记】
文章目录 快速入门匹配中文或数字或大小写字母(一个或多个) 正则表达式底层实现(重要)mather.find() 完成的任务mather.group(0) 分析 正则表达式基本语法元字符转义字符区分大小写限定字符选择匹配符特殊字符字符匹配符定位符 分组、捕获和反向引用捕获特别分组反向引用经典结…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...