错误处理在Spring Integration中如何工作

1.引言

这篇文章的目标是向您展示将消息传递系统与Spring Integration结合使用时如何处理错误。 您将看到同步和异步消息传递之间的错误处理有所不同。 和往常一样,我将跳过聊天并继续进行一些示例。

  • 您可以在github上获取源代码。

2,样品申请

我将使用一个基本示例,因为我想专注于异常处理。 该应用程序包含一个订单服务,该服务接收订单,处理订单并返回确认。

下面我们可以看到消息传递系统的配置方式:

int-config.xml

<context:component-scan base-package="xpadro.spring.integration"/><int:gateway default-request-channel="requestChannel" service-interface="xpadro.spring.integration.service.OrderService"/><int:channel id="requestChannel"/><int:router input-channel="requestChannel" ref="orderRouter" method="redirectOrder"/><int:channel id="syncChannel"/><int:channel id="asyncChannel"><int:queue capacity="5"/>
</int:channel><int:service-activator method="processOrder" input-channel="syncChannel" ref="orderProcessor"/><int:service-activator method="processOrder" input-channel="asyncChannel" ref="orderProcessor"><int:poller fixed-delay="2000"/>
</int:service-activator>

网关是消息传递系统的入口点。 它将接收订单并将其发送到直接通道“ requestChannel”,路由器将根据订单ID将其重定向到适当的通道:

  • syncChannel:一个直接通道 ,它将订单发送到订阅该通道的订单处理器。
  • asyncChannel:一个队列通道 ,订单处理器将从中主动检索订单。

处理订单后,订单确认将发送回网关。 这是代表此的图形:

嫁接

好的,让我们从最简单的情况开始,使用直接通道进行同步发送。

3.与直接通道同步发送

订单处理器已订阅“ syncChannel”直接渠道。 “ processOrder”方法将在发送者的线程中调用。

public OrderConfirmation processOrder(Order order) {logger.info("Processing order {}", order.getId());if (isInvalidOrder(order)) {logger.info("Error while processing order [{}]", ERROR_INVALID_ID);throw new InvalidOrderException(ERROR_INVALID_ID);}return new OrderConfirmation("confirmed");
}

现在,我们将执行一个测试,该测试将通过发送无效订单来引发异常。 此测试将向网关发送订单:

public interface OrderService {@Gatewaypublic OrderConfirmation sendOrder(Order order);
}

考试:

TestSyncErrorHandling.java

