Spring集成:将Web服务挂接到FIFO队列

vfwfrxfs  于 2023-09-29  发布在  Spring
关注(0)|答案(5)|浏览(106)

我仍然在与Spring Integration作斗争-这是我的场景:

  1. Web服务从客户端A获取请求
  2. Web服务将请求放到队列中
    1.队列使用者处理消息FIFO并发送响应,该响应被路由回Web服务
  3. Web服务将响应发送回客户端A
    将有多个Web服务将消息提供给这个队列,我需要确保它们确实按照接收的顺序进行处理。
    我需要将Spring Integration的哪些部分连接在一起?
ruarlubt

ruarlubt1#

我无法在Spring Integration方面为您提供帮助,但您可能需要重新给予您的架构。在ESB系统中,当您知道消息的处理将花费相当长的时间时,或者如果您不确定远程端是否准备好了(另一个原因是桥接不兼容的组件),则通常将消息放置在队列中。当您将消息添加到队列时,您将立即返回给请求者,指示消息已收到,但不提供操作的结果。然后请求者需要轮询结果,或者您也可以提供某种“推送”功能。
因此,如果队列中的消息处理需要花费大量时间,我建议修改您的体系结构。Web客户端等待长时间的回复并不常见,许多请求也可能超时。
另一方面,如果消息的处理快速可靠,则不需要使用Queue通道。让所有的消息都与一个中心组件(Java EE Session Bean、Spring Bean、Web服务)通信,并自己实现一个队列机制。已经有答案涵盖了你如何做到这一点。

rkttyhzu

rkttyhzu2#

基于QueueChannel的Javadoc,这是我的尝试。这并不涉及Web服务配置,而只是涉及Web服务后端实现中的代码。
这是将某些内容添加到队列(您的Web服务)的代码。

public class TheWebService {

  // Could also use QueueChannel, or PollableChannel here instead
  // just picked the most general one
  private org.springframework.integration.channel.MessageChannel queue;

  public void yourWebServiceMethod(SomeArg arg) {
     SomeObjectToPassThatExtendsMessage passed = someInitialProcessing(arg);
     queue.send(passed);
  }
}

这是在接收器/处理器/出队类中的代码

public class TheProcessor {

  // Could also use QueueChannel here instead
  // just picked the most general one
  private org.springframework.integration.channel.PollableChannel queue;

  // This method needs to be setup to be called by a separate thread.
  // See http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/scheduling/package-summary.html
  // and it's sub-packages.
  public void someProcessingPoller() {
     SomeObjectToPassThatExtendsMessage passed = queue.receive();
     // Do some processing with the passed object.
  }

}

Spring配置看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">

  <bean id="webService" class="mypackage.TheWebService">
      <property name="queue" ref="queue" />
  </bean>

  <bean id="processor" class="mypackage.TheProcessor ">
      <property name="queue" ref="queue" />
  </bean>

  <bean id="queue" class="org.springframework.integration.channel.QueueChannel"/>
</beans>
2ic8powd

2ic8powd3#

请注意Spring Integration,但Java 5有许多可以处理FIFO的BlockingQueues。

3hvapo4f

3hvapo4f4#

您应该查看Spring Integration中的http(对于REST)或ws(对于POX/SOAP)“inbound-gateway”元素。任何一个都可以通过“request-channel”属性连接到共享的、队列支持的通道(通过同一网关返回的应答路由可以在后台处理)。我建议从浏览样本开始。这个博客可以帮助你启动和运行:http://blog.springsource.com/2010/09/29/new-spring-integration-samples/
希望能帮上忙。- 马克

but5z9lq

but5z9lq5#

问题不是Spring。我认为您需要一个包含请求和提供响应的元素的队列。但是响应需要阻塞,直到元素被dequed和处理。所以queue元素看起来像这样:

public class BlockingPair {
  private final RequestBodyType request;
  private ResponseBodyType response;

  public BlockingPair(RequestBodyType request) {
    this.request = request;
  }

  public RequestBodyType getRequest() {
    return request;
  }

  public ResponseBodyType getResponse() {
    while (response == null) {
      Thread.currentThread().sleep(10);
    }
    return response;
  }

  public void setResponse(ResponseBodyType response) {
    this.response = response;
  }
}

Webservice enqueing使用其请求主体创建BlockingPair。然后将BlockingPair元素推送到队列。然后,它从BlockingPair中获取响应主体,创建响应,但阻塞。
消费者deque一个BlockingPair并设置响应主体。从那里,Web服务继续写入响应。
你需要三颗豆子:Webservice、阻塞队列和消费者。Web服务和消费者都需要将队列作为bean属性。
队列和消费者bean需要在应用程序上下文中进行规划(由ContextLoaderListener初始化)。队列需要一个bean id才能被webservice引用(它有自己的上下文,但应用程序上下文作为父上下文,因此队列引用可以被引用):
关于web.xml

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
  <servlet-name>service</servlet-name>
  <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>service</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

applicationContext.xml包含两个bean:

<bean id="queue" class="java.util.concurrent.LinkedBlockingQueue"/>

<bean id="consumer" class="...">
  <property name="queue" ref="queue"/>
</bean>

webservice有自己的上下文定义,这里是service-servlet.xml

<bean id="endpoint" class="org.springframework.ws.server.endpoint....PayloadEndpoint">
  <property name="queue" ref="queue"/>
</bean>

有关定义spring ws端点的更多信息,请参见spring tutorial
消费者需要是一个后台任务,所以我更喜欢quartz,对于spring集成,请参阅here

相关问题