我有一个 Spring 应用程序,其中有不同的休息控制器。 我想为不同的控制器使用不同的 WebFluxConfigurations。
例如,对于“configureHttpMessageCodecs”,我希望基于控制器或基于 URI 有不同的编解码器。
我还希望对“nettyCustomizer”bean 和不同的“openApiInteractionValidator”bean 有不同的实现,同样基于控制器/URI。
我知道有一种方法可以通过使用 DelegatingWebFluxConfiguration 来做到这一点,但我在网上找到的文档很少,以便了解如何实现我需要的内容。
到目前为止我尝试做的是有 2 个 WebFluxConfigurer 的实现:
@Configuration
public class WorkflowWebFluxConfiguration implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
// Register custom json encoder/decoders for both application/json and application/hal+json, using our own object
// mapper.
configurer.customCodecs()
.registerWithDefaultConfig(new Jackson2JsonEncoder(workflowObjectMapper, MIME_TYPE_HAL, MimeTypeUtils.APPLICATION_JSON));
configurer.customCodecs()
.registerWithDefaultConfig(new Jackson2JsonDecoder(workflowObjectMapper, MIME_TYPE_HAL, MimeTypeUtils.APPLICATION_JSON));
}
和:
@Configuration
public class ActivityWebFluxConfiguration implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonEncoder(objectMapper, SUPPORTED_MIMETYPES));
configurer.customCodecs().registerWithDefaultConfig(new Jackson2JsonDecoder(objectMapper, SUPPORTED_MIMETYPES));
}
@Bean
public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> nettyCustomizer() {
return factory -> factory
.addServerCustomizers(httpServer -> httpServer.httpRequestDecoder(spec -> spec.maxInitialLineLength(MAX_URI_LENGTH)));
}
@Bean
public OpenApiInteractionValidator openApiInteractionValidator(
@Value("classpath:apispecs/activity-v3.yaml") final Resource apiSpecification) throws IOException {
我实现了这个:
@Configuration
public class MainWebFluxConfiguration extends DelegatingWebFluxConfiguration {
@Autowired
public MainWebFluxConfiguration(WorkflowWebFluxConfiguration workflowWebFluxConfiguration,
ActivityWebFluxConfiguration activityWebFluxConfiguration) {
log.info("YYY main config web flux");
this.setConfigurers(List.of(workflowWebFluxConfiguration, activityWebFluxConfiguration));
}
}
但除此之外,我不明白我如何路由/指向/配置每个 WebFluxConfiguration 来处理特定的 URI,或映射到特定的控制器或包,无论哪种方式都有效。
非常感谢任何帮助。 谢谢!
如果您想在 Spring
WebFluxConfigurer
应用程序中基于 URI 或控制器拥有不同的 WebFlux
配置,有几种方法可以实现这一点。这是一步一步的细分:
您可以结合使用 HandlerMapping、请求属性和条件配置来实现此目的。方法如下:
要根据请求 URI 有条件地应用配置,您可以使用 WebFilter 来检查 URI 并设置自定义属性。然后可以使用此属性来确定要应用的配置。
@Configuration
public class MainWebFluxConfiguration implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
// Default codecs
configurer.customCodecs().registerWithDefaultConfig(new DefaultJsonEncoder());
configurer.customCodecs().registerWithDefaultConfig(new DefaultJsonDecoder());
}
@Bean
public WebFilter uriBasedFilter() {
return (exchange, chain) -> {
String path = exchange.getRequest().getPath().value();
if (path.startsWith("/workflow")) {
exchange.getAttributes().put("customCodec", "workflow");
} else if (path.startsWith("/activity")) {
exchange.getAttributes().put("customCodec", "activity");
}
return chain.filter(exchange);
};
}
}
这里: 过滤器检查 URI 并附加自定义属性(例如,具有
"workflow"
或 "activity"
等值的“customCodec”)。
此属性稍后可用于动态自定义行为。
如果您将控制器分组到包中(例如,
com.example.workflow.controller
和com.example.activity.controller
),您可以使用HandlerMapping
将不同的控制器绑定到特定的URI前缀。
@Configuration
public class WorkflowWebFluxConfiguration implements WebFluxConfigurer {
@Bean
public HandlerMapping workflowHandlerMapping() {
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
mapping.setOrder(0); // Higher priority
mapping.setPathPrefixes(Collections.singletonMap("/workflow", "com.example.workflow.controller"));
return mapping;
}
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.customCodecs().registerWithDefaultConfig(new WorkflowJsonEncoder());
configurer.customCodecs().registerWithDefaultConfig(new WorkflowJsonDecoder());
}
}
@Configuration
public class ActivityWebFluxConfiguration implements WebFluxConfigurer {
@Bean
public HandlerMapping activityHandlerMapping() {
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
mapping.setOrder(1); // Lower priority
mapping.setPathPrefixes(Collections.singletonMap("/activity", "com.example.activity.controller"));
return mapping;
}
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.customCodecs().registerWithDefaultConfig(new ActivityJsonEncoder());
configurer.customCodecs().registerWithDefaultConfig(new ActivityJsonDecoder());
}
}
这里:
每个 HandlerMapping 将 URI 前缀(/workflow 或 /activity)与特定的控制器包相关联。 相应的 WebFluxConfigurer 实现为每个组提供自定义行为。
您可以创建根据之前设置的请求属性激活的条件bean。
nettyCustomizer
的示例:
@Bean
@ConditionalOnRequestAttribute(name = "customCodec", value = "workflow")
public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> workflowNettyCustomizer() {
return factory -> factory.addServerCustomizers(httpServer ->
httpServer.httpRequestDecoder(spec -> spec.maxInitialLineLength(8192)));
}
@Bean
@ConditionalOnRequestAttribute(name = "customCodec", value = "activity")
public WebServerFactoryCustomizer<NettyReactiveWebServerFactory> activityNettyCustomizer() {
return factory -> factory.addServerCustomizers(httpServer ->
httpServer.httpRequestDecoder(spec -> spec.maxInitialLineLength(4096)));
}
openApiInteractionValidator
的示例:
@Bean
@ConditionalOnRequestAttribute(name = "customCodec", value = "workflow")
public OpenApiInteractionValidator workflowOpenApiValidator() throws IOException {
return new OpenApiInteractionValidator(...); // Workflow-specific OpenAPI spec
}
@Bean
@ConditionalOnRequestAttribute(name = "customCodec", value = "activity")
public OpenApiInteractionValidator activityOpenApiValidator() throws IOException {
return new OpenApiInteractionValidator(...); // Activity-specific OpenAPI spec
}
完成上述内容后:
WorkflowWebFluxConfiguration
。ActivityWebFluxConfiguration
。
WebFilter
或 HandlerMapping
确保正确的路由,而条件 bean 处理上下文特定的行为。