REST添加子资源

时间:2015-01-23 10:34:23

标签: java rest jax-rs resteasy

学习REST我偶然发现了子资源,我做了一些实验,但都没有成功。这是代码,我正在使用RESTeasy 3.0.9。

@Path(value="/user")
public interface UsersHttp {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public User[] getUsers();

    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User getUser(@PathParam("id") Long id);
    ...
}

此接口由此会话bean实现:

@Stateless
public class UsersHttpImpl implements UsersHttp {

    @Inject
    private UserPersistence persist;
    @Inject
    private MediaUtils mediaUtils;

    @Override
    public User[] getUsers() {
        return persist.getUsers(null);
    }

    @Override
    public User getUser(Long id) {
        return persist.getUser(id);
    }
    ...
}

这是User类的片段:

@SuppressWarnings("serial")
@Entity
@Table(name = "usr_user")
@XmlRootElement
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "usr_id")
    private Long id;

    @Column(name = "usr_name", nullable = false)
    private String name;

    ...

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Path("/name")
    public String getName() {
        return name;
    }
    ...
}

我可以User成功获得MyApplication/user/1,但当GET MyApplication/user/1/name javax.ws.rs.NotFoundException时,我得到Alice,我期待{{1}相反。我错过了什么?

1 个答案:

答案 0 :(得分:1)

您没有任何映射到请求URI中的name部分的内容。 @Path不会那样工作(把它放在模型类中)。

如果您只想过滤名称,我建议使用查询参数或矩阵参数(请参阅更多here)。根据提供的参数,您可以创建部分表示。一篇好文章可以阅读here。一个简单的例子可能是

// ...users/1234?filter=name,age

@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public UserDTO getUser(@PathParam("id") Long id,
                       @QueryParam("filter") String filter) {
    User user = service.findUserById(id);
    String[] include = filter.split(",");
    UserDTO dto = new UserDTO();
    for (String s: include) {
        // set dto fields based on the filter
        // example in psuedo code
        if (s equals name)
            dto.setName(user.getName());
    }
    return dto;
}

根据编组提供程序的不同,您可能需要配置一些设置以忽略空字段。

尽管如此,这可能不是您的主要问题/担忧。如果您只是想要掌握子资源,那么您有点不对劲。在JAX-RS的上下文中,这不是获取资源的一部分的方法"。

基本上,子资源/子资源方法是使用@Path注释的任何方法。该类是根资源,任何 注释@Path的方法都是可以在根资源上执行的操作。任何使用@Path注释的方法都是根资源的子资源。在你的情况下,user(我会让users)是一个"收集资源"并且在方法上使用" @Path(" {id}")`,表示您想要子资源,这是一个单独的用户。

然后是子资源定位器的概念,它的工作方式略有不同。这里我们说可以通过root-resource类找到另一个资源类,比如

@Path("/users")
public class UserResource {
    @GET
    @Path("{id}/friends")
    public FriendsResource getFriendsResource(@PathParam("id") lond id) {
        User user = service.getUserById(id);
        return new FriendsResource(user);
    }
}

public class FriendsResource {
    User user;

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

    @GET
    public List<Friend> getAllFriends() {
        return user.getFriends();
    }
}

以上操作会导致URI ...users/1234/friends转到FriendsResource类,并调用getAllFriends()

这几乎是JAX-RS背景下子资源的要点。