首页 文章

Swagger JAX-RS和Jersey 1.19给出'Conflicting URI templates'错误

提问于
浏览
1

我正在尝试将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>

任何帮助,将不胜感激 .

1 回答

  • 2

    Update 2: 看起来像版本1.5.8的swagger核心修复问题 . 有关详细信息,请参见this commit .


    Update: 不是将Swagger资源添加为子资源,而是更容易覆盖 @Path 映射 . 详细信息请参见解决方案2


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


    解决方案1 - 没有同意的映射

    围绕它的一种简单且不灵活的方式是 not 来定义到根路径 @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);
    }
    

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

    <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>
    

    顺便说一句,我注意到由于Grizzly related bug,在 web.xml 中使用 <filter/> 配置Jersey的GF 3.1.2.2不能与Swagger一起使用 .

    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 之下,你仍然可以使用root资源 .

    它有点长,但有效!希望有所帮助 .

相关问题