SpringBoot中使用SpringIntegration

简介

spring-integration是一个功能强大的EIP(Enterprise Integration Patterns),即企业集成模式。对,spring-integration是一个集大成者。就我自己的理解,集成了众多功能的它,是一种便捷的事件驱动消息框架用来在系统之间做消息传递的。
今天我们来探索一下如果使用它发送http请求。

什么是Spring Integration

Spring Integration在基于Spring的应用程序中实现轻量级消息传递,并支持通过声明适配器与外部系统集成。 Spring Integration的主要目标是提供一个简单的模型来构建企业集成解决方案,同时保持关注点的分离,这对于生成可维护,可测试的代码至关重要。Spring Framework鼓励开发人员使用接口进行编码,并使用依赖注入(DI)为普通旧Java对象(POJO)提供执行其任务所需的依赖项。 Spring Integration将这一概念更进一步,其中POJO使用消息传递范例连接在一起,并且各个组件可能不了解应用程序中的其他组件。这种应用程序是通过组装细粒度可重用组件来构建的,以形成更高级别的功能。通过精心设计,这些流程可以模块化,并在更高的层次上重复使用。

官方地址:spring-integration

核心类

下次补充,不敢误人子弟

快速入门

阅读官方文档它是这样描述的:

In the following “quick start” application you can see that the same gateway interface is used to invoke two completely different service implementations. To build and run this program you will need the spring-integration-ws and spring-integration-xml modules as described above.

大概意思是使用这个示例,需要spring-integration-wsspring-integration-xml两个模块,同时它使用了相同的网关接口调用了两个不同的服务实现。

编写快速启动类

public class Main {

        public static void main(String... args) throws Exception {
                ApplicationContext ctx =
                        new ClassPathXmlApplicationContext("context.xml");
                // Simple Service
                TempConverter converter =
                        ctx.getBean("simpleGateway", TempConverter.class);
                System.out.println(converter.fahrenheitToCelcius(68.0f));
                // Web Service
                converter  = ctx.getBean("wsGateway", TempConverter.class);
                System.out.println(converter.fahrenheitToCelcius(68.0f));
        }
 }

编写接口类

public interface TempConverter {

        float fahrenheitToCelcius(float fahren);

}

编写xml

<!-- Simple Service -->
<!-- 网关:simpleGateway -->
<int:gateway id="simpleGateway"
        service-interface="foo.TempConverter"
        default-request-channel="simpleExpression" />

<int:service-activator id="expressionConverter"
        input-channel="simpleExpression"
        expression="(payload - 32) / 9 * 5"/>

<!-- Web Service -->

<int:gateway id="wsGateway" service-interface="foo.TempConverter"
        default-request-channel="viaWebService" />

<int:chain id="wsChain" input-channel="viaWebService">
        <int:transformer
           expression="'&lt;FahrenheitToCelsius xmlns=&quot;https://www.w3schools.com/xml/&quot;&gt;&lt;Fahrenheit&gt;XXX&lt;/Fahrenheit&gt;&lt;/FahrenheitToCelsius&gt;'.replace('XXX', payload.toString())" />
        <int-ws:header-enricher>
                <int-ws:soap-action value="https://www.w3schools.com/xml/FahrenheitToCelsius"/>
        </int-ws:header-enricher>
        <int-ws:outbound-gateway
                uri="https://www.w3schools.com/xml/tempconvert.asmx"/>
        <int-xml:xpath-transformer
                xpath-expression="/*[local-name()='FahrenheitToCelsiusResponse']/*[local-name()='FahrenheitToCelsiusResult']"/></int:chain>

咦,嫌弃,和我们想用的内容有差距啊,,既然用SpringBoot那就得跟上节奏,JavaBean配置,接着往下看

And here is the same application (web service part) using the Java DSL (and Spring Boot). You will need the spring-boot-starter-integration dependency or spring-integration-java-dsl directly if you don’t use Spring Boot. If you use Spring Integration starting version 5.0, you don’t need any additional dependencies - the Java DSL is included to the core project

进入正题了,大意是使用JavaBean配置或者spring boot的示例,如果不实用Spring Boot那么就需要咱们手动加入spring-boot-starter-integration或者spring-integration-java-dsl所依赖的模块,如果使用的是5.0及以上的版本,那么你不需要手动引入依赖,Java DSL已经包含在其中

@Configuration
@SpringBootApplication
@IntegrationComponentScan
public class Application {

  public static void main(String[] args) {
    ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
    TempConverter converter = ctx.getBean(TempConverter.class);
    System.out.println(converter.fahrenheitToCelcius(68.0f));
    ctx.close();
  }

  @MessagingGateway
  public interface TempConverter {

    @Gateway(requestChannel = "convert.input")
    float fahrenheitToCelcius(float fahren);

  }

