【问题标题】:Swagger JAX-RS with Jersey 1.19 gives 'Conflicting URI templates' error带有 Jersey 1.19 的 Swagger JAX-RS 给出“冲突的 URI 模板”错误
【发布时间】:2015-10-01 19:25:27
【问题描述】:

我正在尝试将 Swagger 添加到使用 Jersey 1.19 的现有应用程序中。为了将 Swagger 添加到应用程序中,我一直遵循本指南:https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-1.X-Project-Setup-1.5。

当我在 Apache Tomcat 上部署应用程序时,我收到以下错误:

SEVERE: Conflicting URI templates. The URI template / for root resource class io.swagger.jaxrs.listing.ApiListingResource and the URI template / transform to the same regular expression (/.*)?

奇怪的是,我的 Jersey servlet 没有部署在根上下文中,而是部署在 /api/* 上下文中,如 web.xml 文件所示:

<servlet>
    <servlet-name>MyApp Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>app.MyApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>MyApp Service</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

我的 MyApplication 类定义如下:

public class MyApplication extends Application {

private final Set<Object> singletons = new HashSet<Object>();
private final Set<Class<?>> classes = new HashSet<Class<?>>();

public MyApplication() {

    MyResource resource= new MyResource();

    singletons.addAll(Arrays.asList(resource));

    BeanConfig beanConfig = new BeanConfig();
    beanConfig.setBasePath("/api");
    beanConfig.setResourcePackage(getClass().getPackage().getName());
    beanConfig.setTitle("REST API");
    beanConfig.setVersion("1.0.0");
    beanConfig.setScan(true);

    classes.add(io.swagger.jaxrs.listing.ApiListingResource.class);
    classes.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
}

@Override
public Set<Class<?>> getClasses() {
    return classes;
}

@Override
public Set<Object> getSingletons() {
    return singletons;
}}

我尝试了其他配置,比如在web.xml文件中定义Swagger servlet而不是使用BeanConfig,但是还是出现同样的错误。我已经让 Swagger 在另一个使用 Jersey 2 的项目上以这种方式工作,但不幸的是,当前项目必须保留在 Jersey 1.19 上。下面是 pom.xml 文件中定义的 Swagger 依赖:

<dependency>
  <groupId>io.swagger</groupId>
  <artifactId>swagger-jersey-jaxrs</artifactId>
  <version>1.5.0</version>
</dependency>

任何帮助将不胜感激。

【问题讨论】:

    标签: java jersey swagger


    【解决方案1】:

    更新 2: swagger-core 的 1.5.8 版似乎修复了该问题。详情请见this commit。


    更新:无需将 Swagger 资源添加为子资源,只需覆盖 @Path 映射就容易得多。有关详细信息,请参阅解决方案 2。


    我面临着完全相同的问题。原因是 Swagger 资源被映射到根 @Path("/") public class ApiListingResource。


    解决方案 1 - 没有并发映射

    一种简单且不灵活的方法是不定义任何到根路径@Path("/")的资源映射。


    解决方案 2 - 覆盖 @Path 映射

    2.1 覆盖 Swagger 类

    ApiListingResource 应该得到一个新的@Path 映射

    package my.api.package.swagger
    
    import javax.ws.rs.Path;
    
    @Path("swagger")
    public class ApiListingResource extends io.swagger.jaxrs.listing.ApiListingResource {}
    

    SwaggerSerializers 应该得到新的包

    package my.api.package.swagger;
    
    import javax.ws.rs.ext.Provider;
    
    @Provider
    public class SwaggerSerializers extends io.swagger.jaxrs.listing.SwaggerSerializers {}
    

    2.2 配置覆盖类

    在 Swagger 包配置中添加 my.api.package.swagger 而不是 io.swagger.jaxrs.listing。


    解决方案 3 - Swagger 资源作为子资源

    其他解决方案是将 Swagger 移动到不同的路径,允许您将资源映射到您喜欢的任何位置。为此,您需要:

    3.1 从提供程序类中删除 ApiListingResource。

    如果你继承Application:

    public MyApplication() {
        //init BeanConfig
        //add your resource classes
    
        //classes.add(io.swagger.jaxrs.listing.ApiListingResource.class);
        classes.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
    }
    

    如果您通过web.xml 使用com.sun.jersey.config.property.packages 参数进行配置:

    <servlet>
        <servlet-name>your-rest-api</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>
                {your_application_packages},
                <!--io.swagger.jaxrs.json,-->
                <!--io.swagger.jaxrs.listing-->
            </param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.property.classnames</param-name>
            <param-value>
                io.swagger.jaxrs.listing.SwaggerSerializers,
                io.swagger.jaxrs.json.JacksonJsonProvider
            </param-value>
        </init-param>
    </servlet>
    

    顺便说一句,我注意到在 web.xml 中使用 &lt;filter/&gt; 配置 Jersey 的 GF 3.1.2.2 不适用于 Swagger,因为 Grizzly related bug。

    3.2 将ApiListingResources 作为子资源添加到您的一个资源中

    @Path("/") 
    class RootResource {
        @Context ServletContext context;
    
        @Path("/swagger")
        public ApiListingResource swagger() {
            return new ApiListingSubResource(context);
        }
    }
    

    由于 ApiListingResource 现在不受 Jersey 管理,因此不会注入 ServletContext。要克服这个问题,您必须将其作为构造函数参数传递,并为该子类ApiListingResource 提供适当的构造函数:

    // context has 'default' visibility
    // so we need to stay in the same package 
    // to be able to access it
    package io.swagger.jaxrs.listing;
    
    import javax.servlet.ServletContext;
    
    public class ApiListingSubResource extends ApiListingResource {
        public ApiListingSubResource(ServletContext sc) { this.context = sc; }
    }
    

    现在您的 Swagger 描述符将位于 http://hostname/app-path/swagger/swagger.json 下,您仍然可以使用根资源。

    这是一个有点长的方式,但有效!希望对您有所帮助。

    【讨论】:

    • 从 1.5.0 升级到 1.5.8 为我解决了这个问题,谢谢!
    猜你喜欢
    • 2016-02-14
    • 2018-01-15
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多