新泽西州。在REST请求的响应中隐藏一些POJO字段的好方法

时间:2017-10-31 18:46:00

标签: java rest jersey

我们假设以下示例。 POJO课程:

@XmlRootElement 
public class User {
    private String id; 
    private String email;
    private String password;
    private String firstName;
    private String lastName;

   // getters and setters
}

资源类:

@Path("user")
public class UserResource {
    private UserRepository userRepository = new UserRepositoryStub();

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
    public User createUser(User user) {            
        return userRepository.create(user);
    }

    @GET
    @Path("{objectId}")
    @Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
    public Response getManagedObject(@PathParam("objectId") String objectId) {
        if (objectId == null) {
            return Response.status(Response.Status.BAD_REQUEST).build();
        }
        User user = userRepository.findUser(objectId);

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

        // Possible, but seems that not nice solution
        // user.setPassword(null);            

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

在这个简单示例中,我希望GET请求 {url} / user / 12345 不会返回密码字段。我评论过一个我不喜欢的解决方案。

通常,在处理API时,我希望为每个请求配置POJO字段的可见性。是否有一种优雅的方式来实现这一目标?

3 个答案:

答案 0 :(得分:2)

创建一个TransferObject即TO或DTO,其中包含您希望用户在JSON响应中显示的字段。您可以在字段上使用@JsonIgnore,而JSON解析器不会解析该字段,因此不会包含在响应中。

答案 1 :(得分:1)

假设您希望POST方法(取消编组)包含密码 -  但不是GET方法(编组) - 你正在使用JAXB,你可以写一个XmlAdapter

它的引用用于在可映射类和不可映射类之间进行转换,但它可以在这里做到。

class User {

    //...

    @XmlJavaTypeAdapter(PasswordAdapter.class);
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

然后为密码属性指定该适配器:

rlist, *_ = select.select([Server] + open_client_sockets, [],[])

答案 2 :(得分:1)

一般做法是在两者之间设置一个服务层。然后你有一个dto对象,它是外部世界的io对象,转换为你的资源/实体/存储库/任何对象。你需要提供转换/映射器/这两种类型的对象之间的任何东西,并且在进入资源方向时你不需要设置密码。通常对休息接口中的ID进行相同的操作。您不希望任何人更新资源,并通过在输入对象中提供ID来更新其他对象。这就是通常的事情,即使它意味着额外的代码,这通常是微不足道的。可以使用Dozer框架或类似的东西使用配置进行简化。

从设计的角度来看,资源/持久层应该只包含原子操作。如果您需要为单个资源执行其中的几项,会发生什么?您必须将它放在资源类中的单个方法中。这样你就可以将rest / io逻辑与服务层中的内容混合起来。

更容易犯错并且更难编写单独的单元测试