日志记录通道适配器
Theis 通常与窃听器结合使用,如Wire Tap 中所讨论的。 但是,它也可以用作任何流的最终使用者。 例如,假设一个流以 a结尾,返回一个结果,但您希望放弃该结果。 为此,您可以将结果发送到。 或者,您可以将其路由到水平。 这样,您可以在级别记录时看到丢弃的消息,但在(例如)级别记录时看不到它。 使用 a,在级别记录时只会看到丢弃的消息。 下面的清单显示了元素的所有可能属性:<logging-channel-adapter>
<service-activator>
NullChannel
INFO
<logging-channel-adapter>
INFO
WARN
NullChannel
DEBUG
logging-channel-adapter
<int:logging-channel-adapter
channel=""
level="INFO"
expression=""
log-full-message="false"
logger-name="" />
将日志记录适配器连接到上游组件的通道。 |
将记录发送到此适配器的消息的日志记录级别。 违约:。INFO |
一个 SpEL 表达式,准确表示记录消息的哪些部分。 默认值:— 仅记录有效负载。 指定了 IFIS,则无法指定此属性。payload log-full-message |
何时,记录整个消息(包括标头)。 默认值:— 仅记录有效负载。 不能指定此属性 ifis。true false expression |
指定记录器(称为 asin)。 用于标识此适配器创建的日志消息。 这样就可以为单个适配器设置日志名称(在日志记录子系统中)。 默认情况下,所有适配器都以以下名称记录:。name category log4j org.springframework.integration.handler.LoggingHandler |
使用 Java 配置
以下 Spring 引导应用程序显示了使用 Java 配置进行配置的示例:LoggingHandler
@SpringBootApplication
public class LoggingJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(LoggingJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToLogger("foo");
}
@Bean
@ServiceActivator(inputChannel = "logChannel")
public LoggingHandler logging() {
LoggingHandler adapter = new LoggingHandler(LoggingHandler.Level.DEBUG);
adapter.setLoggerName("TEST_LOGGER");
adapter.setLogExpressionString("headers.id + ': ' + payload");
return adapter;
}
@MessagingGateway(defaultRequestChannel = "logChannel")
public interface MyGateway {
void sendToLogger(String data);
}
}
使用 Java DSL 进行配置
以下 Spring 引导应用程序显示了使用 Java DSL 配置日志记录通道适配器的示例:
@SpringBootApplication
public class LoggingJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(LoggingJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToLogger("foo");
}
@Bean
public IntegrationFlow loggingFlow() {
return IntegrationFlow.from(MyGateway.class)
.log(LoggingHandler.Level.DEBUG, "TEST_LOGGER",
m -> m.getHeaders().getId() + ": " + m.getPayload());
}
@MessagingGateway
public interface MyGateway {
void sendToLogger(String data);
}
}
java.util.function
接口支持
从版本 5.1 开始,Spring 集成为软件包中的接口提供了直接支持。 所有消息传递端点(服务激活器、转换器、筛选器等)现在可以引用(或)bean。 消息传递注释可以直接应用于这些 bean,类似于常规定义。 例如,如果您有这个豆定义:java.util.function
Function
Consumer
MessageHandler
Function
@Configuration
public class FunctionConfiguration {
@Bean
public Function<String, String> functionAsService() {
return String::toUpperCase;
}
}
您可以将其用作 XML 配置文件中的简单引用:
<service-activator input-channel="processorViaFunctionChannel" ref="functionAsService"/>
当我们使用消息传递注释配置流时,代码很简单:
@Bean
@Transformer(inputChannel = "functionServiceChannel")
public Function<String, String> functionAsService() {
return String::toUpperCase;
}
当函数返回一个数组时,(本质上是 any)或 Reactor,可以在这样的 bean 上使用,对结果内容执行迭代。Collection
Iterable
Stream
Flux
@Splitter
该接口可用于 anor,与注释一起执行流的最后一步:java.util.function.Consumer
<int:outbound-channel-adapter>
@ServiceActivator
@Bean
@ServiceActivator(inputChannel = "messageConsumerServiceChannel")
public Consumer<Message<?>> messageConsumerAsService() {
// Has to be an anonymous class for proper type inference
return new Consumer<Message<?>>() {
@Override
public void accept(Message<?> e) {
collector().add(e);
}
};
}
另外,请注意上面代码片段中的注释:如果您想处理您/您/中的整个消息,则不能使用 lambda 定义。 由于 Java 类型擦除,我们无法确定方法调用的目标类型。Function
Consumer
apply()/accept()
该接口可以简单地与注释一起使用,也可以作为:java.util.function.Supplier
@InboundChannelAdapter
ref
<int:inbound-channel-adapter>
@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<String> pojoSupplier() {
return () -> "foo";
}
使用 Java DSL,我们只需要在端点定义中使用对函数 Bean 的引用。 同时,接口的实现可以用作常规定义:Supplier
MessageSource
@Bean
public Function<String, String> toUpperCaseFunction() {
return String::toUpperCase;
}
@Bean
public Supplier<String> stringSupplier() {
return () -> "foo";
}
@Bean
public IntegrationFlow supplierFlow() {
return IntegrationFlow.from(stringSupplier())
.transform(toUpperCaseFunction())
.channel("suppliedChannel")
.get();
}
当与 Spring Cloud 函数框架一起使用时,此函数支持非常有用,在Spring Cloud函数框架中,我们有一个函数目录,可以从集成流定义中引用其成员函数。
科特林支持
该框架也得到了改进,以支持 Kotlin lambda 的函数,所以现在你可以使用 Kotlin 语言和 Spring Integration 流程定义的组合:
@Bean
@Transformer(inputChannel = "functionServiceChannel")
fun kotlinFunction(): (String) -> String {
return { it.toUpperCase() }
}
@Bean
@ServiceActivator(inputChannel = "messageConsumerServiceChannel")
fun kotlinConsumer(): (Message<Any>) -> Unit {
return { print(it) }
}
@Bean
@InboundChannelAdapter(value = "counterChannel",
poller = Poller(fixedRate = "10", maxMessagesPerPoll = "1"))
fun kotlinSupplier(): () -> String {
return { "baz" }
}
Kotlin 协程
从 6.0 版开始,Spring Integration 提供了对Kotlin 协程的支持。 Nowfunctions 和 &return 类型可用于服务方法:suspend
kotlinx.coroutines.Deferred
kotlinx.coroutines.flow.Flow
@ServiceActivator(inputChannel = "suspendServiceChannel", outputChannel = "resultChannel")
suspend fun suspendServiceFunction(payload: String) = payload.uppercase()
@ServiceActivator(inputChannel = "flowServiceChannel", outputChannel = "resultChannel", async = "true")
fun flowServiceFunction(payload: String) =
flow {
for (i in 1..3) {
emit("$payload #$i")
}
}
该框架将它们视为反应式流交互,并用于转换为相关和反应器类型。 这样的函数回复然后在回复通道中处理,如果它是一个,或者作为相应回调的结果。ReactiveAdapterRegistry
Mono
Flux
ReactiveStreamsSubscribableChannel
CompletableFuture
带有结果的函数不是默认的,so实例是作为回复消息有效负载生成的。 目标应用程序负责将此对象作为协程处理或分别转换为协程。Flow async @ServiceActivator Flow Flux |
接口方法在 Kotlin 中声明时也可以用修饰符标记。 该框架利用内部使用下游流执行请求-回复。 这样的结果由 API 在内部处理,以满足网关调用函数的参数:@MessagingGateway
suspend
Mono
Mono
MonoKt.awaitSingleOrNull()
kotlin.coroutines.Continuation
suspend
@MessagingGateway(defaultRequestChannel = "suspendRequestChannel")
interface SuspendFunGateway {
suspend fun suspendGateway(payload: String): String
}
此方法必须根据 Kotlin 语言要求作为协程调用:
@Autowired
private lateinit var suspendFunGateway: SuspendFunGateway
fun someServiceMethod() {
runBlocking {
val reply = suspendFunGateway.suspendGateway("test suspend gateway")
}
}