简体   繁体   English

使用Spring Cloud Stream的Spring REST请求响应

[英]Spring REST Request Response with Spring Cloud Stream

I am trying to connect a rest endpoint Request/Response with Spring cloud stream using Spring integration gateway. 我正在尝试使用Spring集成网关将其余端点的请求/响应与Spring云流连接。 The below code works for the first rest call, but subsequent calls do not work. 以下代码适用于第一个rest调用,但后续调用不起作用。 I understand that spring cloud stream is for messaging/async operations. 我知道Spring Cloud Stream是用于消息传递/异步操作的。 But this is a practical scenario where in which you need a request/response sync. 但这是一种实际情况,其中您需要请求/响应同步。

SpringBootApplication SpringBoot应用程序

package com.example.restgateway;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.dsl.HeaderEnricherSpec;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


@EnableBinding({RestGatewayApplication.GatewayChannels.class})
@SpringBootApplication
public class RestGatewayApplication {

  interface GatewayChannels {

    String TO_UPPERCASE_REPLY = "to-uppercase-reply";
    String TO_UPPERCASE_REQUEST = "to-uppercase-request";

    @Input(TO_UPPERCASE_REPLY)
    SubscribableChannel toUppercaseReply();

    @Output(TO_UPPERCASE_REQUEST)
    MessageChannel toUppercaseRequest();
  }

  @MessagingGateway
  public interface StreamGateway {
    @Gateway(requestChannel = ENRICH, replyChannel = GatewayChannels.TO_UPPERCASE_REPLY)
    String process(String payload);
  }

  private static final String ENRICH = "enrich";

  public static void main(String[] args) {
    SpringApplication.run(RestGatewayApplication.class, args);
  }

  @Bean
  public IntegrationFlow headerEnricherFlow() {
    return IntegrationFlows.from(ENRICH).enrichHeaders(HeaderEnricherSpec::headerChannelsToString)
        .channel(GatewayChannels.TO_UPPERCASE_REQUEST).get();
  }

  @RestController
  public class UppercaseController {
    @Autowired
    StreamGateway gateway;

    @GetMapping(value = "/uppercase/{string}",
        produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    public ResponseEntity<String> getUser(@PathVariable("string") String string) {
      return new ResponseEntity<String>(gateway.process(string), HttpStatus.OK);
    }
  }


  @StreamListener(GatewayChannels.TO_UPPERCASE_REQUEST)
  @SendTo(GatewayChannels.TO_UPPERCASE_REPLY)
  public Message<?> process(Message<String> request) {
    return MessageBuilder.withPayload(request.getPayload().toUpperCase())
        .copyHeaders(request.getHeaders()).build();
  }

}

application.yml application.yml

spring:
  cloud:
    stream:
      bindings:
        to-uppercase-request:
          destination: to-uppercase-request
          group: stream-to-uppercase-request
          producer:
            required-groups: stream-to-uppercase-request
        to-uppercase-reply:
          destination: to-uppercase-reply
          group: gateway-to-uppercase-reply
          producer:
           required-groups: gateway-to-uppercase-reply
      kafka:
        binder:
          brokers:
          - 192.168.34.210:9092
      default-binder: kafka


server:
  port: 8080

It's not clear what you are trying to do; 目前尚不清楚您要做什么。 the IntegrationFlow is sending a message directly to the input channel, bypassing the destination topic; IntegrationFlow正在绕过目标主题直接向输入通道发送消息; the reply (alternately) goes out via the topic and the replyChannel header (required by the gateway will be lost since it's not serializable). 答复(或者)通过主题和replyChannelreplyChannel (网关要求的消息将丢失,因为它不可序列化)。

It will work alternately because you have 2 subscribers on the reply channel - the gateway and the binding. 因为您在回复通道上有2个订阅者(网关和绑定),所以它将交替工作。 By default, when a channel has 2 subscribers, messages are distributed in round-robin fashion. 默认情况下,当一个频道有2个订阅者时,消息以循环方式分发。 One message will go to the gateway, the next to the binding, etc, etc. 一条消息将发送到网关,另一条消息将发送到绑定,等等,依此类推。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM