【问题标题】:Spring boot with Jersey - Filter request body properties带有 Jersey 的 Spring Boot - 过滤请求正文属性
【发布时间】:2019-05-28 10:51:00
【问题描述】:

我想知道是否有某种方法可以过滤资源接收到的对象的属性。

让我解释一下:假设我们有这个对象:

用户DTO

public final class IniciativaDocument {
    private String id;
    private String name;
    private String surname;
    private String address;
    private Double balance;
}

对于一个资源,我只需要属性“name”和“surname”,但对于其他资源,我只需要“address”和“id”。有什么方法可以让不需要的变量像 Jackson 这样的变量自动为空?

我的目标是,如果客户端发送的请求包含不需要的字段,我不必在将其保存到数据库之前将其设为 null,因为在注册时不应该初始化该字段。

谢谢。

编辑 1

为了更清楚:这是为了安全和方便。

假设我是一名黑客,并且不知何故知道DTO 类具有的字段。我可以轻松地将这样的POST 请求发送到注册用户的服务:

{
   "id": "wrong",
   "name": "Wrong",
   "balance": 20000
}

对于我的服务,我只需要 idname 但黑客也发送了 balance 字段。

我想要做的是,当我收到这个对象时,我可以设置我的端点/api/v1/users(用于注册)将任何不是idname 的初始化字段放入null .

您可能会说我可以确保它为 0 或手动将其设置为 null。是的,确实如此,但我想知道是否有一种自动且更舒适的方式来使用注释或类似的东西。

编辑 2

资源示例:

@Component
@Path("iniciativas")
@Produces(MediaType.APPLICATION_JSON)
public final class IniciativasEndpoint {
    @POST
    public Response crearIniciativa(@Valid @NotNull(message = CONSTRAINT_BODY_NOT_NULL) @ConvertGroup(to = IniciativasGroup.Create.class)
                                        final IniciativaDTO iniciativaDTO,
                                    @Context UriInfo uriInfo) {

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

【问题讨论】:

    标签: java spring spring-boot jersey


    【解决方案1】:

    您可以使用Jackson's JsonIgnore Property 来表示:

    @JsonInclude(Include.NON_NULL)
    public final class IniciativaDocument {
        private String id;
        private String name;
        private String surname;
        private String address;
    }
    

    所以基本上它的作用是,当它将此类映射到Json 时,它将忽略所有具有null 值的字段。如果你不希望它适用于整个班级,你也可以在字段上这样做。

    如果你想通过front-end 实现它,那么你可以使用这个很棒的apiGraphQL,所以基本上在请求中你会指定你需要的字段,它只会返回那些字段。

    【讨论】:

    • 我不希望它忽略空字段。我希望可以这样说“对于 /api/v1/users 的服务,我只需要字段 'name' 和 'surname',如果有任何其他字段具有值,请将它们设置为 null”
    • 如果没有找到这些字段的值,它会自动将它们设置为空,例如,当您发送一个帖子请求时,只有姓名和姓氏,其他字段默认为空
    • 我不是这个意思。我进行了编辑以试图澄清我的问题。
    【解决方案2】:

    使用后匹配过滤器: 您可以实现 ContainerRequestFilter 并使用 @PostMaching (javax.ws.rs.container.PreMatching) 注释您的过滤器,并在其中使用其数据处理您的请求。

    为你的过滤器定义一个@interface:

    @NameBinding
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD })
    public @interface AnnotationForYourFilter {}
    

    使用@AnnotationForYourFilter 注释您想要的子资源,您就完成了。

    【讨论】:

    • 我似乎无法弄清楚如何让它以这种方式工作。请举个简单的例子好吗?
    • 我明天会这样做,因为现在是当地时间 17:00,我下班了。
    • 您还需要帮助吗?
    • 好的。让我知道你有什么资源和端点(子资源)
    • 在您的crearIniciativa 子资源中,您等待一个IniciativaDocument-object 并且您不需要控制 (id, name, surname, @ 的值987654329@, balance) 但在另一个子资源中(你没有显示)你在等待......什么?
    猜你喜欢
    • 1970-01-01
    • 2022-01-12
    • 2017-11-08
    • 2023-03-14
    • 1970-01-01
    • 2021-04-19
    • 2018-07-18
    • 2017-10-02
    • 2020-10-18
    相关资源
    最近更新 更多