提交 399b96d7 编写于 作者: 茶陵後's avatar 茶陵後 👍

#1 静态文件复制

上级 a321352d

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -5,7 +5,7 @@
"readme:copy": "cp -r README.md readme docs/ && cp -r README.md readme docs/en/",
"seo:copy": "cp -r seo/*.* docs/.vuepress/dist/",
"fix-memory-limit": "cross-env LIMIT=8192 increase-memory-limit",
"mv":"rm -rf public && mkdir -p public && mv docs/.vuepress/dist public"
"mv":"rm -rf public && mkdir public && cp -rf docs/.vuepress/dist/ public/"
},
"devDependencies": {
"cross-env": "^7.0.3",
......
此差异已折叠。
rAiSqm9/qDzLic/YPihA
\ No newline at end of file
此差异已折叠。
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{430:function(t,e,r){t.exports=r.p+"assets/img/quick-img-1-12bfde9c5c280b1940d85dee3d81772d.e4640717.png"},431:function(t,e,r){t.exports=r.p+"assets/img/quick-img2-ac5ae88c60ffaa062234a580f9f1abc3.d814978e.png"},432:function(t,e,r){t.exports=r.p+"assets/img/quick-img3-afa0a1fe446db8e3c8c7a8d9ca532d23.668ef3e3.png"},803:function(t,e,r){"use strict";r.r(e);var a=r(56),n=Object(a.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"spring-快速入门指南"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#spring-快速入门指南"}},[t._v("#")]),t._v(" Spring 快速入门指南")]),t._v(" "),a("h2",{attrs:{id:"您将构建什么"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#您将构建什么"}},[t._v("#")]),t._v(" 您将构建什么")]),t._v(" "),a("p",[t._v("您将构建一个经典的“Hello World!” 任何浏览器都可以连接的终端。你甚至可以告诉它你的名字,它会以更友好的方式回应。")]),t._v(" "),a("h2",{attrs:{id:"你需要什么"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#你需要什么"}},[t._v("#")]),t._v(" 你需要什么")]),t._v(" "),a("p",[a("strong",[t._v("集成开发人员环境 (IDE)")])]),t._v(" "),a("p",[t._v("热门选择包括"),a("a",{attrs:{href:"https://www.jetbrains.com/idea/",target:"_blank",rel:"noopener noreferrer"}},[t._v("IntelliJ IDEA"),a("OutboundLink")],1),t._v(","),a("a",{attrs:{href:"https://spring.io/tools",target:"_blank",rel:"noopener noreferrer"}},[t._v("Spring Tools"),a("OutboundLink")],1),t._v(","),a("a",{attrs:{href:"https://code.visualstudio.com/docs/languages/java",target:"_blank",rel:"noopener noreferrer"}},[t._v("Visual Studio Code"),a("OutboundLink")],1),t._v(""),a("a",{attrs:{href:"https://www.eclipse.org/downloads/packages/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Eclipse"),a("OutboundLink")],1),t._v("等等。")]),t._v(" "),a("p",[a("strong",[t._v("Java™ 开发工具包 (JDK)")])]),t._v(" "),a("p",[t._v("我们推荐"),a("a",{attrs:{href:"https://bell-sw.com/",target:"_blank",rel:"noopener noreferrer"}},[t._v("BellSoft Liberica JDK"),a("OutboundLink")],1),t._v("版本 8 或版本 11。")]),t._v(" "),a("h2",{attrs:{id:"第一步-开始一个新的-spring-boot-项目"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第一步-开始一个新的-spring-boot-项目"}},[t._v("#")]),t._v(" 第一步:开始一个新的 Spring Boot 项目")]),t._v(" "),a("p",[t._v("通过"),a("a",{attrs:{href:"https://start.spring.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("start.spring.io"),a("OutboundLink")],1),t._v("创建一个“web”项目。在“依赖项”对话框中搜索并添加“web”依赖项,如屏幕截图所示。点击“生成”按钮,下载 zip,然后将其解压缩到计算机上的文件夹中。")]),t._v(" "),a("p",[a("img",{attrs:{src:r(430),alt:"quick-img-1-12bfde9c5c280b1940d85dee3d81772d"}})]),t._v(" "),a("p",[t._v("通过"),a("a",{attrs:{href:"https://start.spring.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("start.spring.io"),a("OutboundLink")],1),t._v("创建的项目包含"),a("a",{attrs:{href:"https://spring.io/projects/spring-boot",target:"_blank",rel:"noopener noreferrer"}},[t._v("Spring Boot"),a("OutboundLink")],1),t._v(",Spring Boot是一个不需要太多代码或配置,就可以使Spring在您的应用程序中正常工作的框架,Spring Boot 是使用 Spring 项目的最快、最流行的方式。")]),t._v(" "),a("h2",{attrs:{id:"第-2-步-添加您的代码"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第-2-步-添加您的代码"}},[t._v("#")]),t._v(" 第 2 步:添加您的代码")]),t._v(" "),a("p",[t._v("在 IDE 中打开项目并在文件夹"),a("code",[t._v("DemoApplication.java")]),t._v("中找到该文件"),a("code",[t._v("src/main/java/com/example/demo")]),t._v("。现在通过添加下面代码中显示的额外方法和注解来更改文件的内容。您可以复制并粘贴代码或直接输入。")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v('\n package com.example.demo;\n import org.springframework.boot.SpringApplication;\n import org.springframework.boot.autoconfigure.SpringBootApplication;\n import org.springframework.web.bind.annotation.GetMapping;\n import org.springframework.web.bind.annotation.RequestParam;\n import org.springframework.web.bind.annotation.RestController;\n \n @SpringBootApplication\n @RestController\n public class DemoApplication {\n \n \n public static void main(String[] args) {\n SpringApplication.run(DemoApplication.class, args);\n }\n \n @GetMapping("/hello")\n public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {\n return String.format("Hello %s!", name);\n }\n \n }\n \n')])])]),a("p",[t._v("这是在Spring Boot中创建一个简单的“Hello World”Web服务所需的所有代码。")]),t._v(" "),a("p",[a("code",[t._v("hello()")]),t._v("方法,我们设计成接收一个字符串参数"),a("code",[t._v("name")]),t._v(",然后将该参数与"),a("code",[t._v('"Hello"')]),t._v("连接起来。如果您请求时将"),a("code",[t._v("name")]),t._v("设置为"),a("code",[t._v("“Amy”")]),t._v(",服务将会返回"),a("code",[t._v("“Hello Amy”")]),t._v(".")]),t._v(" "),a("p",[a("code",[t._v("@RestController")]),t._v("注解告诉 Spring 这段代码描述了一个应该在 web 上可用的端点。\n"),a("code",[t._v("@GetMapping(“/hello”)")]),t._v("告诉 Spring 使用我们的方法"),a("code",[t._v("hello()")]),t._v("来响应发送到该"),a("code",[t._v("http://localhost:8080/hello")]),t._v("地址的请求。\n"),a("code",[t._v("@RequestParam")]),t._v("告诉 Spring期望请求中包含"),a("code",[t._v("name")]),t._v("参数,但如果它不存在,将使用默认值“World”。")]),t._v(" "),a("h2",{attrs:{id:"第-3-步-尝试一下"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#第-3-步-尝试一下"}},[t._v("#")]),t._v(" 第 3 步:尝试一下")]),t._v(" "),a("p",[t._v("让我们构建并运行程序。打开命令行(或终端)并进入到项目所在文件夹。可以通过以下命令来构建和运行应用程序:")]),t._v(" "),a("p",[a("strong",[t._v("MacOS/Linux:")])]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("./mvnw spring-boot:run\n")])])]),a("p",[a("strong",[t._v("Windows:")])]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("mvnw spring-boot:run\n")])])]),a("p",[t._v("您应该会看到一些与此非常相似的输出:")]),t._v(" "),a("p",[a("img",{attrs:{src:r(431),alt:"quick-img2-ac5ae88c60ffaa062234a580f9f1abc3"}})]),t._v(" "),a("p",[t._v("最后的几行日志显示Spring已经启动了。Spring Boot 的嵌入式 Apache Tomcat 服务器充当 Web 服务器,并正在监听"),a("code",[t._v("localhost")]),t._v(""),a("code",[t._v("8080")]),t._v("端口请求。打开浏览器,在地址栏中输入"),a("a",{attrs:{href:"http://localhost:8080/hello",target:"_blank",rel:"noopener noreferrer"}},[t._v("http://localhost:8080/hello"),a("OutboundLink")],1),t._v(". 你应该得到一个很好的友好回应,如下所示:")]),t._v(" "),a("p",[a("img",{attrs:{src:r(432),alt:"quick-img3-afa0a1fe446db8e3c8c7a8d9ca532d23"}})]),t._v(" "),a("p",[t._v("原文链接: https://spring.io/quickstart")])])}),[],!1,null,null,null);e.default=n.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[102],{525:function(t,e,n){"use strict";n.r(e);var s=n(56),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]);
\ No newline at end of file
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[104],{527:function(t,e,n){"use strict";n.r(e);var s=n(56),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{1149:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(434),n(56)),p=Object(r.a)(i,void 0,void 0,!1,null,"69025e8c",null);e.default=p.exports},375:function(t,e,n){},434:function(t,e,n){"use strict";n(375)}}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[110],{532:function(e,n,t){"use strict";t.r(n);var a=t(56),o=Object(a.a)({},(function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"error-handling"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#error-handling"}},[e._v("#")]),e._v(" Error Handling")]),e._v(" "),t("h2",{attrs:{id:"error-handling-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#error-handling-2"}},[e._v("#")]),e._v(" Error Handling")]),e._v(" "),t("p",[e._v("As described in the "),t("RouterLink",{attrs:{to:"/en/spring-integration/overview.html#overview"}},[e._v("overview")]),e._v(" at the very beginning of this manual, one of the main motivations behind a message-oriented framework such as Spring Integration is to promote loose coupling between components.\nThe message channel plays an important role, in that producers and consumers do not have to know about each other.\nHowever, the advantages also have some drawbacks.\nSome things become more complicated in a loosely coupled environment, and one example is error handling.")],1),e._v(" "),t("p",[e._v("When sending a message to a channel, the component that ultimately handles that message may or may not be operating within the same thread as the sender.\nIf using a simple default "),t("code",[e._v("DirectChannel")]),e._v(" (when the "),t("code",[e._v("<channel>")]),e._v(" element that has no "),t("code",[e._v("<queue>")]),e._v(" child element and no 'task-executor' attribute), the message handling occurs in the same thread that sends the initial message.\nIn that case, if an "),t("code",[e._v("Exception")]),e._v(" is thrown, it can be caught by the sender (or it may propagate past the sender if it is an uncaught "),t("code",[e._v("RuntimeException")]),e._v(").\nThis is the same behavior as an exception-throwing operation in a normal Java call stack.")]),e._v(" "),t("p",[e._v("A message flow that runs on a caller thread might be invoked through a messaging gateway (see "),t("RouterLink",{attrs:{to:"/en/spring-integration/gateway.html#gateway"}},[e._v("Messaging Gateways")]),e._v(") or a "),t("code",[e._v("MessagingTemplate")]),e._v(" (see "),t("RouterLink",{attrs:{to:"/en/spring-integration/channel.html#channel-template"}},[t("code",[e._v("MessagingTemplate")])]),e._v(").\nIn either case, the default behavior is to throw any exceptions to the caller.\nFor the messaging gateway, see "),t("RouterLink",{attrs:{to:"/en/spring-integration/gateway.html#gateway-error-handling"}},[e._v("Error Handling")]),e._v(" for details about how the exception is thrown and how to configure the gateway to route the errors to an error channel instead.\nWhen using a "),t("code",[e._v("MessagingTemplate")]),e._v(" or sending to a "),t("code",[e._v("MessageChannel")]),e._v(" directly, exceptions are always thrown to the caller.")],1),e._v(" "),t("p",[e._v("When adding asynchronous processing, things become rather more complicated.\nFor instance, if the 'channel' element does provide a 'queue' child element ("),t("code",[e._v("QueueChannel")]),e._v(" in Java & Annotations Configuration), the component that handles the message operates in a different thread than the sender.\nThe same is true when an "),t("code",[e._v("ExecutorChannel")]),e._v(" is used.\nThe sender may have dropped the "),t("code",[e._v("Message")]),e._v(" into the channel and moved on to other things.\nThere is no way for the "),t("code",[e._v("Exception")]),e._v(" to be thrown directly back to that sender by using standard "),t("code",[e._v("Exception")]),e._v(" throwing techniques.\nInstead, handling errors for asynchronous processes requires that the error-handling mechanism also be asynchronous.")]),e._v(" "),t("p",[e._v("Spring Integration supports error handling for its components by publishing errors to a message channel.\nSpecifically, the "),t("code",[e._v("Exception")]),e._v(" becomes the payload of a Spring Integration "),t("code",[e._v("ErrorMessage")]),e._v(".\nThat "),t("code",[e._v("Message")]),e._v(" is then sent to a message channel that is resolved in a way that is similar to the 'replyChannel' resolution.\nFirst, if the request "),t("code",[e._v("Message")]),e._v(" being handled at the time the "),t("code",[e._v("Exception")]),e._v(" occurred contains an 'errorChannel' header (the header name is defined in the "),t("code",[e._v("MessageHeaders.ERROR_CHANNEL")]),e._v(" constant), the "),t("code",[e._v("ErrorMessage")]),e._v(" is sent to that channel.\nOtherwise, the error handler sends to a “global” channel whose bean name is "),t("code",[e._v("errorChannel")]),e._v(" (this is also defined as a constant: "),t("code",[e._v("IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME")]),e._v(").")]),e._v(" "),t("p",[e._v("A default "),t("code",[e._v("errorChannel")]),e._v(" bean is created internally by the Framework.\nHowever, you can define your own if you want to control the settings.\nThe following example shows how to define an error channel in XML configuration backed by a queue with a capacity of "),t("code",[e._v("500")]),e._v(":")]),e._v(" "),t("p",[e._v("Java")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("@Bean\nQueueChannel errorChannel() {\n return new QueueChannel(500);\n}\n")])])]),t("p",[e._v("XML")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('<int:channel id="errorChannel">\n <int:queue capacity="500"/>\n</int:channel>\n')])])]),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("The default error channel is a "),t("code",[e._v("PublishSubscribeChannel")]),e._v(".")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("The most important thing to understand here is that the messaging-based error handling applies only to exceptions that are thrown by a Spring Integration task that is executing within a "),t("code",[e._v("TaskExecutor")]),e._v(".\nThis does not apply to exceptions thrown by a handler that operates within the same thread as the sender (for example, through a "),t("code",[e._v("DirectChannel")]),e._v(" as described earlier in this section).")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("When exceptions occur in a scheduled poller task’s execution, those exceptions are wrapped in "),t("code",[e._v("ErrorMessage")]),e._v(" instances and sent to the 'errorChannel' as well."),t("br"),e._v("This is done via a "),t("code",[e._v("MessagePublishingErrorHandler")]),e._v(" injected into the global "),t("code",[e._v("taskScheduler")]),e._v(" bean."),t("br"),e._v("It is recommended to use that "),t("code",[e._v("MessagePublishingErrorHandler")]),e._v(" for any custom "),t("code",[e._v("taskScheduler")]),e._v(" if the error handling still has to be done using standard 'errorChannel' integration flow logic."),t("br"),e._v("A registered "),t("code",[e._v("integrationMessagePublishingErrorHandler")]),e._v(" bean can be used in this case.")])])]),e._v(" "),t("tbody")]),e._v(" "),t("p",[e._v("To enable global error handling, register a handler on that channel.\nFor example, you can configure Spring Integration’s "),t("code",[e._v("ErrorMessageExceptionTypeRouter")]),e._v(" as the handler of an endpoint that is subscribed to the 'errorChannel'.\nThat router can then spread the error messages across multiple channels, based on the "),t("code",[e._v("Exception")]),e._v(" type.")]),e._v(" "),t("p",[e._v("Starting with version 4.3.10, Spring Integration provides the "),t("code",[e._v("ErrorMessagePublisher")]),e._v(" and the "),t("code",[e._v("ErrorMessageStrategy")]),e._v(".\nYou can use them as a general mechanism for publishing "),t("code",[e._v("ErrorMessage")]),e._v(" instances.\nYou can call or extend them in any error handling scenarios.\nThe "),t("code",[e._v("ErrorMessageSendingRecoverer")]),e._v(" extends this class as a "),t("code",[e._v("RecoveryCallback")]),e._v(" implementation that can be used with retry, such as the"),t("RouterLink",{attrs:{to:"/en/spring-integration/handler-advice.html#retry-advice"}},[t("code",[e._v("RequestHandlerRetryAdvice")])]),e._v(".\nThe "),t("code",[e._v("ErrorMessageStrategy")]),e._v(" is used to build an "),t("code",[e._v("ErrorMessage")]),e._v(" based on the provided exception and an "),t("code",[e._v("AttributeAccessor")]),e._v(" context.\nIt can be injected into any "),t("code",[e._v("MessageProducerSupport")]),e._v(" or "),t("code",[e._v("MessagingGatewaySupport")]),e._v(".\nThe "),t("code",[e._v("requestMessage")]),e._v(" is stored under "),t("code",[e._v("ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY")]),e._v(" in the "),t("code",[e._v("AttributeAccessor")]),e._v(" context.\nThe "),t("code",[e._v("ErrorMessageStrategy")]),e._v(" can use that "),t("code",[e._v("requestMessage")]),e._v(" as the "),t("code",[e._v("originalMessage")]),e._v(" property of the "),t("code",[e._v("ErrorMessage")]),e._v(" it creates.\nThe "),t("code",[e._v("DefaultErrorMessageStrategy")]),e._v(" does exactly that.")],1),e._v(" "),t("p",[e._v("Starting with version 5.2, all the "),t("code",[e._v("MessageHandlingException")]),e._v(" instances thrown by the framework components, includes a component "),t("code",[e._v("BeanDefinition")]),e._v(" resource and source to determine a configuration point form the exception.\nIn case of XML configuration, a resource is an XML file path and source an XML tag with its "),t("code",[e._v("id")]),e._v(" attribute.\nWith Java & Annotation configuration, a resource is a "),t("code",[e._v("@Configuration")]),e._v(" class and source is a "),t("code",[e._v("@Bean")]),e._v(" method.\nIn most case the target integration flow solution is based on the out-of-the-box components and their configuration options.\nWhen an exception happens at runtime, there is no any end-user code involved in stack trace because an execution is against beans, not their configuration.\nIncluding a resource and source of the bean definition helps to determine possible configuration mistakes and provides better developer experience.")]),e._v(" "),t("p",[e._v("Starting with version 5.4.3, the default error channel is configured with the property "),t("code",[e._v("requireSubscribers = true")]),e._v(" to not silently ignore messages when there are no subscribers on this channel (e.g. when application context is stopped).\nIn this case a "),t("code",[e._v("MessageDispatchingException")]),e._v(" is thrown which may lend on the client callback of the inbound channel adapter to negatively acknowledge (or roll back) an original message in the source system for redelivery or other future consideration.\nTo restore the previous behavior (ignore non dispatched error messages), the global integration property "),t("code",[e._v("spring.integration.channels.error.requireSubscribers")]),e._v(" must be set to "),t("code",[e._v("false")]),e._v(".\nSee "),t("RouterLink",{attrs:{to:"/en/spring-integration/configuration.html#global-properties"}},[e._v("Global Properties")]),e._v(" and "),t("RouterLink",{attrs:{to:"/en/spring-integration/channel.html#channel-configuration-pubsubchannel"}},[t("code",[e._v("PublishSubscribeChannel")]),e._v(" Configuration")]),e._v(" (if you configure a global "),t("code",[e._v("errorChannel")]),e._v(" manually) for more information.")],1)])}),[],!1,null,null,null);n.default=o.exports}}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[111],{535:function(e,n,t){"use strict";t.r(n);var a=t(56),s=Object(a.a)({},(function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"spring-applicationevent-support"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#spring-applicationevent-support"}},[e._v("#")]),e._v(" Spring ApplicationEvent Support")]),e._v(" "),t("h2",{attrs:{id:"spring-applicationevent-support-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#spring-applicationevent-support-2"}},[e._v("#")]),e._v(" Spring "),t("code",[e._v("ApplicationEvent")]),e._v(" Support")]),e._v(" "),t("p",[e._v("Spring Integration provides support for inbound and outbound "),t("code",[e._v("ApplicationEvents")]),e._v(", as defined by the underlying Spring Framework.\nFor more information about Spring’s support for events and listeners, see the "),t("a",{attrs:{href:"https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Reference Manual"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("You need to include this dependency into your project:")]),e._v(" "),t("p",[e._v("Maven")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("<dependency>\n <groupId>org.springframework.integration</groupId>\n <artifactId>spring-integration-event</artifactId>\n <version>5.5.9</version>\n</dependency>\n")])])]),t("p",[e._v("Gradle")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('compile "org.springframework.integration:spring-integration-event:5.5.9"\n')])])]),t("h3",{attrs:{id:"receiving-spring-application-events"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#receiving-spring-application-events"}},[e._v("#")]),e._v(" Receiving Spring Application Events")]),e._v(" "),t("p",[e._v("To receive events and send them to a channel, you can define an instance of Spring Integration’s "),t("code",[e._v("ApplicationEventListeningMessageProducer")]),e._v(".\nThis class is an implementation of Spring’s "),t("code",[e._v("ApplicationListener")]),e._v(" interface.\nBy default, it passes all received events as Spring Integration messages.\nTo limit based on the type of event, you can use the 'eventTypes' property to configure the list of event types that you want to receive.\nIf a received event has a "),t("code",[e._v("Message")]),e._v(" instance as its 'source', that "),t("code",[e._v("Message")]),e._v(" is passed as-is.\nOtherwise, if a SpEL-based "),t("code",[e._v("payloadExpression")]),e._v(" has been provided, that is evaluated against the "),t("code",[e._v("ApplicationEvent")]),e._v(" instance.\nIf the event’s source is not a "),t("code",[e._v("Message")]),e._v(" instance and no "),t("code",[e._v("payloadExpression")]),e._v(" has been provided, the "),t("code",[e._v("ApplicationEvent")]),e._v(" itself is passed as the payload.")]),e._v(" "),t("p",[e._v("Starting with version 4.2, the "),t("code",[e._v("ApplicationEventListeningMessageProducer")]),e._v(" implements "),t("code",[e._v("GenericApplicationListener")]),e._v(" and can be configured to accept not only "),t("code",[e._v("ApplicationEvent")]),e._v(" types but any type for treating payload events (which are also supported since Spring Framework 4.2).\nWhen the accepted event is an instance of "),t("code",[e._v("PayloadApplicationEvent")]),e._v(", its "),t("code",[e._v("payload")]),e._v(" is used for the message to send.")]),e._v(" "),t("p",[e._v("For convenience, namespace support is provided to configure an "),t("code",[e._v("ApplicationEventListeningMessageProducer")]),e._v(" with the "),t("code",[e._v("inbound-channel-adapter")]),e._v(" element, as the following example shows:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('<int-event:inbound-channel-adapter channel="eventChannel"\n error-channel="eventErrorChannel"\n event-types="example.FooEvent, example.BarEvent, java.util.Date"/>\n\n<int:publish-subscribe-channel id="eventChannel"/>\n')])])]),t("p",[e._v("In the preceding example, all application context events that match one of the types specified by the 'event-types' (optional) attribute are delivered as Spring Integration messages to the message channel named 'eventChannel'.\nIf a downstream component throws an exception, a "),t("code",[e._v("MessagingException")]),e._v(" that contains the failed message and exception is sent to the channel named 'eventErrorChannel'.\nIf no "),t("code",[e._v("error-channel")]),e._v(" is specified and the downstream channels are synchronous, the exception is propagated to the caller.")]),e._v(" "),t("p",[e._v("Using Java to configure the same adapter:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("@Bean\npublic ApplicationEventListeningMessageProducer eventsAdapter(\n MessageChannel eventChannel, MessageChannel eventErrorChannel) {\n\n ApplicationEventListeningMessageProducer producer =\n new ApplicationEventListeningMessageProducer();\n producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);\n producer.setOutputChannel(eventChannel);\n producer.setErrorChannel(eventErrorChannel);\n return producer;\n}\n")])])]),t("p",[e._v("With the Java DSL:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("@Bean\npublic ApplicationEventListeningMessageProducer eventsAdapter() {\n\n ApplicationEventListeningMessageProducer producer =\n new ApplicationEventListeningMessageProducer();\n producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);\n return producer;\n}\n\n@Bean\npublic IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter,\n MessageChannel eventErrorChannel) {\n\n return IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))\n .handle(...)\n ...\n .get();\n}\n")])])]),t("h3",{attrs:{id:"sending-spring-application-events"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sending-spring-application-events"}},[e._v("#")]),e._v(" Sending Spring Application Events")]),e._v(" "),t("p",[e._v("To send Spring "),t("code",[e._v("ApplicationEvents")]),e._v(", create an instance of the "),t("code",[e._v("ApplicationEventPublishingMessageHandler")]),e._v(" and register it within an endpoint.\nThis implementation of the "),t("code",[e._v("MessageHandler")]),e._v(" interface also implements Spring’s "),t("code",[e._v("ApplicationEventPublisherAware")]),e._v(" interface and consequently acts as a bridge between Spring Integration messages and "),t("code",[e._v("ApplicationEvents")]),e._v(".")]),e._v(" "),t("p",[e._v("For convenience, namespace support is provided to configure an "),t("code",[e._v("ApplicationEventPublishingMessageHandler")]),e._v(" with the "),t("code",[e._v("outbound-channel-adapter")]),e._v(" element, as the following example shows:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('<int:channel id="eventChannel"/>\n\n<int-event:outbound-channel-adapter channel="eventChannel"/>\n')])])]),t("p",[e._v("If you use a "),t("code",[e._v("PollableChannel")]),e._v(" (such as a "),t("code",[e._v("QueueChannel")]),e._v("), you can also provide a "),t("code",[e._v("poller")]),e._v(" child element of the "),t("code",[e._v("outbound-channel-adapter")]),e._v(" element.\nYou can also optionally provide a "),t("code",[e._v("task-executor")]),e._v(" reference for that poller.\nThe following example demonstrates both:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('<int:channel id="eventChannel">\n <int:queue/>\n</int:channel>\n\n<int-event:outbound-channel-adapter channel="eventChannel">\n <int:poller max-messages-per-poll="1" task-executor="executor" fixed-rate="100"/>\n</int-event:outbound-channel-adapter>\n\n<task:executor id="executor" pool-size="5"/>\n')])])]),t("p",[e._v("In the preceding example, all messages sent to the 'eventChannel' channel are published as "),t("code",[e._v("ApplicationEvent")]),e._v(" instances to any relevant "),t("code",[e._v("ApplicationListener")]),e._v(" instances that are registered within the same Spring "),t("code",[e._v("ApplicationContext")]),e._v(".\nIf the payload of the message is an "),t("code",[e._v("ApplicationEvent")]),e._v(", it is passed as-is.\nOtherwise, the message itself is wrapped in a "),t("code",[e._v("MessagingEvent")]),e._v(" instance.")]),e._v(" "),t("p",[e._v("Starting with version 4.2, you can configure the "),t("code",[e._v("ApplicationEventPublishingMessageHandler")]),e._v(" ("),t("code",[e._v("<int-event:outbound-channel-adapter>")]),e._v(") with the "),t("code",[e._v("publish-payload")]),e._v(" boolean attribute to publish to the application context "),t("code",[e._v("payload")]),e._v(" as is, instead of wrapping it to a "),t("code",[e._v("MessagingEvent")]),e._v(" instance.")]),e._v(" "),t("p",[e._v("To configure the adapter using Java configuration:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\n@ServiceActivator(inputChannel = "eventChannel")\npublic ApplicationEventPublishingMessageHandler eventHandler() {\n ApplicationEventPublishingMessageHandler handler =\n new ApplicationEventPublishingMessageHandler();\n handler.setPublishPayload(true);\n return handler;\n}\n')])])]),t("p",[e._v("With the Java DSL:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\npublic ApplicationEventPublishingMessageHandler eventHandler() {\n ApplicationEventPublishingMessageHandler handler =\n new ApplicationEventPublishingMessageHandler();\n handler.setPublishPayload(true);\n return handler;\n}\n\n@Bean\n// MessageChannel is "eventsFlow.input"\npublic IntegrationFlow eventsOutFlow(ApplicationEventPublishingMessageHandler eventHandler) {\n return f -> f.handle(eventHandler);\n}\n')])])])])}),[],!1,null,null,null);n.default=s.exports}}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[112],{533:function(e,t,n){"use strict";n.r(t);var a=n(56),r=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"feed-adapter"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#feed-adapter"}},[e._v("#")]),e._v(" Feed Adapter")]),e._v(" "),n("h2",{attrs:{id:"feed-adapter-2"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#feed-adapter-2"}},[e._v("#")]),e._v(" Feed Adapter")]),e._v(" "),n("p",[e._v("Spring Integration provides support for syndication through feed adapters.\nThe implementation is based on the "),n("a",{attrs:{href:"https://rometools.github.io/rome/",target:"_blank",rel:"noopener noreferrer"}},[e._v("ROME Framework"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("You need to include this dependency into your project:")]),e._v(" "),n("p",[e._v("Maven")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("<dependency>\n <groupId>org.springframework.integration</groupId>\n <artifactId>spring-integration-feed</artifactId>\n <version>5.5.9</version>\n</dependency>\n")])])]),n("p",[e._v("Gradle")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('compile "org.springframework.integration:spring-integration-feed:5.5.9"\n')])])]),n("p",[e._v("Web syndication is a way to publish material such as news stories, press releases, blog posts, and other items typically available on a website but also made available in a feed format such as RSS or ATOM.")]),e._v(" "),n("p",[e._v("Spring integration provides support for web syndication through its 'feed' adapter and provides convenient namespace-based configuration for it.\nTo configure the 'feed' namespace, include the following elements within the headers of your XML configuration file:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('xmlns:int-feed="http://www.springframework.org/schema/integration/feed"\nxsi:schemaLocation="http://www.springframework.org/schema/integration/feed\n\thttps://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd"\n')])])]),n("h3",{attrs:{id:"feed-inbound-channel-adapter"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#feed-inbound-channel-adapter"}},[e._v("#")]),e._v(" Feed Inbound Channel Adapter")]),e._v(" "),n("p",[e._v("The only adapter you really need to provide support for retrieving feeds is an inbound channel adapter.\nIt lets you subscribe to a particular URL.\nThe following example shows a possible configuration:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('<int-feed:inbound-channel-adapter id="feedAdapter"\n channel="feedChannel"\n url="https://feeds.bbci.co.uk/news/rss.xml">\n <int:poller fixed-rate="10000" max-messages-per-poll="100" />\n</int-feed:inbound-channel-adapter>\n')])])]),n("p",[e._v("In the preceding configuration, we are subscribing to a URL identified by the "),n("code",[e._v("url")]),e._v(" attribute.")]),e._v(" "),n("p",[e._v("As news items are retrieved, they are converted to messages and sent to a channel identified by the "),n("code",[e._v("channel")]),e._v(" attribute.\nThe payload of each message is a "),n("code",[e._v("com.sun.syndication.feed.synd.SyndEntry")]),e._v(" instance.\nEach one encapsulates various data about a news item (content, dates, authors, and other details).")]),e._v(" "),n("p",[e._v("The inbound feed channel adapter is a polling consumer.\nThat means that you must provide a poller configuration.\nHowever, one important thing you must understand with regard to a feed is that its inner workings are slightly different then most other polling consumers.\nWhen an inbound feed adapter is started, it does the first poll and receives a "),n("code",[e._v("com.sun.syndication.feed.synd.SyndEntryFeed")]),e._v(" instance.\nThat object contains multiple "),n("code",[e._v("SyndEntry")]),e._v(" objects.\nEach entry is stored in the local entry queue and is released based on the value in the "),n("code",[e._v("max-messages-per-poll")]),e._v(" attribute, such that each message contains a single entry.\nIf, during retrieval of the entries from the entry queue, the queue has become empty, the adapter attempts to update the feed, thereby populating the queue with more entries ("),n("code",[e._v("SyndEntry")]),e._v(" instances), if any are available.\nOtherwise the next attempt to poll for a feed is determined by the trigger of the poller (every ten seconds in the preceding configuration).")]),e._v(" "),n("h3",{attrs:{id:"duplicate-entries"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#duplicate-entries"}},[e._v("#")]),e._v(" Duplicate Entries")]),e._v(" "),n("p",[e._v("Polling for a feed can result in entries that have already been processed (“I already read that news item, why are you showing it to me again?”).\nSpring Integration provides a convenient mechanism to eliminate the need to worry about duplicate entries.\nEach feed entry has a “published date” field.\nEvery time a new "),n("code",[e._v("Message")]),e._v(" is generated and sent, Spring Integration stores the value of the latest published date in an instance of the "),n("code",[e._v("MetadataStore")]),e._v(" strategy (see "),n("RouterLink",{attrs:{to:"/en/spring-integration/meta-data-store.html#metadata-store"}},[e._v("Metadata Store")]),e._v(").")],1),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("The key used to persist the latest published date is the value of the (required) "),n("code",[e._v("id")]),e._v(" attribute of the feed inbound channel adapter component plus the "),n("code",[e._v("feedUrl")]),e._v(" (if any) from the adapter’s configuration.")])])]),e._v(" "),n("tbody")]),e._v(" "),n("h3",{attrs:{id:"other-options"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#other-options"}},[e._v("#")]),e._v(" Other Options")]),e._v(" "),n("p",[e._v("Starting with version 5.0, the deprecated "),n("code",[e._v("com.rometools.fetcher.FeedFetcher")]),e._v(" option has been removed and an overloaded "),n("code",[e._v("FeedEntryMessageSource")]),e._v(" constructor for an "),n("code",[e._v("org.springframework.core.io.Resource")]),e._v(" is provided.\nThis is useful when the feed source is not an HTTP endpoint but is any other resource (such as local or remote on FTP).\nIn the "),n("code",[e._v("FeedEntryMessageSource")]),e._v(" logic, such a resource (or provided "),n("code",[e._v("URL")]),e._v(") is parsed by the "),n("code",[e._v("SyndFeedInput")]),e._v(" to the "),n("code",[e._v("SyndFeed")]),e._v(" object for the processing mentioned earlier.\nYou can also inject a customized "),n("code",[e._v("SyndFeedInput")]),e._v(" (for example, with the "),n("code",[e._v("allowDoctypes")]),e._v(" option) instance into the "),n("code",[e._v("FeedEntryMessageSource")]),e._v(".")]),e._v(" "),n("table",[n("thead",[n("tr",[n("th"),e._v(" "),n("th",[e._v("If the connection to the feed needs some customization, e.g. connection and read timeouts, the "),n("code",[e._v("org.springframework.core.io.UrlResource")]),e._v(" extension with its "),n("code",[e._v("customizeConnection(HttpURLConnection)")]),e._v(" override has to be used instead of plain "),n("code",[e._v("URL")]),e._v(" injection into the "),n("code",[e._v("FeedEntryMessageSource")]),e._v("."),n("br"),e._v("For example:"),n("br"),n("br"),n("code",[e._v('<br/>@Bean<br/>@InboundChannelAdapter("feedChannel")<br/>FeedEntryMessageSource feedEntrySource() {<br/> UrlResource urlResource =<br/>\t new UrlResource(url) {<br/><br/>\t @Override<br/>\t protected void customizeConnection(HttpURLConnection connection) throws IOException {<br/>\t super.customizeConnection(connection);<br/>\t connection.setConnectTimeout(10000);<br/>\t connection.setReadTimeout(5000);<br/>\t }<br/>\t };<br/> return new FeedEntryMessageSource(urlResource, "myKey");<br/>}<br/>')])])])]),e._v(" "),n("tbody")]),e._v(" "),n("h3",{attrs:{id:"java-dsl-configuration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#java-dsl-configuration"}},[e._v("#")]),e._v(" Java DSL Configuration")]),e._v(" "),n("p",[e._v("The following Spring Boot application shows an example of how to configure the inbound adapter with the Java DSL:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@SpringBootApplication\npublic class FeedJavaApplication {\n\n public static void main(String[] args) {\n new SpringApplicationBuilder(FeedJavaApplication.class)\n .web(false)\n .run(args);\n }\n\n @Value("org/springframework/integration/feed/sample.rss")\n private Resource feedResource;\n\n @Bean\n public MetadataStore metadataStore() {\n PropertiesPersistingMetadataStore metadataStore = new PropertiesPersistingMetadataStore();\n metadataStore.setBaseDirectory(tempFolder.getRoot().getAbsolutePath());\n return metadataStore;\n }\n\n @Bean\n public IntegrationFlow feedFlow() {\n return IntegrationFlows\n .from(Feed.inboundAdapter(this.feedResource, "feedTest")\n .metadataStore(metadataStore()),\n e -> e.poller(p -> p.fixedDelay(100)))\n .channel(c -> c.queue("entries"))\n .get();\n }\n\n}\n')])])])])}),[],!1,null,null,null);t.default=r.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{377:function(t,e,a){},436:function(t,e,a){"use strict";a(377)},444:function(t,e,a){"use strict";a.r(e);var n={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted:function(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(436),a(56)),s=Object(i.a)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"8fc1d43a",null);e.default=s.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[124],{547:function(e,n,t){"use strict";t.r(n);var a=t(56),o=Object(a.a)({},(function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"kotlin-dsl"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#kotlin-dsl"}},[e._v("#")]),e._v(" Kotlin DSL")]),e._v(" "),t("h2",{attrs:{id:"kotlin-dsl-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#kotlin-dsl-2"}},[e._v("#")]),e._v(" Kotlin DSL")]),e._v(" "),t("p",[e._v("The Kotlin DSL is a wrapper and extension to "),t("RouterLink",{attrs:{to:"/en/spring-integration/dsl.html#java-dsl"}},[e._v("Java DSL")]),e._v(" and aimed to make Spring Integration development on Kotlin as smooth and straightforward as possible with interoperability with the existing Java API and Kotlin language-specific structures.")],1),e._v(" "),t("p",[e._v("All you need to get started is just an import for "),t("code",[e._v("org.springframework.integration.dsl.integrationFlow")]),e._v(" - an overloaded global function for Kotlin DSL.")]),e._v(" "),t("p",[e._v("For "),t("code",[e._v("IntegrationFlow")]),e._v(" definitions as lambdas we typically don’t need anything else from Kotlin and just declare a bean like this:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nfun oddFlow() =\nIntegrationFlow { flow ->\n flow.handle<Any> { _, _ -> "odd" }\n}\n')])])]),t("p",[e._v("In this case Kotlin understands that the lambda should be translated into "),t("code",[e._v("IntegrationFlow")]),e._v(" anonymous instance and target Java DSL processor parses this construction properly into Java objects.")]),e._v(" "),t("p",[e._v("As an alternative to the construction above and for consistency with use-cases explained below, a Kotlin-specif DSL should be used for declaring integration flows in the "),t("strong",[e._v("builder")]),e._v(" pattern style:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nfun flowLambda() =\n integrationFlow {\n filter<String> { it === "test" }\n wireTap {\n handle { println(it.payload) }\n }\n transform<String, String> { it.toUpperCase() }\n }\n')])])]),t("p",[e._v("Such a global "),t("code",[e._v("integrationFlow()")]),e._v(" function expects a lambda in builder style for a "),t("code",[e._v("KotlinIntegrationFlowDefinition")]),e._v(" (a Kotlin wrapper for the "),t("code",[e._v("IntegrationFlowDefinition")]),e._v(") and produces a regular "),t("code",[e._v("IntegrationFlow")]),e._v(" lambda implementation.\nSee more overloaded "),t("code",[e._v("integrationFlow()")]),e._v(" variants below.")]),e._v(" "),t("p",[e._v("Many other scenarios require an "),t("code",[e._v("IntegrationFlow")]),e._v(" to be started from source of data (e.g. "),t("code",[e._v("JdbcPollingChannelAdapter")]),e._v(", "),t("code",[e._v("JmsInboundGateway")]),e._v(" or just an existing "),t("code",[e._v("MessageChannel")]),e._v(").\nFor this purpose, the Spring Integration Java DSL provides an "),t("code",[e._v("IntegrationFlows")]),e._v(" factory with its large number of overloaded "),t("code",[e._v("from()")]),e._v(" methods.\nThis factory can be used in Kotlin as well:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nfun flowFromSupplier() =\n IntegrationFlows.from<String>({ "bar" }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }\n .channel { c -> c.queue("fromSupplierQueue") }\n .get()\n')])])]),t("p",[e._v("But unfortunately not all "),t("code",[e._v("from()")]),e._v(" methods are compatible with Kotlin structures.\nTo fix the gap, this project provides a Kotlin DSL around an "),t("code",[e._v("IntegrationFlows")]),e._v(" factory.\nIt is implemented as a set of overloaded "),t("code",[e._v("integrationFlow()")]),e._v(" functions.\nWith a consumer for a "),t("code",[e._v("KotlinIntegrationFlowDefinition")]),e._v(" to declare the rest of the flow as an "),t("code",[e._v("IntegrationFlow")]),e._v(" lambda to reuse the mentioned above experience and also avoid "),t("code",[e._v("get()")]),e._v(" call in the end.\nFor example:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nfun functionFlow() =\n integrationFlow<Function<String, String>>({ beanName("functionGateway") }) {\n transform<String, String> { it.toUpperCase() }\n }\n\n@Bean\nfun messageSourceFlow() =\n integrationFlow(MessageProcessorMessageSource { "testSource" },\n { poller { it.fixedDelay(10).maxMessagesPerPoll(1) } }) {\n channel { queue("fromSupplierQueue") }\n }\n')])])]),t("p",[e._v("In addition, Kotlin extensions are provided for the Java DSL API which needs some refinement for Kotlin structures.\nFor example "),t("code",[e._v("IntegrationFlowDefinition<*>")]),e._v(" requires a reifying for many methods with "),t("code",[e._v("Class<P>")]),e._v(" argument:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nfun convertFlow() =\n integrationFlow("convertFlowInput") {\n convert<TestPojo>()\n }\n')])])])])}),[],!1,null,null,null);n.default=o.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{376:function(e,t,a){},435:function(e,t,a){"use strict";a(376)},443:function(e,t,a){"use strict";a.r(t);a(84),a(39),a(7),a(117),a(118);var o={name:"CodeGroup",data:function(){return{codeTabs:[],activeCodeTabIndex:-1}},watch:{activeCodeTabIndex:function(e){this.activateCodeTab(e)}},mounted:function(){this.loadTabs()},methods:{changeCodeTab:function(e){this.activeCodeTabIndex=e},loadTabs:function(){var e=this;this.codeTabs=(this.$slots.default||[]).filter((function(e){return Boolean(e.componentOptions)})).map((function(t,a){return""===t.componentOptions.propsData.active&&(e.activeCodeTabIndex=a),{title:t.componentOptions.propsData.title,elm:t.elm}})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab:function(e){this.codeTabs.forEach((function(e){e.elm&&e.elm.classList.remove("theme-code-block__active")})),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},c=(a(435),a(56)),n=Object(c.a)(o,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ClientOnly",[a("div",{staticClass:"theme-code-group"},[a("div",{staticClass:"theme-code-group__nav"},[a("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(t,o){return a("li",{key:t.title,staticClass:"theme-code-group__li"},[a("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(t.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?a("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"df26b1cc",null);t.default=n.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[134],{557:function(e,n,t){"use strict";t.r(n);var r=t(56),a=Object(r.a)({},(function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"preface"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#preface"}},[e._v("#")]),e._v(" Preface")]),e._v(" "),t("h2",{attrs:{id:"requirements"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#requirements"}},[e._v("#")]),e._v(" Requirements")]),e._v(" "),t("p",[e._v("This section details the compatible "),t("a",{attrs:{href:"https://www.oracle.com/technetwork/java/javase/downloads/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("Java"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://spring.io/projects/spring-framework",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring Framework"),t("OutboundLink")],1),e._v(" versions.")]),e._v(" "),t("h3",{attrs:{id:"compatible-java-versions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#compatible-java-versions"}},[e._v("#")]),e._v(" Compatible Java Versions")]),e._v(" "),t("p",[e._v("For Spring Integration 5.5.x, the minimum compatible Java version is Java SE 8.\nOlder versions of Java are not supported.")]),e._v(" "),t("h3",{attrs:{id:"compatible-versions-of-the-spring-framework"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#compatible-versions-of-the-spring-framework"}},[e._v("#")]),e._v(" Compatible Versions of the Spring Framework")]),e._v(" "),t("p",[e._v("Spring Integration 5.5.x requires Spring Framework 5.3 or later.")]),e._v(" "),t("h2",{attrs:{id:"code-conventions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#code-conventions"}},[e._v("#")]),e._v(" Code Conventions")]),e._v(" "),t("p",[e._v("Spring Framework 2.0 introduced support for namespaces, which simplifies the XML configuration of the application context and lets Spring Integration provide broad namespace support.")]),e._v(" "),t("p",[e._v("In this reference guide, the "),t("code",[e._v("int")]),e._v(" namespace prefix is used for Spring Integration’s core namespace support.\nEach Spring Integration adapter type (also called a module) provides its own namespace, which is configured by using the following convention:")]),e._v(" "),t("p",[e._v("The following example shows the "),t("code",[e._v("int")]),e._v(", "),t("code",[e._v("int-event")]),e._v(", and "),t("code",[e._v("int-stream")]),e._v(" namespaces in use:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('<?xml version="1.0" encoding="UTF-8"?>\n<beans xmlns="http://www.springframework.org/schema/beans"\n xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n xmlns:int="http://www.springframework.org/schema/integration"\n xmlns:int-webflux="http://www.springframework.org/schema/integration/webflux"\n xmlns:int-stream="http://www.springframework.org/schema/integration/stream"\n xsi:schemaLocation="\n http://www.springframework.org/schema/beans\n https://www.springframework.org/schema/beans/spring-beans.xsd\n http://www.springframework.org/schema/integration\n https://www.springframework.org/schema/integration/spring-integration.xsd\n http://www.springframework.org/schema/integration/webflux\n https://www.springframework.org/schema/integration/webflux/spring-integration-webflux.xsd\n http://www.springframework.org/schema/integration/stream\n https://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd">\n\n</beans>\n')])])]),t("p",[e._v("For a detailed explanation regarding Spring Integration’s namespace support, see "),t("RouterLink",{attrs:{to:"/en/spring-integration/configuration.html#configuration-namespace"}},[e._v("Namespace Support")]),e._v(".")],1),e._v(" "),t("table",[t("thead",[t("tr",[t("th"),e._v(" "),t("th",[e._v("The namespace prefix can be freely chosen."),t("br"),e._v("You may even choose not to use any namespace prefixes at all."),t("br"),e._v("Therefore, you should apply the convention that best suits your application."),t("br"),e._v("Be aware, though, that SpringSource Tool Suite™ (STS) uses the same namespace conventions for Spring Integration as used in this reference guide.")])])]),e._v(" "),t("tbody")]),e._v(" "),t("h2",{attrs:{id:"conventions-in-this-guide"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conventions-in-this-guide"}},[e._v("#")]),e._v(" Conventions in This Guide")]),e._v(" "),t("p",[e._v("In some cases, to aid formatting when specifying long fully qualified class names, we shorten "),t("code",[e._v("org.springframework")]),e._v(" to "),t("code",[e._v("o.s")]),e._v(" and "),t("code",[e._v("org.springframework.integration")]),e._v(" to "),t("code",[e._v("o.s.i")]),e._v(", such as with "),t("code",[e._v("o.s.i.transaction.TransactionSynchronizationFactory")]),e._v(".")])])}),[],!1,null,null,null);n.default=a.exports}}]);
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[135],{558:function(e,a,t){"use strict";t.r(a);var n=t(56),r=Object(n.a)({},(function(){var e=this,a=e.$createElement,t=e._self._c||a;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"r2dbc-support"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#r2dbc-support"}},[e._v("#")]),e._v(" R2DBC Support")]),e._v(" "),t("h2",{attrs:{id:"r2dbc-support-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#r2dbc-support-2"}},[e._v("#")]),e._v(" R2DBC Support")]),e._v(" "),t("p",[e._v("Spring Integration provides channel adapters for receiving and sending messages by using reactive access to databases via "),t("a",{attrs:{href:"https://r2dbc.io/",target:"_blank",rel:"noopener noreferrer"}},[e._v("R2DBC"),t("OutboundLink")],1),e._v(" drivers.")]),e._v(" "),t("p",[e._v("You need to include this dependency into your project:")]),e._v(" "),t("p",[e._v("Maven")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("<dependency>\n <groupId>org.springframework.integration</groupId>\n <artifactId>spring-integration-r2dbc</artifactId>\n <version>5.5.9</version>\n</dependency>\n")])])]),t("p",[e._v("Gradle")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('compile "org.springframework.integration:spring-integration-r2dbc:5.5.9"\n')])])]),t("h3",{attrs:{id:"r2dbc-inbound-channel-adapter"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#r2dbc-inbound-channel-adapter"}},[e._v("#")]),e._v(" R2DBC Inbound Channel Adapter")]),e._v(" "),t("p",[e._v("The "),t("code",[e._v("R2dbcMessageSource")]),e._v(" is a pollable "),t("code",[e._v("MessageSource")]),e._v(" implementation based on the "),t("code",[e._v("R2dbcEntityOperations")]),e._v(" and produces messages with a "),t("code",[e._v("Flux")]),e._v(" or "),t("code",[e._v("Mono")]),e._v(" as a payload for data fetched from database according an "),t("code",[e._v("expectSingleResult")]),e._v(" option.\nThe query to "),t("code",[e._v("SELECT")]),e._v(" can be statically provided or based on a SpEL expression which is evaluated on every "),t("code",[e._v("receive()")]),e._v(" call.\nThe "),t("code",[e._v("R2dbcMessageSource.SelectCreator")]),e._v(" is present as a root object for evaluation context to allow to use a "),t("code",[e._v("StatementMapper.SelectSpec")]),e._v(" fluent API.\nBy default this channel adapter maps records from the select into a "),t("code",[e._v("LinkedCaseInsensitiveMap")]),e._v(" instances.\nIt can be customized providing a "),t("code",[e._v("payloadType")]),e._v(" options which is used underneath by the "),t("code",[e._v("EntityRowMapper")]),e._v(" based on the "),t("code",[e._v("this.r2dbcEntityOperations.getConverter()")]),e._v(".\nThe "),t("code",[e._v("updateSql")]),e._v(" is optional and used to mark read records in the databased for skipping from the subsequent polls.\nThe "),t("code",[e._v("UPDATE")]),e._v(" operation can be supplied with a "),t("code",[e._v("BiFunction<DatabaseClient.GenericExecuteSpec, ?, DatabaseClient.GenericExecuteSpec>")]),e._v(" to bind values into an "),t("code",[e._v("UPDATE")]),e._v(" based on records in the "),t("code",[e._v("SELECT")]),e._v(" result.")]),e._v(" "),t("p",[e._v("A typical configuration for this channel adapter might look like this:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\n@InboundChannelAdapter("fromR2dbcChannel")\npublic R2dbcMessageSource r2dbcMessageSourceSelectMany() {\n R2dbcMessageSource r2dbcMessageSource = new R2dbcMessageSource(this.r2dbcEntityTemplate,\n "SELECT * FROM person WHERE name=\'Name\'");\n r2dbcMessageSource.setPayloadType(Person.class);\n r2dbcMessageSource.setUpdateSql("UPDATE Person SET name=\'SomeOtherName\' WHERE id = :id");\n r2dbcMessageSource.setBindFunction(\n\t\t\t\t(DatabaseClient.GenericExecuteSpec bindSpec, Person o) -> bindSpec.bind("id", o.getId()));}\n return r2dbcMessageSource;\n}\n')])])]),t("p",[e._v("With Java DSL a configuration for this channel adapter is like this:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\nIntegrationFlow r2dbcDslFlow(R2dbcEntityTemplate r2dbcEntityTemplate) {\n return IntegrationFlows\n .from(R2dbc.inboundChannelAdapter(r2dbcEntityTemplate,\n (selectCreator) ->\n selectCreator.createSelect("person")\n .withProjection("*")\n .withCriteria(Criteria.where("id").is(1)))\n .expectSingleResult(true)\n .payloadType(Person.class)\n .updateSql("UPDATE Person SET id=\'2\' where id = :id")\n .bindFunction((DatabaseClient.GenericExecuteSpec bindSpec, Person o) ->\n bindSpec.bind("id", o.getId())),\n e -> e.poller(p -> p.fixedDelay(100)))\n .<Mono<?>>handle((p, h) -> p, e -> e.async(true))\n .channel(MessageChannels.flux())\n .get();\n}\n')])])]),t("h3",{attrs:{id:"r2dbc-outbound-channel-adapter"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#r2dbc-outbound-channel-adapter"}},[e._v("#")]),e._v(" R2DBC Outbound Channel Adapter")]),e._v(" "),t("p",[e._v("The "),t("code",[e._v("R2dbcMessageHandler")]),e._v(" is a "),t("code",[e._v("ReactiveMessageHandler")]),e._v(" implementation to perform an "),t("code",[e._v("INSERT")]),e._v(" (default), "),t("code",[e._v("UPDATE")]),e._v(" or "),t("code",[e._v("DELETE")]),e._v(" query in database using a provided "),t("code",[e._v("R2dbcEntityOperations")]),e._v(".\nThe "),t("code",[e._v("R2dbcMessageHandler.Type")]),e._v(" can be configured statically or via a SpEL expression against request message.\nThe query to execute can be based on the "),t("code",[e._v("tableName")]),e._v(", "),t("code",[e._v("values")]),e._v(" and "),t("code",[e._v("criteria")]),e._v(" expression options or (if "),t("code",[e._v("tableName")]),e._v(" is not provided) the whole message payload is treated as an "),t("code",[e._v("org.springframework.data.relational.core.mapping.Table")]),e._v(" entity to perform SQL against.\nThe package "),t("code",[e._v("org.springframework.data.relational.core.query")]),e._v(" is registered as an import into a SpEL evaluation context for direct access to the "),t("code",[e._v("Criteria")]),e._v(" fluent API which is used for "),t("code",[e._v("UPDATE")]),e._v(" and "),t("code",[e._v("DELETE")]),e._v(" queries.\nThe "),t("code",[e._v("valuesExpression")]),e._v(" is used in the "),t("code",[e._v("INSERT")]),e._v(" and "),t("code",[e._v("UPDATE")]),e._v(" and must be evaluated to the "),t("code",[e._v("Map")]),e._v(" for column-value pairs to perform a change in the target table against request message.")]),e._v(" "),t("p",[e._v("A typical configuration for this channel adapter might look like this:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('@Bean\n@ServiceActivator(inputChannel = "toR2dbcChannel")\npublic R2dbcMessageHandler r2dbcMessageHandler(R2dbcEntityTemplate r2dbcEntityTemplate) {\n R2dbcMessageHandler messageHandler = new R2dbcMessageHandler(r2dbcEntityTemplate)\n messageHandler.setValuesExpression(new FunctionExpression<Message<?>>(Message::getPayload));\n messageHandler.setQueryType(R2dbcMessageHandler.Type.UPDATE);\n messageHandler.setCriteriaExpression(\n EXPRESSION_PARSER.parseExpression("T(Criteria).where(\'id).is(headers.personId)));\n return messageHandler;\n}\n')])])]),t("p",[e._v("With Java DSL a configuration for this channel adapter is like this:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('.handle(R2dbc.outboundChannelAdapter(r2dbcEntityTemplate)\n .queryType(R2dbcMessageHandler.Type.UPDATE)\n .tableNameExpression("payload.class.simpleName")\n .criteria((message) -> Criteria.where("id").is(message.getHeaders().get("personId")))\n .values("{age:36}"))\n')])])])])}),[],!1,null,null,null);a.default=r.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[139],{562:function(t,e,r){"use strict";r.r(e);var n=r(56),a=Object(n.a)({},(function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"additional-resources"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#additional-resources"}},[t._v("#")]),t._v(" Additional Resources")]),t._v(" "),r("h2",{attrs:{id:"additional-resources-2"}},[r("a",{staticClass:"header-anchor",attrs:{href:"#additional-resources-2"}},[t._v("#")]),t._v(" Additional Resources")]),t._v(" "),r("p",[t._v("The definitive source of information about Spring Integration is the "),r("a",{attrs:{href:"https://projects.spring.io/spring-integration/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Spring Integration Home"),r("OutboundLink")],1),t._v(" at "),r("a",{attrs:{href:"https://spring.io",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://spring.io"),r("OutboundLink")],1),t._v(".\nThat site serves as a hub of information and is the best place to find up-to-date announcements about the project as well as links to articles, blogs, and new sample applications.")])])}),[],!1,null,null,null);e.default=a.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[160],{583:function(t,e,n){"use strict";n.r(e);var s=n(56),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]);
\ No newline at end of file
此差异已折叠。
(window.webpackJsonp=window.webpackJsonp||[]).push([[162],{585:function(t,e,n){"use strict";n.r(e);var s=n(56),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册