Spring Integration完整示例

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。

在本课程中,向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来,您将深入研究Spring Integration的基础知识,例如通道,转换器和适配器。 在这里查看 !

目录

1.简介 2.系统概述 3.埃及剧院服务 4. Pantages剧院服务 5.用户界面 6.记录每个用户请求 7.丢弃无效的条目 8.选择要请求的剧院 9.请求埃及剧院 10.请求潘太及斯剧院 11.处理错误
11.1。 将消息存储到数据库 11.2。 向负责人发送电子邮件
12.关闭应用程序 13.看一看完整的流程 14.技术版本

1.简介

本教程将详细介绍一个应用程序的完整示例,该应用程序使用Spring Integration提供的多个组件来为其用户提供服务。 该服务由一个系统提示用户选择不同的剧院组成。 选择后,系统将向所选剧院的外部系统发出请求,并返回其可用电影的列表。 每个电影院通过不同的API提供服务; 我们将在解释每个外部系统的部分(第三部分和第四部分)中看到这一点。

2.系统概述

以下活动图显示了系统的高级视图。

图1

图1

  • 用户界面 :在图的左侧,我们开始了流程; 请求用户条目。 系统显示的该进入请求以及对用户的系统响应都是与流集成的示例。
  • Web服务调用 :根据用户的选择,系统将从另一个外部系统检索影片列表。 埃及剧院通过HTTP公开其服务,而潘塔基斯剧院则通过SOAP公开其服务。
  • 错误处理 :如果在流程中出现错误,可能是由于意外异常或Web服务不可用,系统会将信息发送到另外两个外部系统:noSQL数据库( MongoDB )和电子邮件地址。

下一部分将更深入地介绍该系统的每个部分。

3.埃及剧院服务

埃及剧院系统通过HTTP公开他的服务。 在本节中,我们将快速浏览该应用程序。 这是一个包含RESTful Web服务的Spring 4 MVC应用程序。

控制器将请求检索剧院中放映的所有可用电影:

@RestController
@RequestMapping(value="/films")
public class FilmController {FilmService filmService;@Autowiredpublic FilmController(FilmService service) {this.filmService = service;}@RequestMapping(method=RequestMethod.GET)public Film[] getFilms() {return filmService.getFilms();}
}

API很简单,并且在此示例中,服务将返回一些虚拟值,因为本节的重点是仅提供有关调用外部系统的更多细节:

@Service("filmService")
public class FilmServiceImpl implements FilmService {@Overridepublic Film[] getFilms() {Film film1 = new Film(1, "Bladerunner", "10am");Film film2 = new Film(2, "Gran Torino", "12pm");return new Film[]{film1, film2};}
}

Spring配置基于注释:

<!-- Detects annotations like @Component, @Service, @Controller, @Repository, @Configuration -->
<context:component-scan base-package="xpadro.spring.mvc.films.controller,xpadro.spring.mvc.films.service"/><!-- Detects MVC annotations like @RequestMapping -->
<mvc:annotation-driven/>

web.xml文件配置Web应用程序:

