使用Jersey 1.19的Swagger JAX-RS提供了“冲突的URI模板”#39;错误

时间:2015-10-01 19:25:27

标签: java jersey swagger

我正在尝试将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 个答案:

答案 0 :(得分:2)

更新2:看起来版本1.5.8的swagger核心修复程序问题。有关详细信息,请参阅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 param:

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

BTW,我注意到<filter/>中使用web.xml配置Jersey的GF 3.1.2.2由于Grizzly related bug而无法与Swagger一起使用。

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

@Path("/") 
class RootResource {
    @Context ServletContext context;

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

由于ApiListingResource现在不受泽西岛管理,因此不会注入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之下,您仍然可以使用根资源。

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