@ContextConfiguration(locations = {"/xpadro/spring/integration/config/int-config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class TestSyncErrorHandling {@Autowiredprivate OrderService service;@Testpublic void testCorrectOrder() {OrderConfirmation confirmation = service.sendOrder(new Order(3, "a correct order"));Assert.assertNotNull(confirmation);Assert.assertEquals("confirmed", confirmation.getId());}@Testpublic void testSyncErrorHandling() {OrderConfirmation confirmation = null;try {confirmation = service.sendOrder(new Order(1, "an invalid order"));Assert.fail("Should throw a MessageHandlingException");} catch (MessageHandlingException e) {Assert.assertEquals(InvalidOrderException.class, e.getCause().getClass());Assert.assertNull(confirmation);}}
}

我们运行测试,看看在订单处理器中如何引发异常并到达测试。 没关系; 我们想验证发送无效订单是否引发了异常。 发生这种情况是因为测试发送了订单,并阻止等待在同一线程中处理订单。 但是,当我们使用异步通道时会发生什么? 让我们继续下一节。

4,与队列通道异步发送

此部分的测试发送一个命令,该命令将由路由器重定向到队列通道。 网关如下所示:

public interface OrderService {@Gatewaypublic Future<OrderConfirmation> sendFutureOrder(Order order);
}

请注意,这次网关正在返回Future 。 如果我们不返回此值,则网关将阻止测试线程。 通过返回Future,网关将变为异步状态,并且不会阻塞发送方的线程。

考试:

TestKoAsyncErrorHandling.java

@ContextConfiguration(locations = {"/xpadro/spring/integration/config/int-config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class TestKoAsyncErrorHandling {@Autowiredprivate OrderService service;@Test(expected=MessageHandlingException.class)public void testAsyncErrorHandling() throws InterruptedException, ExecutionException {Future<OrderConfirmation> confirmation = service.sendFutureOrder(new Order(6, "another order"));}
}

好的,现在我们将启动测试并看到引发异常的信息…

java.lang.AssertionError: Expected exception: org.springframework.integration.MessageHandlingException

糟糕,测试失败,因为没有异常到达测试! 发生了什么? 好吧,解释如下:

<int:channel id="asyncChannel"><int:queue capacity="5"/>
</int:channel><int:service-activator method="processOrder" input-channel="asyncChannel" ref="orderProcessor"><int:poller fixed-delay="2000"/>
</int:service-activator>

由于我们使用的是异步通道(队列),因此发送者发送订单并继续前进。 然后,接收方从另一个线程轮询订单。 因此,不可能将Exception抛回到发送方。 让我们表现得好像什么都没发生吗? 好吧,您最好不要,还有其他选择。

5,异步错误处理

当使用异步消息传递时,Spring Integration通过将异常发布到消息通道来处理它们。 引发的异常将包装到MessagingException中,并成为消息的有效负载。

错误消息发送到哪个通道? 首先,它将检查请求消息是否包含名为“ errorChannel”的标头。 如果找到,错误消息将被发送到那里。 否则,该消息将被发送到所谓的全局错误通道。

5.1全局错误通道

默认情况下,Spring Integration创建一个名为“ errorChannel”的全局错误通道。 该频道是发布-订阅频道。 这意味着我们可以为该频道订阅多个端点。 实际上,已经有一个端点订阅了它:一个日志记录处理程序 。该处理程序将记录到达通道的消息的有效负载,尽管可以将其配置为不同的行为。

现在,我们将向该全局通道订阅一个新的处理程序,并通过将其存储到数据库中来测试它是否接收到异常消息。

首先,我们需要在配置中进行一些更改。 我创建了一个新文件,因此它不会干扰我们之前的测试:

int-async-config.xml

<context:component-scan base-package="xpadro.spring.integration"/><int:gateway default-request-channel="asyncChannel" service-interface="xpadro.spring.integration.service.OrderService" error-channel="errorChannel"/><int:channel id="asyncChannel"><int:queue capacity="5"/>
</int:channel><int:service-activator method="processOrder" input-channel="asyncChannel" ref="orderProcessor"><int:poller fixed-delay="2000"/>
</int:service-activator><int:service-activator input-channel="errorChannel" ref="orderErrorHandler" method="handleFailedOrder"/><bean id="orderErrorHandler" class="xpadro.spring.integration.activator.OrderErrorHandler"/>

网关 :我添加了一个错误通道。 如果调用失败,错误消息将发送到该通道。 如果我没有定义错误通道,则网关会将异常传播给调用者,但是在这种情况下,由于这是一个异步网关,因此无法正常工作。

错误处理程序 :我已经定义了一个新的端点,该端点已订阅了全局错误通道。 现在,任何发送到全局错误通道的错误消息都将传递给我们的处理程序。

我还添加了一个配置文件以配置数据库。 我们的错误处理程序会将收到的错误插入此数据库:

db-config.xml

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><constructor-arg ref="dataSource"/>
</bean><!-- in-memory database -->
<jdbc:embedded-database id="dataSource"><jdbc:script location="classpath:db/schemas/schema.sql" />
</jdbc:embedded-database>

错误处理程序非常简单。 它收到错误消息,并将其信息插入数据库:

public class OrderErrorHandler {@Autowiredprivate JdbcTemplate jdbcTemplate;@ServiceActivatorpublic void handleFailedOrder(Message<MessageHandlingException> message) {Order requestedOrder = (Order) message.getPayload().getFailedMessage().getPayload();saveToBD(requestedOrder.getId(), message.getPayload().getMessage());}private void saveToBD(int orderId, String errorMessage) {String query = "insert into errors(orderid, message) values (?,?)";jdbcTemplate.update(query, orderId, errorMessage);}
}

好的,现在一切就绪。 让我们实施一个新的测试:

TestOkAsyncErrorHandlingTest.java

@ContextConfiguration(locations = {"/xpadro/spring/integration/config/int-async-config.xml","/xpadro/spring/integration/config/db-config.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class TestOkAsyncErrorHandling {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate OrderService service;@Beforepublic void prepareTest() {jdbcTemplate.update("delete from errors");}@Testpublic void testCorrectOrder() throws InterruptedException, ExecutionException {Future<OrderConfirmation> confirmation = service.sendFutureOrder(new Order(7, "another correct order"));OrderConfirmation orderConfirmation = confirmation.get();Assert.assertNotNull(orderConfirmation);Assert.assertEquals("confirmed", orderConfirmation.getId());}@Testpublic void testAsyncErrorHandling() throws InterruptedException, ExecutionException {Future<OrderConfirmation> confirmation = service.sendFutureOrder(new Order(6, "another order"));Thread.sleep(2000);Assert.assertEquals(1, getSavedErrors());validateSavedError(6);}private int getSavedErrors() {return jdbcTemplate.queryForObject("select count(*) from errors", Integer.class);}private void validateSavedError(int orderId) {String query = "select * from errors where orderid=?";Map<String, Object> result = jdbcTemplate.queryForMap(query, orderId);Assert.assertEquals(6, result.get("orderid"));assertThat((String)result.get("message"), containsString("Order ID is invalid"));}
}

这次测试成功,错误消息已存储到数据库。

5.2其他机制

自定义错误通道 :您可以定义错误通道并将其定义为队列通道,而不是默认的发布-订阅通道:

<int:poller id="defaultPoller" default="true" fixed-delay="5000" /><int:channel id="errorChannel"><int:queue capacity="10"/>
</int:channel>

ErrorMessageExceptionTypeRouter :这个Spring Integration专用路由器将解析将错误消息发送到的通道。 它基于错误的最具体原因做出决定:

<int:exception-type-router input-channel="errorChannel" default-output-channel="genericErrorChannel"><int:mapping exception-type="xpadro.spring.integration.exception.InvalidOrderException" channel="invalidChannel" /><int:mapping exception-type="xpadro.spring.integration.exception.FooException" channel="fooChannel" />
</int:exception-type-router>

六,结论

我们已经了解了使用Spring Integration时错误处理的不同机制是什么。 有了这个基础,您将能够通过实现转换器从错误消息中提取信息,使用标头扩展器设置错误通道或实现自己的路由器等来扩展它并配置错误处理。

参考:来自XavierPadró博客博客的JCG合作伙伴 Xavier Padro 在Spring Integration中如何处理错误 。

翻译自: https://www.javacodegeeks.com/2014/02/how-error-handling-works-in-spring-integration.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364724.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原生js、jQuery实现选项卡功能

在大家在网上平常浏览网页的时候&#xff0c;想必各位都会看到选项卡功能&#xff0c;在这里给大家详解一下用原生js、jQuery如何来写一些基本的选项卡 话不多说&#xff0c;先给各位看一下功能图&#xff1a; 好了&#xff0c;下边开始写代码了&#xff1a; HTML代码&#x…

.NET core2.0 发布至IIS中

.NET CORE和asp.net 发布时不太一样&#xff0c;ASP.NET Core不再是由IIS工作进程&#xff08;w3wp.exe&#xff09;托管&#xff0c;而是使用自托管Web服务器&#xff08;Kestrel&#xff09;运行&#xff0c;IIS则是作为反向代理的角色转发请求到Kestrel不同端口的ASP.NET Co…

如何用纯 CSS 创作一个文本淡入淡出的 loader 动画

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/ERwpeG可交互视频此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打开观…

《机器学习基石》第一周 —— When Can Machine Learn?

&#xff08;注&#xff1a;由于之前进行了吴恩达机器学习课程的学习&#xff0c;其中有部分内容与机器学习基石的内容重叠&#xff0c;所以以下该系列的笔记只记录新的知识&#xff09; 《机器学习基石》课程围绕着下面这四个问题而展开&#xff1a; 主要内容&#xff1a; 一、…

如何用纯 CSS 创作一盘传统蚊香

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/BVpvMz可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

[Unity3D]Unity3D游戏开发之怪物AI

大家好。欢迎大家关注由我为大家带来的Unity3D游戏开发系列文章&#xff0c;我的博客地址为&#xff1a;http://blog.csdn.net/qinyuanpei。在上一篇文章中&#xff0c;我们基本上实现了一个小地图的功能&#xff0c;今天呢&#xff0c;我们来实现怪物AI&#xff0c;所谓怪物AI…

如何把握好 transition 和 animation 的时序,创作描边按钮特效

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/mKdzZM可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

使用PHREAK算法实现Drools 6性能

Drools 6引入了新的惰性匹配算法。 该算法的详细信息已在之前的两个博客中介绍&#xff1a; RIP RETE时间获得PHREAKY 基于PHREAK堆栈的评估和向后链接 第一篇文章讨论了性能以及为什么算法的批处理和惰性方面难以比较。 “性能的最后一点。 通常&#xff0c;使用PHREAK的单…

PAT 1131 Subway Map

题目链接&#xff1a; https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432 思路&#xff1a; 说多了都是泪&#xff0c; Dijstra超时&#xff0c;采用dfs 利用map<pair<int,int>,int>&#xff0c;表示两个点和他们中间的地铁线号 每次…

专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

1、为什么要对 Vue CLI 进行大规模修改&#xff1f; 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版&#xff0c;这种拉模版的方式有几个问题&#xff1a; &#xff08;1&#xff09; 在单个模版里面同时支持太多选项会导致模版本身变得极其复杂和难以维护&#x…

java秒杀时间与服务器时间_Javascript实现秒杀倒计时(时间与服务器时间同步)...

现在有很多网站都在做秒杀商品&#xff0c;而这其中有一个很重要的环节就是倒计时。关于倒计时&#xff0c;有下面几点需要注意&#xff1a;1.应该使用服务器时间而不是本地时间(本地时间存在时区不同、用户自行设置等问题)。2.要考虑网络传输的耗时。3.获取时间时可直接从AJAX…

Python3.5-20190501-廖老师的

python是一门解释型\脚本语言(和js特别像,如果同时学习js和python完全搅浑了.) 在运行py时候是一句一句翻译成cpu识别的机器码,所以速度比较慢.而C程序是运行前直接编译成CPU能执行的机器码&#xff0c;所以非常快. 学习python,就需要安装python.安装的同时会有一个解释器,就是…

如何用纯 CSS 创作一个冒着热气的咖啡杯

效果预览 在线演示 按下右侧的“点击预览”按钮在当前页面预览&#xff0c;点击链接全屏预览。https://codepen.io/zhang-ou/pen/xjXxoz可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打开观看。…

FC冒险岛java版_冒险岛单机版

游戏概述冒险岛单机版是一款非常好玩的横版动作RPG游戏&#xff0c;游戏难度很适中&#xff0c;冒险岛单机版采用了与其他Q版2D游戏不同的横向卷轴的移动方式&#xff0c;场景高低落差的设计&#xff0c;整个画面层次感设计算是一级&#xff0c;喜欢这类手柄闯关游戏的玩家快来…

通过小程序实现网站扫码登录!每年都可以省 300 块...代替微信开放平台和服务号的登陆模式!

我们知道&#xff0c;要接入微信登陆有两种方式 1、微信开放平台2、微信服务号 这两种方式均可生成带参数的二维码&#xff0c;然后扫码获取用户基本信息的&#xff0c;所以我们可以在网站上用这两种方式开发网站的扫码登录&#xff0c;也是现在很多网站的通用做法。 微信开…

WAR文件与具有嵌入式服务器的Java应用程序

大多数服务器端Java应用程序&#xff08;例如&#xff0c;面向Web或面向服务的&#xff09;都希望在容器中运行。 打包这些应用程序以进行分发的传统方法是将它们捆绑为WAR文件。 这无非是具有标准目录布局的ZIP归档文件&#xff0c;其中包含运行时所需的所有库和应用程序级依赖…

easypanel mysql错误_Easypanel v1.6(虚拟主机控制面板)图文使用教程

一、Easypanel软件简介&#xff1a;Easypanel是一款虚拟主机管理工具&#xff0c;它支持php(windows系统还支持asp、asp.net)、磁盘配额、在线文件管理、在线web软件安装&#xff0c;是一款集虚拟主机、ftp、mysql等功能为一体的管理系统&#xff0c;本身还集成了kangle web服务…

游戏、脑洞大开1(密码简单破译)

“二八”妙龄写密码&#xff0c;看谁聪明“爱死他”。 密文&#xff1a;766C7273626F76706A5E6F715F7271766C72706D626B71716C6C71666A62 注意&#xff1a;&#xff08;1&#xff09;此题由正心41上课的同学做 &#xff08;2&#xff09;第一个提交&#xff0c;答案&#xff1a…

thinkPHP利用ajax异步上传图片并显示、删除

近来学习tp5的过程中&#xff0c;项目中有个发帖功能&#xff0c;选择主题图片。如下&#xff1a; 利用原始的文件上传处理&#xff0c;虽然通过原始js语句能实时显示上传图片&#xff0c;但是这样的话会涉及很多兼容问题。使用ajax技术&#xff0c;实现选择性删除所选图片功能…

php redis.dll php5.6,在Windows 64位下为PHP5.6.14安装redis扩展

一.php安装redis扩展1.使用phpinfo()查看当前版本的信息2.根据PHP版本号&#xff0c;编译器版本号和CPU架构选择php_redis-2.2.5-5.6-nts-vc11-x64.zip和php_igbinary-1.2.1-5.5-nts-vc11-x64.zip下载地址&#xff1a;http://windows.php.net/downloads/pecl/snaps/redis/2.2.5…