【问题标题】:How to deal with multiple sub resources in JAX-RS?如何处理 JAX-RS 中的多个子资源?
【发布时间】:2016-04-21 16:01:32
【问题描述】:

我有一个带有多个子资源的 JAX-RS REST API,例如

users/{user_id}/posts/{post_id}/comments/{comment_id}。资源被划分为单独的类(UsersResourceUserResourcePostsResource 等)并通过子资源定位器访问。每个资源都使用关联服务(UserServicePostServiceCommentService)来访问数据库。

我将如何实现这一点?我试图搜索一个示例,但只能找到非常基本的示例。

我已经实现了几种方法,但它们都“感觉”错了。

一个是在根资源中注入所有服务并传递它们。但是实例化所有服务似乎很浪费,尽管可能只需要第一个。

另一个是使所有资源@RequestScoped 并注入后续资源,以便可以在正确的位置注入正确的服务。但是我需要提前注入子资源,即使我不需要它也无法传递参数。

我目前的方法无法将服务注入我的子资源中。 (见下文)

root resource (resources/users)

@RequestScoped
@Path("users")
public class UsersResource() {

    @Inject
    private UserService service;

    @Path("{user_id}")
    public UserResource getUserResource(@Context ResourceContext context, @PathParam("user_id") Long id) {
        User entity = this.service.find(id);

        if (entity == null)
            throw new WebApplicationException(Response.status(Status.NOT_FOUND).build());

        return context.initResource(new UserResource(entity, this.service));
    }
}

user sub resource (resources/users/{user_id})

public class UserResource() {

    private User entity;
    private UserService service;

    public UserResource(User entity, UserService service) {
        this.entity = entity;
        this.service = service;
    }

    @GET
    public Response doGet() {
        return Response.ok(entity).build();
    }

    @Path("posts")
    public TodosResource getPostsResource(@Context ResourceContext context) {
        return context.initResource(new PostsResource(entity));
    }
}

posts sub resource (resources/users/{user_id}/posts)

public class PostsResource() {

    @Inject // can't inject here
    private PostService service;

    private User user;

    public PostsResource(User user) {
        this.user = user;
    }

    @POST
    public Response doPost(@Context UriInfo info, Post post) {
        post.setUser(this.user);
        Post entity = this.service.persist(post);
        URI uri = info.getAbsolutePathBuilder().path("/" + entity.getId()).build();

        return Response.created(uri).entity(entity).build();
    }

    @Path("{post_id}")
    public PostResource getpostResource(@Context ResourceContext context, @PathParam("post_id") Long id) {
        Post entity = this.service.find(id);

        if (entity == null)
            throw new WebApplicationException(Response.status(Status.NOT_FOUND).build());

        return context.initResource(new PostResource(entity));
    }

服务示例

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    (...)
}

【问题讨论】:

  • 看看您的设置方式,我不禁觉得您的设置本身过于复杂。我会在 UsersResource 级别创建一个整体的“API”资源,并在该级别注入所有服务,然后在该级别映射子资源的内容。
  • 我的原因是我不想实例化它们,如果我不需要的话。即使请求是针对根本身的,根资源也必须为每个可能的服务创建一个实例。
  • 在一个资源中使用多个服务背后的想法并不是你现在就需要它们,但你肯定会在未来某个时候需要它们,所以让它们准备就绪当他们需要的时候。您的服务器将为所有用户运行您的 UsersResource 的单个实例,但目前,您建议在每次调用的基础上提供短暂的 UserResource 和 PostResource,一旦它们完成,这将超出范围,这比保留单个资源的成本要高得多。

标签: java rest jax-rs cdi


【解决方案1】:

也许有点晚了,但这个问题的答案仍然很难找到。

要直接在子资源中注入 EJB,请使用 @Provider 注释子资源,附加 @Produces 也是一个好主意。

所以你的

public class PostsResource() {

变成

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class PostsResource() {

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多