<!-- Root context configuration -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:xpadro/spring/mvc/config/root-context.xml</param-value>
</context-param><!-- Loads Spring root context, which will be the parent context -->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- Spring servlet -->
<servlet><servlet-name>springServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:xpadro/spring/mvc/config/app-context.xml</param-value></init-param>
</servlet>
<servlet-mapping><servlet-name>springServlet</servlet-name><url-pattern>/spring/*</url-pattern>
</servlet-mapping>

因此,系统将处理发送到http://localhost:8080/rest-films/spring/films请求,其中rest-films是应用程序的上下文路径。

4. Pantages剧院服务

Pantages Theatre服务通过SOAP公开其服务。 像埃及剧院一样,它包含在Web应用程序中,但在这种情况下,它是通过Spring Web Services实现的 。

该终结filmRequest使用名称空间http://www.xpadro.spring.samples.com/films服务于filmRequest请求。 响应是从电影服务收到的结果中构建的:

@Endpoint
public class FilmEndpoint {@Autowiredprivate FilmService filmService;@PayloadRoot(localPart="filmRequest", namespace="http://www.xpadro.spring.samples.com/films")public @ResponsePayload FilmResponse getFilms() {return buildResponse();}private FilmResponse buildResponse() {FilmResponse response = new FilmResponse();for (Film film : filmService.getFilms()) {response.getFilm().add(film);}return response;}
}

电影服务也是虚拟服务,它将返回一些默认值:

@Service
public class FilmServiceImpl implements FilmService {@Overridepublic List<Film> getFilms() {List<Film> films = new ArrayList<>();Film film = new Film();film.setId(new BigInteger(("1")));film.setName("The Good, the Bad and the Uggly");film.setShowtime("6pm");films.add(film);film = new Film();film.setId(new BigInteger(("2")));film.setName("The Empire strikes back");film.setShowtime("8pm");films.add(film);return films;}
}

Spring配置如下所示:

<!-- Detects @Endpoint since it is a specialization of @Component -->
<context:component-scan base-package="xpadro.spring.ws"/><!-- detects @PayloadRoot -->
<ws:annotation-driven/><ws:dynamic-wsdl id="filmDefinition" portTypeName="Films" locationUri="http://localhost:8080/ws-films"><ws:xsd location="/WEB-INF/schemas/xsd/film-service.xsd"/>
</ws:dynamic-wsdl>

最后, web.xml文件:

<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:xpadro/spring/ws/config/root-config.xml</param-value>
</context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><servlet><servlet-name>Films Servlet</servlet-name><servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:xpadro/spring/ws/config/servlet-config.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet><servlet-mapping><servlet-name>Films Servlet</servlet-name><url-pattern>/films/*</url-pattern>
</servlet-mapping>

根据此配置,Pantages Theatre应用程序将处理发送到http://localhost:8080/ws-films/films请求,其中ws-films是应用程序的上下文路径。

5.用户界面

一旦我们了解了将与Spring Integration应用程序进行通信的外部系统是什么,让我们继续看一下如何构建此应用程序。

独立应用程序从引导Spring上下文的主要方法开始,该方法包含我们所有的集成组件。 接下来,它提示用户输入他的选择:

public class TheaterApp {private static Logger logger = LoggerFactory.getLogger("mainLogger");static AbstractApplicationContext context;public static void main(String[] args) {context = new ClassPathXmlApplicationContext("classpath:xpadro/spring/integration/config/int-config.xml");context.registerShutdownHook();logger.info("\\nSelect your option (1-Egyptian Theater / 2-Pantages Theater / 0-quit):\\n");}public static void shutdown() {logger.info("Shutting down...");context.close();}
}

该应用程序还实现了一种关闭方法,该方法将由用户调用。 我们将在后面的部分中更详细地介绍这一点。

好的,现在用户选择将如何进入消息传递系统? 这是与流集成起作用的地方。 消息传递系统的系统条目是使用入站通道适配器实现的,该适配器将从stdin( System.in )中读取。

<!-- System entry -->
<int-stream:stdin-channel-adapter id="consoleIn" channel="systemEntry"><int:poller fixed-delay="1000" max-messages-per-poll="1" />
</int-stream:stdin-channel-adapter>

通过使用轮询器,入站通道适配器将尝试每秒从System.read中读取并将结果放入systemEntry通道。

现在,我们收到了一条带有用户条目作为其有效负载的Spring Integration消息。 我们可以使用端点来转换数据并将其发送到所需的系统。 示例:控制台将提示用户在不同的剧院之间进行选择:

2014-04-11 13:04:32,959|AbstractEndpoint|started org.springframework.integration.config.ConsumerEndpointFactoryBean#7Select your option (1-Egyptian Theater / 2-Pantages Theater / 0-quit):

6.记录每个用户请求

系统要做的第一件事是记录用户选择。 这是通过使用丝锥完成的 。 此窃听是拦截器的实现,该拦截器将拦截通过通道(在我们的情况下为systemEntry通道)传播的消息。 它不会改变流量; 该消息将继续到达其目的地,但有线分流器还将其发送到另一个通道,通常用于监视。

在我们的应用程序中,该消息还将发送到日志记录通道适配器。

<int:channel id="systemEntry"><int:interceptors><int:wire-tap channel="requestLoggingChannel"/></int:interceptors>
</int:channel><int:logging-channel-adapter id="requestLoggingChannel" expression="'User selection: '.concat(payload)" level="INFO"/>

日志记录通道适配器由LoggingChannelAdapterParser实现。 它基本上创建了一个LoggingHandler ,它将使用Apache Commons Logging库记录消息的有效负载。 如果要记录完整消息而不是仅记录其有效负载,则可以将log-full-message属性添加到log-full-message记录通道适配器。

示例:日志显示用户所做的选择

Select your option (1-Egyptian Theater / 2-Pantages Theater / 0-quit):1
2014-04-11 13:06:07,110|LoggingHandler|User selection: 1

7.丢弃无效的条目

看一眼用户提示,我们看到系统接受三个有效条目:

logger.info("\\nSelect your option (1-Egyptian Theater / 2-Pantages Theater / 0-quit):\\n")

无效条目的处理非常简单; 系统将过滤无效条目,以防止它们在流程中向前移动。 这些丢弃的消息然后将被发送到discards通道。

订阅invalidEntries丢弃通道,还有另一个流通道适配器,在这种情况下,是出站适配器:

<int:filter input-channel="systemEntry" output-channel="validEntriesChannel" ref="entryFilter" discard-channel="invalidEntries"/><!-- Invalid entries (show on console) -->
<int:chain input-channel="invalidEntries"><int:transformer ref="discardsTransformer"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" />
</int:chain>

该适配器的功能是写入stdout( System.out ),因此用户将收到用户在控制台上输入了无效请求的信息。

要记住的一件事是我们没有创建invalidEntries通道。 适配器将通过匿名临时直接通道连接到过滤器。

示例:控制台显示用户输入了无效的选择。

Select your option (1-Egyptian Theater / 2-Pantages Theater / 0-quit):8
2014-04-11 13:07:41,808|LoggingHandler|User selection: 8
Invalid entry: 8

8.选择要请求的剧院

成功通过上一个过滤器的有效条目将被发送到路由器:

<!-- Valid entries (continue processing) -->
<int:channel id="validEntriesChannel" />
<int:router input-channel="validEntriesChannel" ref="cinemaRedirector"/>

该路由器负责确定用户需要哪个外部系统的信息。 它还将检测用户何时要关闭该应用程序:

@Component("cinemaRedirector")
public class CinemaRedirector {private static final String CINEMA_EGYPTIAN_CHANNEL = "egyptianRequestChannel";private static final String CINEMA_PANTAGES_CHANNEL = "pantagesRequestChannel";private static final String QUIT_REQUEST_CHANNEL = "quitRequestChannel";@Routerpublic String redirectMessage(Message<String> msg) {String payload = msg.getPayload();if ("1".equals(payload)) {return CINEMA_EGYPTIAN_CHANNEL;}else if ("2".equals(payload)) {return CINEMA_PANTAGES_CHANNEL;}return QUIT_REQUEST_CHANNEL;}
}

因此,这里的流程分为三个不同的通道,每个剧院的请求和完成流程的请求。

9.请求埃及剧院

为了与埃及剧院系统进行通信,我们需要发送一个HTTP请求。 我们通过使用HTTP出站网关来完成此任务。

<int-http:outbound-gateway url="http://localhost:8080/rest-films/spring/films" expected-response-type="java.lang.String" http-method="GET" charset="UTF-8"/>

该网关配置了几个属性:

  • expected-response-type :Web服务返回的返回类型将是一个字符串,其中包含带有电影列表的JSON。
  • http-method :我们正在发出GET请求。
  • charset :用于将有效载荷转换为字节的字符集。

收到响应后,我们将使用转换器将返回的JSON转换为Java对象。 在我们的例子中,我们将响应转换为Film数组:

<int:json-to-object-transformer type="xpadro.spring.integration.model.Film[]"/>

接下来,服务激活器将遍历数组并构建更适合用户的String。

<int:service-activator ref="restResponseHandler"/>

实现如下所示:

@Component("restResponseHandler")
public class RestResponseHandler {private static final String NEW_LINE = "\\n";@ServiceActivatorpublic String handle(Message<Film[]> msg) {Film[] films = msg.getPayload();StringBuilder response = new StringBuilder(NEW_LINE);if (films.length > 0) {response.append("Returned films:" + NEW_LINE);}else {response.append("No films returned" + NEW_LINE);}for (Film f:films) {response.append(f.getName()).append(NEW_LINE);}return response.toString();}
}

最后,我们将通过在控制台上打印响应显示给用户。 我们正在使用与用于向用户显示其无效条目的通道适配器相同的通道适配器。 适配器将写入System.out:

<int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" />

下一个代码段显示了完整的请求。 由于我不想为这些端点之间的每次交互创建消息通道,因此我使用了消息处理程序链。 当我们在序列中有多个端点时,这种类型的端点简化了所需的XML配置。 通过使用消息处理程序链,其所有端点都通过匿名直接通道连接。

<!-- Egyptian Theater request -->
<int:chain input-channel="egyptianRequestChannel"><int-http:outbound-gateway url="http://localhost:8080/rest-films/spring/films" expected-response-type="java.lang.String" http-method="GET" charset="UTF-8"/><int:json-to-object-transformer type="xpadro.spring.integration.model.Film[]"/><int:service-activator ref="restResponseHandler"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" />
</int:chain>

示例:向用户显示了埃及剧院的电影列表。

1
2014-04-11 14:26:20,981|LoggingHandler|User selection: 1Returned films:
Bladerunner
Gran Torino

10.请求潘太及斯剧院

我们将需要一个Web服务网关来与Pantages Theatre系统进行交互,但是首先,我们必须构建一个filmRequest类型的请求对象,以便由埃及Web服务端点进行服务。

我们正在使用转换器将消息更改为电影Web服务请求:

<int:transformer ref="soapRequestTransformer"/>

实现:

@Component("soapRequestTransformer")
public class SoapRequestTransformer {@Transformerpublic Message<?> createRequestMessage(Message<String> msg) {return MessageBuilder.withPayload(new FilmRequest()).copyHeadersIfAbsent(msg.getHeaders()).build();}
}

我们获得了请求对象,因此我们现在可以使用Web服务网关来调用Web服务:

<int-ws:outbound-gateway uri="http://localhost:8080/ws-films/films" marshaller="marshaller" unmarshaller="marshaller"/>

如上一教程中所述,将需要编组器来转换请求和响应。 对于此任务,我们将使用oxm名称空间:

<oxm:jaxb2-marshaller id="marshaller" contextPath="xpadro.spring.integration.ws.types" />

当我们收到Web服务响应时,它将采用FilmResponse的形式。 序列中的下一个端点将调整响应并返回一个String,以便在下一阶段向用户显示:

<int:service-activator ref="soapResponseHandler"/>

实现:

@Component("soapResponseHandler")
public class SoapResponseHandler {private static final String NEW_LINE = "\\n";@ServiceActivatorpublic String handle(Message<FilmResponse> msg) {FilmResponse response = msg.getPayload();StringBuilder resp = new StringBuilder(NEW_LINE);if (response.getFilm().size() > 0) {resp.append("Returned films:" + NEW_LINE);}else {resp.append("No films returned" + NEW_LINE);}for (Film f : response.getFilm()) {resp.append(f.getName()).append(NEW_LINE);}return resp.toString();}
}

与埃及请求一样,该请求也以另一个流出站通道适配器结束:

<int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" />

由于我们还有另一个端点序列,因此我们使用消息处理程序链来最大程度地减少所需的配置量:

<!-- Pantages Theater request -->
<int:chain input-channel="pantagesRequestChannel"><int:transformer ref="soapRequestTransformer"/><int-ws:outbound-gateway uri="http://localhost:8080/ws-films/films" marshaller="marshaller" unmarshaller="marshaller"/><int:service-activator ref="soapResponseHandler"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" />
</int:chain>

示例:向用户显示了Pantages Theatre电影列表。

2
2014-04-11 14:27:54,796|LoggingHandler|User selection: 2Returned films:
The Good, the Bad and the Uggly
The Empire strikes back

11.处理错误

如果出现任何问题,我们需要以某种方式进行注册。 发生这种情况时,应用程序将执行以下两项操作:

  • 将消息存储到数据库。
  • 发送电子邮件到指定地址。

Spring Integration消息通道名为errorChannel将接收消息处理程序抛出的MessagingException类型的错误。 这个特殊频道是一个发布-订阅频道,这意味着它可以有多个订阅者。 我们的应用程序订阅了两个端点,以便执行先前指定的两个操作。

将消息存储到数据库

以下服务激活器已预订到错误通道,因此它将收到MessagingException:

<int:service-activator ref="mongodbRequestHandler"/>

这个激活器将要做的是解决将请求发送到哪个剧院,然后它将构建一个FailedMessage对象,其中包含我们要记录的信息:

@Component("mongodbRequestHandler")
public class MongodbRequestHandler {private Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate TheaterResolver theaterResolver;public FailedMessage handle(MessagingException exc) {logger.error("Request failed. Storing to the database");String theater = theaterResolver.resolve(exc);FailedMessage failedMsg = new FailedMessage(new Date(), exc.getMessage(), theater);return failedMsg;}
}

失败的消息结构包含基本信息:

public class FailedMessage implements Serializable {private static final long serialVersionUID = 4411815706008283621L;private final Date requestDate;private final String messsage;private final String theater;public FailedMessage(Date requestDate, String message, String theater) {this.requestDate = requestDate;this.messsage = message;this.theater = theater;}public Date getRequestDate() {return new Date(requestDate.getTime());}public String getMessage() {return this.messsage;}public String getTheater() {return this.theater;}
}

构建消息后,我们将使用mongodb出站通道适配器将其存储到数据库中:

<int-mongodb:outbound-channel-adapter id="mongodbAdapter" collection-name="failedRequests" mongodb-factory="mongoDbFactory" />

这部分流程的完整代码如下所示:

<import resource="mongodb-config.xml"/><int:chain input-channel="errorChannel"><int:service-activator ref="mongodbRequestHandler"/><int-mongodb:outbound-channel-adapter id="mongodbAdapter" collection-name="failedRequests" mongodb-factory="mongoDbFactory" />
</int:chain>

mongodb-config.xml文件包含特定于MongoDB配置的信息:

<bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory"><constructor-arg><bean class="com.mongodb.Mongo"/></constructor-arg><constructor-arg value="jcgdb"/>
</bean><bean id="mongoDbMessageStore" class="org.springframework.integration.mongodb.store.ConfigurableMongoDbMessageStore"><constructor-arg ref="mongoDbFactory"/>
</bean>

示例:以下屏幕快照显示了两个失败请求后的集合,每个剧院类型一个:

图2

图2

向负责人发送电子邮件

订阅错误通道的另一个端点是邮件请求处理程序。

<int:service-activator ref="mailRequestHandler"/>

此处理程序负责创建MailMessage以便将其发送到邮件网关:

@Component("mailRequestHandler")
public class MailRequestHandler {private Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate TheaterResolver theaterResolver;@ServiceActivatorpublic MailMessage handle(MessagingException exc) {logger.error("Request failed. Sending mail");MailMessage mailMsg = new SimpleMailMessage();mailMsg.setFrom("Theater.System");mailMsg.setTo("my.mail@gmail.com");mailMsg.setSubject("theater request failed");String theater = theaterResolver.resolve(exc);StringBuilder textMessage = new StringBuilder("Invocation to ").append(theater).append(" failed\\n\\n").append("Error message was: ").append(exc.getMessage());mailMsg.setText(textMessage.toString());return mailMsg;}
}

剧院解析器检查用户选择,并返回所请求剧院的名称。

完整的配置如下:

<int:chain input-channel="errorChannel"><int:service-activator ref="mailRequestHandler"/><int-mail:outbound-channel-adapter mail-sender="mailSender" />
</int:chain><import resource="mail-config.xml"/>

mail-config.xml包含Spring邮件发件人的配置:

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"><property name="host" value="smtp.gmail.com" /><property name="port" value="465" /><property name="username" value="my.mail@gmail.com" /><property name="password" value="myPassword" /><property name="javaMailProperties"><props><prop key="mail.smtp.starttls.enable">true</prop><prop key="mail.smtp.auth">true</prop><prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop></props></property>
</bean>

示例:邮件发送到gmail帐户:

图3

图3

12.关闭应用程序

出现提示时,用户可以通过输入零来决定完成应用程序的执行。 当他决定这样做时,路由器会将消息重定向到quitRequestChannel通道(请参阅第8节)。 订阅此频道,我们已经配置了消息处理程序链:

<!-- Quit message (shutdown application) -->
<int:chain input-channel="quitRequestChannel"><int:service-activator ref="shutdownActivator"/><int-event:outbound-channel-adapter/>
</int:chain>

服务激活器将创建一个ShutdownEvent并将其返回,以便由消息处理程序链的下一个端点进行处理:

@Component("shutdownActivator")
public class ShutdownActivator {@ServiceActivatorpublic ShutdownEvent createEvent(Message<String> msg) {return new ShutdownEvent(this);}
}

ShutdownEventApplicationEvent的实例。

public class ShutdownEvent extends ApplicationEvent {private static final long serialVersionUID = -198696884593684436L;public ShutdownEvent(Object source) {super(source);}public ShutdownEvent(Object source, String message) {super(source);}public String toString() {return "Shutdown event";}
}

事件出站通道适配器将发布为ApplicationEvent ,将发送到订阅该通道的任何消息。 这样,它们将由在应用程序上下文中注册的任何ApplicationListener实例处理。 但是,如果消息的有效负载是ApplicationEvent的实例,则它将按原样传递。 如前面的代码所示,我们的ShutdownEventApplicationEvent一个实例。

侦听此类事件,我们已经注册了一个侦听器:

@Component("shutdownListener")
public class ShutdownListener implements ApplicationListener<ShutdownEvent> {@Overridepublic void onApplicationEvent(ShutdownEvent event) {TheaterApp.shutdown();}
}

侦听器用于关闭应用程序。 如果您记得第五节中的关闭方法, Theater应用程序将关闭应用程序上下文。

13.看一看完整的流程

为了简化起见,我将所有集成元素都放在同一个文件中,但是我们可以考虑将其拆分为较小的文件:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:int="http://www.springframework.org/schema/integration"xmlns:int-jms="http://www.springframework.org/schema/integration/jms"xmlns:int-stream="http://www.springframework.org/schema/integration/stream"xmlns:int-event="http://www.springframework.org/schema/integration/event"xmlns:int-http="http://www.springframework.org/schema/integration/http"xmlns:int-ws="http://www.springframework.org/schema/integration/ws"xmlns:int-mongodb="http://www.springframework.org/schema/integration/mongodb"xmlns:int-mail="http://www.springframework.org/schema/integration/mail"xmlns:oxm="http://www.springframework.org/schema/oxm"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-3.0.xsdhttp://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms-3.0.xsdhttp://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream-3.0.xsdhttp://www.springframework.org/schema/integration/event http://www.springframework.org/schema/integration/event/spring-integration-event-3.0.xsdhttp://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-3.0.xsdhttp://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws-3.0.xsdhttp://www.springframework.org/schema/integration/mongodb http://www.springframework.org/schema/integration/mongodb/spring-integration-mongodb-3.0.xsdhttp://www.springframework.org/schema/integration/mail http://www.springframework.org/schema/integration/mail/spring-integration-mail-3.0.xsdhttp://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"><context:component-scan base-package="xpadro.spring.integration"/><!-- System entry --><int-stream:stdin-channel-adapter id="consoleIn" channel="systemEntry"><int:poller fixed-delay="1000" max-messages-per-poll="1" /></int-stream:stdin-channel-adapter><int:channel id="systemEntry"><int:interceptors><int:wire-tap channel="requestLoggingChannel"/></int:interceptors></int:channel><int:logging-channel-adapter id="requestLoggingChannel" expression="'User selection: '.concat(payload)" level="INFO"/><int:filter input-channel="systemEntry" output-channel="validEntriesChannel" ref="entryFilter" discard-channel="invalidEntries"/><!-- Invalid entries (show on console) --><int:chain input-channel="invalidEntries"><int:transformer ref="discardsTransformer"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" /></int:chain><!-- Valid entries (continue processing) --><int:channel id="validEntriesChannel" /><int:router input-channel="validEntriesChannel" ref="cinemaRedirector"/><!-- Quit message (shutdown application) --><int:chain input-channel="quitRequestChannel"><int:service-activator ref="shutdownActivator"/><int-event:outbound-channel-adapter/></int:chain><!-- Continue processing (get data) --><!-- Pantages Theater request --><int:chain input-channel="pantagesRequestChannel"><int:transformer ref="soapRequestTransformer"/><int-ws:outbound-gateway uri="http://localhost:8080/ws-films/films" marshaller="marshaller" unmarshaller="marshaller"/><int:service-activator ref="soapResponseHandler"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" /></int:chain><oxm:jaxb2-marshaller id="marshaller" contextPath="xpadro.spring.integration.ws.types" /><!-- Egyptian Theater request --><int:chain input-channel="egyptianRequestChannel"><int-http:outbound-gateway url="http://localhost:8080/rest-films/spring/films" expected-response-type="java.lang.String" http-method="GET" charset="UTF-8"/><int:json-to-object-transformer type="xpadro.spring.integration.model.Film[]"/><int:service-activator ref="restResponseHandler"/><int-stream:stdout-channel-adapter id="consoleOut" append-newline="true" /></int:chain><!-- Error handling --><import resource="mongodb-config.xml"/><int:chain input-channel="errorChannel"><int:service-activator ref="mongodbRequestHandler"/><int-mongodb:outbound-channel-adapter id="mongodbAdapter" collection-name="failedRequests" mongodb-factory="mongoDbFactory" /></int:chain><int:chain input-channel="errorChannel"><int:service-activator ref="mailRequestHandler"/><int-mail:outbound-channel-adapter mail-sender="mailSender" /></int:chain><import resource="mail-config.xml"/></beans>

14.技术版本

对于此应用程序,我使用了Spring框架的3.2.8发行版和Spring Integration的最新3.0.2发行版。

完整的依赖项列表如下所示:

<properties><spring-version>3.2.8.RELEASE</spring-version><spring-integration-version>3.0.2.RELEASE</spring-integration-version><slf4j-version>1.7.5</slf4j-version><jackson-version>2.3.0</jackson-version><javax-mail-version>1.4.1</javax-mail-version>
</properties><dependencies><!-- Spring Framework - Core --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring-version}</version></dependency><!-- Spring Framework - Integration --><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-core</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-jms</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-stream</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-event</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-http</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-ws</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-mongodb</artifactId><version>${spring-integration-version}</version></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-mail</artifactId><version>${spring-integration-version}</version></dependency><!-- javax.mail --><dependency><groupId>javax.mail</groupId><artifactId>mail</artifactId><version>${javax-mail-version}</version></dependency><!-- Jackson --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson-version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson-version}</version></dependency><!-- Logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j-version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j-version}</version></dependency>
</dependencies>

翻译自: https://www.javacodegeeks.com/2015/09/spring-integration-full-example.html

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

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

相关文章

配置环境_JavaJDK环境变量配置

1.Java环境搭建1.1 JDK与JREJDK(Java Development Kit Java开发工具包)JDK是提供给Java开发人员使用的&#xff0c;其中包含了java的开发工具&#xff0c;也包括了JRE。所以安装了JDK&#xff0c;就不用在单独安装JRE了。其中开发工具&#xff1a;编译工具(javac.exe)打包工具(…

僵固式思维 OR 成长式思维

有意无意中&#xff0c;看到这样的一篇文章&#xff0c;觉得非常富有正能量&#xff0c;而且也比较有同感。而且&#xff0c;不仅仅对于职场暂时失落或者失意的人有帮助&#xff0c;就是对学生&#xff0c;也一样的。故特分享&#xff0c;以共勉之。 我想每个新人进入职场之后都…

Asp.net MVC 的一些总结(二)——图片显示

这里实现的是&#xff0c;如下图片所示的效果&#xff1a; 当然&#xff0c;当你看的下图的时候&#xff0c;请不要自己想当然的认为是简单的html布局&#xff01;&#xff01;&#xff01; &#xff08;1&#xff09;业务说明&#xff1a;图片地址是数据库里存的&#xff0c;图…

Spring整合基础

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中&#xff0c;向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来&#xff0c;您将深入研究Spring Integration的基础知识&#xff0c;例如通道&#xff0c;转换器和适…

java 布局管理器_有时在Java中,一个布局管理器是不够的

java 布局管理器在开发Java Swing应用程序时&#xff0c;最经常的是&#xff0c;我们需要在多个嵌套面板中使用多个布局管理器。 这通常不是问题&#xff0c;被认为是几乎所有人类已知语言的所有UI开发的常规做法。 但是&#xff0c;大多数情况下&#xff0c;对于UI中的每个面板…

支付宝支付、微信支付(最详细教程)

对接支付宝支付接口&#xff0c;官方文档已经写的很清楚了&#xff0c;但是也有很多像我一样的小白&#xff0c;第一次对接支付宝支付接口&#xff0c;会有些迷茫&#xff0c;所以我在此写下这篇文章&#xff0c;给我和我一样的同学&#xff0c;一点思路吧。 第一步&#xff1…

降雨插值_ArcGIS计算土壤侵蚀模数(二)降雨侵蚀力因子R计算

本次采用中国土壤流失方程CSLE计算土壤侵蚀模数&#xff0c;计算公式为&#xff1a;ARKLSBET式中&#xff0c;式中&#xff1a;A—土壤侵蚀模数。thm-2a-1&#xff1b;R—降雨侵蚀力因子&#xff0c;MJmmhm-2h-1a-1&#xff1b;K—土壤可蚀性因子&#xff0c;thm2hhm-2MJmm-1&a…

购买阿里云ECS服务器忘记终端管理密码或者没有设置

自己开发一个APP,想把源码放到服务器上跑一跑,发现使用Xshell远程连接不上去,我记得买服务器的时候没有设置。 一般有两种方法: 1.买服务器的时候,阿里会给你发一份邮件,邮件里面有,这个是官方的说法,我是公司CTO,账号是老板开的,根本不可能看到邮件,所以对我来说不…

输出空格隔开换行_【前端干货】CSS 的空格处理

一空格规则HTML 代码的空格通常会被浏览器忽略。<p>◡◡hello◡◡world◡◡</p>上面是一行 HTML 代码&#xff0c;文字的前部、内部和后部各有两个空格。为了便于识别&#xff0c;这里使用半圆形符号◡表示空格。浏览器的输出结果如下。hello world可以看到&#x…

宝塔面板绑定域名导致无法访问

用这个命令rm -f /www/server/panel/data/domain.conf删除绑定域名后&#xff0c; 就能用ip端口进入面板了&#xff0c;以后还是不要绑定域名了 主要是因为我手残。 看重点&#xff0c;我是绑定了域名&#xff0c;用域名也无法访问。 现在终于进去啦

宝塔访问域名访问不到

首先说明一点&#xff0c;我这个问题不是宝塔面板绑定域名的那种情况。 浏览器输入域名会报上面的错误&#xff0c;经过各种尝试&#xff0c;发现是安全组没有放开&#xff0c;在阿里云控制台添加一个80/80的通用安全组规则即可&#xff0c;知道上行和下行的区别&#xff0c;打…

双千兆和双频千兆哪个好_关于千兆路由器的那些事儿!赶紧收藏

无线Wi-Fi已成为现代人生活、工作的标配&#xff0c;随着百兆乃至千兆的光纤网络普及&#xff0c;传统路由器已跟不上时代的速度了。不少用户的眼光已投向速度更快的千兆路由器&#xff0c;那么大家真的了解什么是千兆路由器吗&#xff1f;千兆路由器有哪几种&#xff1f;近期火…

华三ospf联动bfd_HCIE2020__路由交换专家__BFD综合实验

1.1.1 关于本实验本实验通过配置BFD与BGP协议联动及与VRRP协议联动&#xff0c;掌握BFD的功能和配置方法。1.1.2 实验目的理解BFD的工作原理。 掌握BFD与BGP联动的应用场景及配置方法。 掌握BFD与VRRP联动的应用场景及配置方法。1.1.3 实验组网介绍图1-1 BFD原理配置实验拓扑图…

大学生助学贷款如何还利息(本金+利息都可以)

生源地助学贷款还利息的步骤: 1、首先需要将钱转入支付宝,金额稍微高于应还款项即可。然后登陆电脑版支付宝,一定是要电脑登陆(手机上无法操作),如图所示 2、然后在支付宝主页中,点击右上角的“应用中心”,然后点击“生活服务”如图所示。

谷歌浏览器下载的内容老是自动打开

原因是每次下载内容在浏览器左下角都有提示&#xff0c;一般都是选择打开所在文件夹&#xff0c;一次手残&#xff0c;点了总是打开此文件导致一下载文件就自动打开。 解决方法。 1.点击右上角的... 2.找到设置-高级设置-下载 3.关掉我标红的位置信息即可。现在看不到啦&…

JBoss Fuse 6.2发布–指导如何快速尝试

在上周的红帽峰会上&#xff0c;宣布发布了JBoss Fuse 6.2 。 我要祝贺保险丝团队发布此版本。 我知道他们今年以来一直非常努力地进行质量检查&#xff0c;并确保质量检查通过了企业产品所期望的高品质壁垒。 因此&#xff0c;带着我的Camel帽子&#xff0c;很高兴看到包含最…

插入文件找不到桌面了?

解决方法&#xff0c;在那个界面空白处&#xff0c;右键显示所有文件即可。

mysql自增长主键_MySQL数据库8(九)列属性之主键、自增长

主键顾名思义&#xff0c;主要的键&#xff0c;primary key&#xff0c;在一张表中&#xff0c;有且只有一个字段&#xff0c;里面的值具有唯一性创建主键随表创建系统提供了两种增加主键的方式&#xff1a;1、直接在需要当做主键的字段之后&#xff0c;增加primary key属性来确…

初学者如何学编程呢

先简单做个测试,这样就能找出你比较适合哪种语言。 下面简单介绍一下不同的语言吧

CellSet 遍历

CellSet 结构&#xff1a; 查询MDX&#xff1a; SELECT NON EMPTY {{ {{ {{ {{ {{ AddCalculatedMembers([店铺.店铺ID].[店铺ID].Members)}} }} }} }} }} DIMENSION PROPERTIES MEMBER_TYPE , [店铺.店铺ID].[店铺ID].[国家], [店铺.店铺ID].[店铺ID].[区域], [店铺.…