【问题标题】:REST add subresourcesREST 添加子资源
【发布时间】:2015-01-23 10:34:22
【问题描述】:

学习 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 类的sn-p:

@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;
    }
    ...
}

我可以通过MyApplication/user/1 成功获得User,但是当我使用MyApplication/user/1/name 获得GET 时,我获得了javax.ws.rs.NotFoundException,我期待的是Alice。我错过了什么?

【问题讨论】:

  • 您无法通过这种方式访问​​对象属性。实际上,没有与此 URI 关联的资源:@​​987654331@。您必须为MyApplication/user/{id}/name 创建另一个资源入口点并返回字符串。
  • 您是否有在线资源可以引用您所说的“子资源”?可能是您偶然发现了一个简单易用的特定功能,而不是通用 JAX-RS API 功能。

标签: java rest jax-rs resteasy


【解决方案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 上下文中子资源的要点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 2019-12-29
    • 1970-01-01
    相关资源
    最近更新 更多