【问题标题】:Jersey: Unable to Get Sub-Sub-ResourceJersey:无法获取子子资源
【发布时间】:2016-10-15 11:37:05
【问题描述】:

我有一个使用 Jersey 实现 REST API 的 Web 应用程序。 Web 容器 ID Tomcat
以下是 API 的摘要:

/rest/patients
获取患者元数据列表。

/rest/patients/{id}
获取有关特定患者的详细数据。

/rest/patients/{id}/visits
获取特定患者的就诊元数据列表。

/rest/patients/{id}/visits/{visitId}
获取有关特定患者的特定就诊的详细数据。

我的问题是我无法获取子子资源。例如,当我请求/rest/patients/1 时,正确接收到患者#1 的详细数据。
但是当我请求/rest/patients/1/visits 时,我得到404 错误,并且流程甚至没有进入getVisits() 方法。
看起来,当收到对特定患者 ID 的请求 (patients/{id}) 时,Jersey 将其正确地从 PatientsMetadataResource 引导到 PatientsResource
但是当请求访问子子资源 (patients/{id}/visits) 时,Jersey 不会将其定向到 PatientsResource

那么我怎样才能将一个子资源连同它的所有子子资源引导到同一个类中呢?

PatientsMetadataResource的代码(名字有点模糊,需要改一下):

@Path("/patients")
public class PatientsMetadataResource {

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Response getPatients(@QueryParam("page") int pageIndex) {
    //.... Loads, Builds and returns the patients' metadata list correctly
  }

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("/{uid:\\d+}")
  public PatientResource getPatient(@PathParam("uid") int uid) {
        return new PatientResource(uid);
  }

}

PatientResource 的代码:

public class PatientResource {

  private final int uid;

  public PatientResource(int uid) {
    this.uid = uid;
  }

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public Response getPatient() {
    //Returns the patient correctly
    System.out.println("A Patient was asked");
    Patient patient = PersistentDataProvider.loadPatientByUid(uid);
    return Response.ok(patient).build();
  }

  @GET
  @Path("/visits")
  @Produces(MediaType.APPLICATION_JSON)
  public VisitsResource getVisits(@PathParam("uid") int patientUid) {
    //The flow doesn't even enter here. A 404 is being returned instead.
    System.out.println("Visits were asked");
    return new VisitsResource(patientUid);
  }
}

web.xml 中 Jersey 部分的代码:

<servlet>
    <servlet-name>Jersey REST Service</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>il.co.site_building.dvardy.resources</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

【问题讨论】:

  • PatientResource .. 的根资源路径是什么?

标签: java rest tomcat jersey-2.0


【解决方案1】:

子资源定位器不应该有 HTTP 方法注释

// @GET    <--- Remove this
// @Produces(MediaType.APPLICATION_JSON)
@Path("/{uid:\\d+}")
public PatientResource getPatient(@PathParam("uid") int uid) {
   return new PatientResource(uid);
}

它们的主要目的只是将请求转发到子资源类,而不是 GET/POST/etc 任何东西。当 Jersey 看到 HTTP 方法注释时,它不再被视为子资源定位器。

您也不需要传递 id。它会相应地通过

@Path("parent")
class ParentResource {
    @Path("{id}")
    public ChildResource  getChild() {
      return new ChildResource();
    }
}

class ChildResource {
    @GET
    public Response get(@PathParam("id") long id) {}

    @GET
    @Path("something")
    public Response something(@PathParam("id") long id) {}
}

这里 GET 'parent/1' 转到 ChildResource.get,传递路径参数,GET parent/1/something 转到 ChilsResource.something,传递路径参数

【讨论】:

  • 有没有办法将其重定向到子资源,而无需显式创建子资源的新实例,例如。返回新的 ChildResource();为什么我要问这个是因为如果 ChildResource 碰巧有一些 Spring 托管依赖项,例如 Autowired ChildService,那么显式创建资源的新实例将不会解决 Autowired 依赖项,并且在运行时它将为 null。我实际上正面临这个问题。
  • @maddy 将ResourceContext 注入父资源并使用resourceContext.getResource(ChildResource.class) 获取资源而不是实例化它。
猜你喜欢
  • 2011-11-19
  • 1970-01-01
  • 2015-07-28
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多