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

多Swagger2Feature实例集成异常:第二个实例扫描错误包路径求助

解决多Swagger实例扫描错误包的问题

看起来你遇到的核心问题是多个Swagger实例的资源扫描范围冲突,加上Web层的Servlet配置没有正确隔离两个上下文。我来一步步帮你修正配置:

问题根源分析

  1. Web层Servlet配置缺失:你的web.xml只配置了一个CXFServlet,仅加载context2.xml,根本没把第一个上下文(rest1)部署进去,两个上下文需要独立的Servlet来做隔离。
  2. JAX-RS Server Bean名称冲突:两个context里的<jaxrs:server>id都是container,如果同时加载会导致Spring容器内的bean名称重复,引发覆盖问题。
  3. Swagger扫描策略错误:scanAllResources="true"会强制Swagger扫描所有已注册的JAX-RS资源,完全忽略你指定的resourcePackage,这就是第二个实例扫到第一个包的直接原因。

修正后的完整配置

1. 修改web.xml:添加两个独立的CXFServlet

每个Servlet对应一个上下文,映射到不同的URL路径,确保两个实例完全隔离:

<web-app>
    <!-- 第一个Swagger实例:对应rest1路径 -->
    <servlet>
        <servlet-name>AppSwaggerCXFServlet1</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <init-param>
            <param-name>config-location</param-name>
            <param-value>classpath*:/context1.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AppSwaggerCXFServlet1</servlet-name>
        <url-pattern>/rest1/*</url-pattern>
    </servlet-mapping>

    <!-- 第二个Swagger实例:对应rest2路径 -->
    <servlet>
        <servlet-name>AppSwaggerCXFServlet2</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <init-param>
            <param-name>config-location</param-name>
            <param-value>classpath*:/context2.xml</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AppSwaggerCXFServlet2</servlet-name>
        <url-pattern>/rest2/*</url-pattern>
    </servlet-mapping>
</web-app>

2. 修改context1.xml:修正Server ID和Swagger扫描策略

把<jaxrs:server>的id改成唯一的container1,并将scanAllResources设为false,确保只扫描指定包:

<context:component-scan base-package="org.app.rest.cxf.service"/>
<bean id="swagger2customizer" class="org.apache.cxf.jaxrs.swagger.Swagger2Customizer">
    <property name="dynamicBasePath" value="true"/>
    <property name="replaceTags" value="true"/>
</bean>
<bean id="swagger2Feature" class="org.apache.cxf.jaxrs.swagger.Swagger2Feature">
    <property name="title" value="Test"/>
    <property name="version" value="1.0"/>
    <property name="description" value="Test 1.0"/>
    <property name="contact" value="dev@syncope.apache.org"/>
    <property name="resourcePackage" value="org.app.rest.api.service"/>
    <!-- 关键:关闭全量扫描,只扫描指定包 -->
    <property name="scanAllResources" value="false"/>
    <property name="activateOnlyIfJaxrsSupported" value="true"/>
    <property name="customizer" ref="swagger2customizer"/>
</bean>
<!-- 修改id为container1,避免与第二个实例的bean冲突 -->
<jaxrs:server id="container1" address="/" basePackages="org.app.rest.api.service, org.app.rest.cxf.service" staticSubresourceResolution="true">
    <jaxrs:properties>
        <entry key="search.lax.property.match" value="true"/>
        <entry key="convert.wadl.resources.to.dom" value="false"/>
    </jaxrs:properties>
    <jaxrs:inInterceptors>
        <ref bean="gzipInInterceptor"/>
        <ref bean="validationInInterceptor"/>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
        <ref bean="gzipOutInterceptor"/>
        <ref bean="validationOutInterceptor"/>
    </jaxrs:outInterceptors>
    <jaxrs:providers>
        <ref bean="dateParamConverterProvider"/>
        <ref bean="jaxbProvider"/>
        <ref bean="jsonProvider"/>
        <ref bean="exceptionMapper"/>
        <ref bean="searchContextProvider"/>
        <ref bean="addDomainFilter"/>
        <ref bean="addETagFilter"/>
        <ref bean="wadlGenerator"/>
    </jaxrs:providers>
    <jaxrs:features>
        <ref bean="swagger2Feature"/>
    </jaxrs:features>
</jaxrs:server>

3. 修改context2.xml:同样修正Server ID和Swagger扫描策略

把<jaxrs:server>的id改成container2,scanAllResources设为false:

<context:component-scan base-package="com.app2.rest.cxf.service"/>
<bean id="swagger2customizer2" class="org.apache.cxf.jaxrs.swagger.Swagger2Customizer">
    <property name="dynamicBasePath" value="true"/>
    <property name="replaceTags" value="true"/>
</bean>
<bean id="swagger2Feature2" class="org.apache.cxf.jaxrs.swagger.Swagger2Feature">
    <property name="title" value="Test"/>
    <property name="version" value="1.0"/>
    <property name="description" value="Test 1.0"/>
    <property name="contact" value="dev@syncope.apache.org"/>
    <property name="resourcePackage" value="com.app2.rest.api.service"/>
    <!-- 关键:关闭全量扫描,只扫描指定包 -->
    <property name="scanAllResources" value="false"/>
    <property name="activateOnlyIfJaxrsSupported" value="true"/>
    <property name="customizer" ref="swagger2customizer2"/>
</bean>
<!-- 修改id为container2,避免与第一个实例的bean冲突 -->
<jaxrs:server id="container2" address="/" basePackages="com.app2.rest.api.service, com.app2.rest.cxf.service" staticSubresourceResolution="true">
    <jaxrs:properties>
        <entry key="search.lax.property.match" value="true"/>
        <entry key="convert.wadl.resources.to.dom" value="false"/>
    </jaxrs:properties>
    <jaxrs:inInterceptors>
        <ref bean="gzipInInterceptor"/>
        <ref bean="validationInInterceptor"/>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
        <ref bean="gzipOutInterceptor"/>
        <ref bean="validationOutInterceptor"/>
    </jaxrs:outInterceptors>
    <jaxrs:providers>
        <ref bean="dateParamConverterProvider"/>
        <ref bean="jaxbProvider"/>
        <ref bean="jsonProvider"/>
        <ref bean="exceptionMapper"/>
        <ref bean="searchContextProvider"/>
        <ref bean="addDomainFilter"/>
        <ref bean="addETagFilter"/>
        <ref bean="wadlGenerator"/>
    </jaxrs:providers>
    <jaxrs:features>
        <ref bean="swagger2Feature2"/>
    </jaxrs:features>
</jaxrs:server>

验证效果

配置完成后重启应用,访问:

  • 第一个Swagger:http://localhost:8080/app/rest1/swagger.json,应该只包含org.app.rest.api.service下的端点
  • 第二个Swagger:http://localhost:8080/app/rest2/swagger.json,应该只包含com.app2.rest.api.service下的端点

核心逻辑就是通过独立的Servlet隔离两个上下文,加上关闭Swagger的全量扫描确保只扫描指定包,同时避免Spring Bean名称冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:40:11