【问题标题】:Spring Integration Doubts: CRUD operations and sharing events between componentsSpring 集成疑点:CRUD 操作和组件间共享事件
【发布时间】:2017-01-12 11:31:20
【问题描述】:

我目前正在使用 Spring 集成框架开发一个简单的 Spring Web 应用程序。我已经阅读了企业集成模式、目的、好处......我已经摆脱了 ServiceLayer 并将应用程序工作流委托给集成框架。但是我遇到了一些我卡住的设计问题,我希望能在设计方面有所了解。下面我将尝试解释它们,在此先感谢。

1.使用 Spring Integration Framework 进行 CRUD 操作

假设您有 2 个端点通过直接通道连接,1 个端点接收请求,另一个端点处理这些请求。我不想从实现的角度讨论,而是从设计的角度讨论(正如我之前所说),但为了澄清这一点,想象一下,您将接收端点实现为连接到网关的 RestController,而将另一个端点实现为ServiceActivator 连接到数据库适配器。 现在,用户可以请求 4 种基本操作,创建、读取、更新和删除(基本 CRUD)。由于接收方端点只能执行一种方法(handleMessage 方法),那么复用这 4 种操作的正确方法是什么?

  1. 在邮件头中添加某种标签?这对我来说似乎很难看,除了接收器端点之外,还必须实现一个 if-else 块。将控制器连接到接口并调用方法并摆脱 spring 集成会更容易。
  2. 创建 4 个连接到同一个数据库的 ServiceActivator?我也不喜欢它,想象一下如果你有 30 个操作而不是 4 个。
  3. 我还没有找到其他解决方案吗?例如,通过不同的通道发送每个操作,这样您就有 4 个通道。您可以从网关的角度执行此操作,但问题是 ServiceActivator 只能有 1 个入站通道。

2。使用 Spring Integration Framework 在端点之间共享事件

假设您有一个连接到转换器的网关。转换器启动一个线程,在该线程中解析一些数据并在完成时将其发送到下一个端点。 现在,网关客户端需要知道它通过通道发送的请求的状态(因为网关对 Transformer 或其实现一无所知,它们不应该共享任何东西)。由于转换器只有 1 个入站通道和 1 个输出通道,并且无法通过第三个通道将结果发布回来,如何实现呢?本质上,问题是,如何在不耦合端点或破坏集成模式架构的情况下共享事件? P.D.:请避免使用静态共享对象等不干净的答案,谢谢。

【问题讨论】:

    标签: java spring web-applications spring-integration integration


    【解决方案1】:

    嗯嗯。你的担忧不知何故不清楚。

    当您之前有一个 ServiceLayer 时,我很确定许多特定操作的方法并没有打扰您。所以,当您切换到消息传递架构时,不知道为什么您如此担心消息通道区分操作。

    同时我猜@CotrollerGETPOSTDELETE@RequestMapping 的方法不再关心你了。

    面对端点之间的MessageChannels,在应用程序中有额外的对象有点不方便。但与此同时,当您开始将您的应用程序视为一堆消息流时,这是一个奖励,其中每个消息流都与MessageChannel 分开,您可以修改任何流而不影响任何其他流。另外不要忘记,使用MessageChannel,您可以简单地进入分布式模式,此时您的业务逻辑相同,但消息通过网络传输以用于目标服务或其他目的。

    所以,IMO 我有@MessagingGateway@Controller 调用,每个网关的方法将映射到特定的MessageChannel

    由于注释模型,您可以只有一个目标服务,但每个 CRUD 操作的方法都用 @ServiceActivator 标记为特定的 MessageChannel

    @MessagingGateway
    public interface CrudGateway {
    
       @Gateway(requestChannel = "getChannel")
       Object get(Object id);
    
       @Gateway(requestChannel = "saveChannel")
       Object save(Object object);
    
       @Gateway(requestChannel = "deleteChannel")
       boolean delete(Object object);
    
    }
    
    ...
    
    @Service
    public class CrudService {
    
       @ServiceActivator(inputChannel = "getChannel")
       public Object get(Object id) {
           // SELECT
       }
    
       @ServiceActivator(inputChannel = "saveChannel")
       public Object save(Object object) {
           // INSERT or UPDATE
       }
    
       @ServiceActivator(inputChannel = "deleteChannel")
       public boolean delete(Object object) {
           // DELETE
       }
    
    }
    

    对于你的第二个问题,也有一些答案。

    考虑使用PublishSubscribeChannel 作为transformer 的输出。

    另一方面,RecipientListRouter 将传入消息分发给多个收件人 - 当然是频道。

    【讨论】:

    • 非常感谢Artem,非常有用的答案。我理解了第一部分,但没有得到第二部分。据我了解,转换器只能有一种方法,因此无法通过发布/订阅发布消息通知转换器内部正在运行的线程的状态。总而言之,我得到了一个控制器 -> 网关 -> 变压器 -> 出站适配器。变压器内部有一个任务。我需要从控制器轮询任务百分比,以便在 html 视图中显示它。怎么可能实现?我的另一个问题是该线程的范围。谢谢!
    • 好吧,你可以从那个线程发布百分比到某个QueueChannel,当你的控制器来检查状态时,它只会轮询来自那个QueueChannel的消息。或者...您可以简单地使用AtomicReference 来放置最新的进度,控制器将只查找该值到AtomicReference.get()
    • 再次感谢 Artem。我不知道您可以直接在课程中注入频道。我认为这一切都是通过注释自动完成的,并且您无法控制通道对象。如果转换器发布其他类型的消息,我是否会破坏架构,因为它将承担多个责任(转换)?此外,如果每个控制器会话的转换器中有一个任务,我如何区分该任务?此外,如何通过通道更新到正确的会话线程?在创建通道/端点/任务时我应该使用消息头还是 @Session?谢谢你
    猜你喜欢
    • 2023-04-01
    • 2011-07-19
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 2022-06-24
    • 1970-01-01
    相关资源
    最近更新 更多