You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Undertow中同时运行Spring WebFlux与MVC(CXF、Shiro等)服务?

在Undertow中同时运行Spring MVC和Reactive WebFlux服务的方案

当然可以!你遇到的问题是因为Spring Boot默认会根据依赖自动选择Servlet栈(MVC)或Reactive栈(WebFlux),一旦选定就会禁用另一套核心组件,但通过手动配置上下文和Undertow容器适配,完全可以让两类服务共存。下面是具体的实现步骤和注意事项:

1. 确保依赖同时包含MVC和WebFlux

首先,在你的构建文件(Maven/Gradle)中同时引入Spring Web(MVC)和Spring WebFlux的starter,不要让Spring Boot自动排除任何一方:

Maven示例:

<dependencies>
    <!-- Spring MVC 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring WebFlux 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <!-- 你的其他依赖:Apache CXF、Shiro等 -->
</dependencies>

默认情况下,Spring Boot会优先启用Servlet栈(MVC),但WebFlux的端点不会自动注册,需要手动配置路由映射。

2. 配置Undertow同时处理MVC和WebFlux请求

我们需要手动把WebFlux的请求处理器绑定到Undertow的非阻塞处理链,让特定路径的请求由WebFlux处理,其余请求交给MVC/CXF处理:

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.reactive.UndertowServerHttpRequest;
import org.springframework.http.server.reactive.UndertowServerHttpResponse;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.server.ServerHttpRequest;
import org.springframework.web.server.ServerHttpResponse;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import io.undertow.servlet.api.DeploymentInfo;
import static io.undertow.Handlers.path;

@Configuration
public class DualStackWebConfig {

    @Bean
    public UndertowServletWebServerFactory undertowServerFactory(ApplicationContext context) {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        
        // 获取WebFlux的核心处理器
        DispatcherHandler webFluxDispatcher = context.getBean(DispatcherHandler.class);
        
        factory.addDeploymentInfoCustomizers((DeploymentInfo deploymentInfo) -> {
            // 创建路径处理器:把/reactive/**的请求转发给WebFlux
            HttpHandler webFluxHandler = exchange -> {
                ServerHttpRequest request = new UndertowServerHttpRequest(exchange);
                ServerHttpResponse response = new UndertowServerHttpResponse(exchange);
                webFluxDispatcher.handle(request, response).block();
            };
            
            // 把WebFlux处理器添加到Undertow的处理链
            deploymentInfo.addOuterHandlerChainWrapper(rootHandler -> 
                path()
                    .addPrefixPath("/reactive", webFluxHandler)
                    .addPrefixPath("/", rootHandler)
            );
        });
        
        return factory;
    }
}

这样,所有/reactive/**前缀的请求会被WebFlux处理,其他请求(包括MVC控制器、CXF REST服务)依然由Servlet栈处理。

3. 适配Shiro安全机制到双栈

因为Shiro默认是基于Servlet的过滤器,需要同时配置适用于MVC的Servlet过滤器和适用于WebFlux的路由过滤器:

保持原有的Shiro MVC配置(用于Servlet栈)

@Configuration
public class ShiroMvcConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);
        
        // 你的原有过滤器链配置,比如:
        Map<String, String> filterChain = new HashMap<>();
        filterChain.put("/mvc/secured/**", "authc");
        filterChain.put("/cxf/rest/**", "authc");
        factoryBean.setFilterChainDefinitionMap(filterChain);
        
        return factoryBean;
    }

    // 其他Shiro相关Bean:SecurityManager、Realm等...
}

添加Shiro WebFlux配置(用于响应式栈)

@Configuration
public class ShiroWebFluxConfig {

    @Bean
    public ShiroWebFilter shiroWebFilter(SecurityManager securityManager) {
        ShiroWebFilter webFilter = new ShiroWebFilter();
        webFilter.setSecurityManager(securityManager);
        
        // 配置响应式路径的安全规则
        Map<String, String> filterChain = new HashMap<>();
        filterChain.put("/reactive/secured/**", "authc");
        webFilter.setFilterChainDefinitionMap(filterChain);
        
        return webFilter;
    }

    // 将Shiro过滤器绑定到WebFlux路由
    @Bean
    public RouterFunction<ServerResponse> securedReactiveRoutes(ShiroWebFilter shiroFilter) {
        return RouterFunctions.route()
                .GET("/reactive/secured/hello", req -> ServerResponse.ok().bodyValue("Secured Reactive Response"))
                .filter(shiroFilter)
                .build();
    }
}

4. 关键注意事项

  • 路径隔离:务必确保MVC、CXF和WebFlux的路径没有重叠,否则会导致请求处理混乱(比如/api/**不要同时被MVC和WebFlux使用)。
  • 线程模型差异:MVC使用阻塞IO线程池,WebFlux使用Undertow的非阻塞IO线程池,需要根据服务负载调整两类线程池的大小,避免资源竞争。
  • Spring版本:建议使用Spring 5.3及以上版本,早期版本对双栈共存的支持不够完善。
  • CXF兼容性:CXF是基于Servlet的REST框架,它的端点会自动融入Servlet栈,无需额外调整,只要路径不冲突即可。

通过以上配置,你就能在Undertow容器中同时运行MVC风格服务、Apache CXF REST服务和Spring Reactive响应式服务了。

内容的提问来源于stack exchange,提问作者KJQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:11:02