如何处理JAX-RS中的多个子资源?

时间:2016-04-21 16:01:33

标签: java rest jax-rs cdi

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

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

我将如何实现这一目标?我试图寻找一个例子,但只能找到非常基本的。

我已经实施了几种方法,但他们都感觉到了#34;错。

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

另一个是制作所有资源@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;

    (...)
}

1 个答案:

答案 0 :(得分:0)

也许有点晚了,但仍然很难找到答案。

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

所以你的

public class PostsResource() {

变为

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