  @Bean
  public IntegrationFlow convert() {
      return f -> f
        .transform(payload ->
              "<FahrenheitToCelsius xmlns=\"https://www.w3schools.com/xml/\">"
            +     "<Fahrenheit>" + payload + "</Fahrenheit>"
            + "</FahrenheitToCelsius>")
        .enrichHeaders(h -> h
            .header(WebServiceHeaders.SOAP_ACTION,
                "https://www.w3schools.com/xml/FahrenheitToCelsius"))
        .handle(new SimpleWebServiceOutboundGateway(
            "https://www.w3schools.com/xml/tempconvert.asmx"))
        .transform(Transformers.xpath("/*[local-name()=\"FahrenheitToCelsiusResponse\"]"
            + "/*[local-name()=\"FahrenheitToCelsiusResult\"]"));
  }

}

开始使用

翻阅了一遍官网的samples,根本没找到http方式关于SpringBoot的示例,没事,咱们活学活用,参考其他模块,直接上代码

pom中加入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-integration</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-http</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>jackson-module-kotlin</artifactId>
                <groupId>com.fasterxml.jackson.module</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

编写测试类

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {

    @Autowired
    private Config.TempConverter tempConverter;

    @Test
    public void test() {
        //字符串方式
        final String info = tempConverter.hello("homeant");
        log.debug("info:{}", info);
        //实体对象方式
        log.debug("userInfo:{}", tempConverter.userInfo("homeant"));
    }


    @Configuration
    @EnableIntegration
    @IntegrationComponentScan
    @EnableAutoConfiguration
    public static class Config {
        @MessagingGateway
        public interface TempConverter {

            @Gateway(requestChannel = "convert.input")
            String hello(String name);

            @Gateway(requestChannel = "userInfo.input")
            UserInfo userInfo(String name);

        }

        @Bean
        public IntegrationFlow convert() {
            return f -> f.handle(Http.outboundGateway("https://api.github.com/users/{name}")
            .httpMethod(HttpMethod.GET)
            .expectedResponseType(String.class).uriVariable("name", r -> r.getPayload()))
            .log(LoggingHandler.Level.DEBUG).bridge();
        }

        @Bean
        public IntegrationFlow userInfo() {
            return f -> f.handle(Http.outboundGateway("https://api.github.com/users/{name}")
            .uriVariable("name", r -> r.getPayload())
            .httpMethod(HttpMethod.GET)
            .expectedResponseType(UserInfo.class))
            .log(LoggingHandler.Level.DEBUG).bridge();
        }
    }
}

启动测试类

[2019-09-30 22:11:54.977] [main] [DEBUG] [fun.vyse.cloud.test.ApplicationTest     :34  ] - info:{"login":"homeant","id":28803295,"node_id":"MDQ6VXNlcjI4ODAzMjk1","avatar_url":"https://avatars0.githubusercontent.com/u/28803295?v=4","gravatar_id":"","url":"https://api.github.com/users/homeant","html_url":"https://github.com/homeant","followers_url":"https://api.github.com/users/homeant/followers","following_url":"https://api.github.com/users/homeant/following{/other_user}","gists_url":"https://api.github.com/users/homeant/gists{/gist_id}","starred_url":"https://api.github.com/users/homeant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/homeant/subscriptions","organizations_url":"https://api.github.com/users/homeant/orgs","repos_url":"https://api.github.com/users/homeant/repos","events_url":"https://api.github.com/users/homeant/events{/privacy}","received_events_url":"https://api.github.com/users/homeant/received_events","type":"User","site_admin":false,"name":"俊晨","company":null,"blog":"https://tianhui.xin","location":"China-BeiJing","email":null,"hireable":null,"bio":"高山仰止,景行行止。虽不能至,心向往之","public_repos":15,"public_gists":0,"followers":3,"following":3,"created_at":"2017-05-19T08:53:17Z","updated_at":"2019-09-27T06:10:27Z"}
[2019-09-30 22:11:55.971] [main] [DEBUG] [fun.vyse.cloud.test.ApplicationTest     :35  ] - userInfo:UserInfo(login=homeant, id=28803295, node_id=MDQ6VXNlcjI4ODAzMjk1, avatar_url=https://avatars0.githubusercontent.com/u/28803295?v=4, gravatar_id=, url=https://api.github.com/users/homeant, html_url=https://github.com/homeant, followers_url=https://api.github.com/users/homeant/followers, following_url=https://api.github.com/users/homeant/following{/other_user}, gists_url=https://api.github.com/users/homeant/gists{/gist_id}, starred_url=https://api.github.com/users/homeant/starred{/owner}{/repo}, subscriptions_url=https://api.github.com/users/homeant/subscriptions, organizations_url=https://api.github.com/users/homeant/orgs, repos_url=https://api.github.com/users/homeant/repos, events_url=https://api.github.com/users/homeant/events{/privacy}, received_events_url=https://api.github.com/users/homeant/received_events, type=User, site_admin=false, name=俊晨, company=null, blog=https://tianhui.xin, location=China-BeiJing, email=null, hireable=null, bio=高山仰止,景行行止。虽不能至,心向往之, public_repos=15, public_gists=0, followers=3, following=3, created_at=2017-05-19T08:53:17Z, updated_at=2019-09-27T06:10:27Z)

参考文档

上一篇:没有了

下一篇:springBoot 定制自己的starter