如何在Spring应用程序中定义基于URI/包/控制器的WebFlux配置

问题描述 投票:0回答:1

我有一个 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,或映射到特定的控制器或包,无论哪种方式都有效。

非常感谢任何帮助。 谢谢!

java spring rest spring-webflux uri
1个回答
0
投票

如果您想在 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
}

完成上述内容后:

  • 对 /workflow/... 的请求将触发
    WorkflowWebFluxConfiguration
  • 对 /activity/... 的请求将触发
    ActivityWebFluxConfiguration

WebFilter
HandlerMapping
确保正确的路由,而条件 bean 处理上下文特定的行为。

© www.soinside.com 2019 - 2024. All rights reserved.