如何在POST期间获取不同资源的JAX-RS @Path?

时间:2012-02-23 17:34:59

标签: java rest path jersey jax-rs

我有两个REST类用于简单的Web服务(Jersey和GlassFish),它涉及用户资源 - 一个用于操作所有用户(例如,@POSTing的工厂),另一个用于个人用户(例如@GET,@ PUT,@ DELETE)。他们在:

@Stateless @Path("users") public class AllUsersResource {...}
@Stateless @Path("user") public class OneUserResource {...}

分别。在POST到AllUsersResource时,我想返回新用户的位置(通过Response.created(uri).build()),例如,

http://localhost:8080/.../user/152

我的问题是如何做到这一点。 AllUsersResource注入了@Context UriInfo uriInfo,但这并没有让我获得OneUserResource的@Path信息,只获得当前调用的信息(“users”)。我最终使用它的方式只是使用反射,但我担心它是脆弱和不洁的:

OneUserResource.class.getAnnotation(Path.class).value();

搜索StackOverflow我发现尝试的其他事情如下,但没有成功:

  • com.sun.jersey.api.core.ResourceContext
  • javax.ws.rs.core.UriInfo.getMatchedResources()
  • @ javax.inject.Inject OneUserResource oneUserRes;

任何帮助都会非常棒!

4 个答案:

答案 0 :(得分:14)

您可以使用UriBuilder.fromresource(),但这仅在提供的Resource类是根资源时才有效(这在javadocs中有明确提及)。即使您在子资源类中,我也找到了实现此目的的方法:

@POST
@Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
public Response createUser(final User user, @Context UriInfo uriInfo) {
    // persist the user here
    URI uri = uriInfo.getAbsolutePathBuilder().path(user.getId()).build();
    return Response.created(uri).build();
}

答案 1 :(得分:9)

我发现了一些javax.ws.rs.core.UriBuilder方法,这些方法可以解决,如果其他人有这个问题我想分享。它们是:UriBuilder.fromResource(OneUserResource.class)和javax.ws.rs.core.UriBuilder.path(Class)。我在一次性通话中使用了后者:

URI newUserUri = uriInfo.getBaseUriBuilder().path(OneUserResource.class).path("/" + user.getId()).build();
return Response.created(newUserUri).build();

答案 2 :(得分:5)

使用严格的REST概念,您可以将其作为一个根资源

@POST   /users        -> CREATE a single user
@GET    /users        -> READ all users
@PUT    /users        -> UPDATE (REPLACE) all users @@?
@DELETE /users        -> DELETE all users @@?

@POST   /users/{id}   -> CREATE a single user's some other child; @@?
@GET    /users/{id}   -> READ a single user
@PUT    /users/{id}   -> UPDATE a single user
@DELETE /users/{id}   -> DELETE a single user
@Path("/users")
@Stateless
public class UsersResouce {

    // /users
    @POST
    @Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
    public Response createUser(final User user) {
        // persist the user here
        return Response.created("/" + user.getId()).build();
    }

    // /users
    @GET
    @Produces({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
    public Response readUsers() {
        //return all users
    }

    // /users/{id}
    @GET
    @Path("/{user_id: \\d+}")
    @Produces({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
    public Response readUser(
        @PathParam("user_id") final Long userId) {

        final User persisted = userBean.find(userId);

        if (persisted == null) {
            return Response.status(Status.NOT_FOUND).build();
        }

        return Response.ok().entity(persisted).build();
    }

    // /users/{id}
    @Consumes({MediaType.APPLICATION-XML, MediaType.APPLICATION-JSON})
    @PUT
    @Path("/{user_id: \\d+}")
    public Response updateUser(
        @PathParam("user_id") final Long userId,
        final User mergeable) {

        final User persisted = userBean.find(userId);

        if (persisted == null) {
            userBean.persist(mergeable);
        } else {
            persist.setName(mergeable.getName());
            userBean.merge(persisted);
        }

        return Response.status(Status.NO_CONTENT).build();
    }

    // /users/{id}
    @DELETE
    @Path("/{user_id: \\d+}")
    public Response deleteUser(
        @PathParam("user_id") final Long userId) {

        userBean.delete(userId);

        return Response.status(Status.NO_CONTENT).build();
    }

    @EJB
    private UserBean userBean;
}

答案 3 :(得分:0)

从JAX-RS 2.0开始,最正确的方法(据我所知)是使用build方法,如下所示:

    String uri = uriInfo.getBaseUriBuilder()
      .path(ODataV4Endpoint.class)
      .path(ODataV4Endpoint.class, "serviceEndpointJSONCatalog")
      .resolveTemplate("endpointId", endpointId).build().toString();

仅供参考,在这种情况下,我需要调用path两次,一次是在类上的路径注释,第二次是在方法上的注释。我怀疑对该方法的调用会同时实现,但不会。

端点serviceEndpointJSONCatalog上的Path注释声明了一个参数,例如:'endpoint / {endpointId}',因此需要调用resolveTemplate。否则,您将只调用path(Class cl,String方法)。

就我而言,我创建了一个生成器和一种引用方法的符号方式,以便编译器/运行时可以检查它们。