gpt4 book ai didi

java - Spring WebFlux过滤器在请求对象反序列化后拦截请求

转载 作者:太空宇宙 更新时间:2023-11-04 09:07:09 26 4
gpt4 key购买 nike

我有一个响应式(Reactive) WebFlux Spring Boot 应用程序(版本 2.2.3.RELEASE)。我定义了一个名为 SearchRequest 的 POJO,它在带注释的 Controller 中用于 GET 和 POST 请求:

@GetMapping(path = "/search")
Mono<ItemCollection> getItems(SearchRequest searchRequest);

@PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE)
Mono<ItemCollection> getItemsPost(@RequestBody SearchRequest searchRequest);

需要完成一些基本验证,以及一些可能的转换。 SearchRequest 中的某些字段本身就是对象,例如:

public class SearchRequest {

private Fields fields;
...
}

其中 Fields 类如下所示:

public class Fields {

private Set<String> include;
private Set<String> exclude;
...
}

对于 HTTP POST 请求,用户只需提交遵循此结构的 JSON 对象即可。对于 HTTP GET 请求,我正在使用的 API 规范允许您简单地提供一个 fields URL 参数,其中包含以“+”或“-”为前缀的字段名称数组。我创建了一个扩展 PropertyEditorSupport 的类来解析 URL 参数并填充 Fields 对象的包含和排除集。这是在我的 Controller 中使用 @InitBinder 配置的:

@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Fields.class, "fields", fieldsPropertyEditor);
}

我的 SearchRequest 对象支持使用 bbox 值或 intersects 值进行地理空间查询,但是如果指定了两者,我需要返回 400。我已尝试以下方法来实现此验证,但找不到我正在寻找的解决方案:

  1. 使用 WebDataBinder 注册另一个自定义编辑器不指定字段的 SearchRequest 类。
  2. 使用 WebDataBinder 注册 validator (均使用 setValidatoraddValidators 方法)。
  3. 实现WebFilter

解决方案1似乎没有效果。编辑从来没有被叫过。在解决方案 2 中,每个请求都会调用 supports 方法,但从不调用 validate 方法。解决方案 3 可以工作,但需要我编写两组逻辑 - 一组用于 GET,一组用于 POST,因为 GET URL 参数与 POST 请求正文分开存储。此外,为了实际检查请求正文,exchange.getRequest.getBody() 返回一个 DataBuffer,可用于将正文反序列化为对象,但如果没有前面提到的属性编辑器(对于 GET 请求),我无法直接反序列化为 SearchRequest

我真的希望找到某种过滤器/转换器/转换器,我可以在将请求反序列化为 SearchRequest 对象之后、但在调用 Controller 处理程序方法之前调用它们,但我似乎找不到一种方法来做到这一点。

有人可以建议这是否可行,或者我唯一的选择是在 WebFilter 中单独处理 GET/POST 请求吗?

最佳答案

这不是我正在寻找的答案,但它似乎至少目前有效。基本上,我只是制作了一个自定义 validator ,并使用 @Valid 在 Controller 方法中注释了我的 SearchRequest 参数。

注释:

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = SingleGeometryValidator.class)
@Documented
public @interface SingleGeometry {
String message () default "Request should not contain both `intersects` and `bbox`. Please choose one geometry to "
+ "search by.";
Class<?>[] groups () default {};
Class<? extends Payload>[] payload () default {};
}

validator :

public class SingleGeometryValidator implements ConstraintValidator<SingleGeometry, SearchRequest> {

@Override
public boolean isValid(SearchRequest searchRequest, ConstraintValidatorContext constraintValidatorContext) {
return !(searchRequest.getBbox() != null && searchRequest.getIntersects() != null);
}
}

请求对象:

@Data
@SingleGeometry
public class SearchRequest {
...
}

Controller 接口(interface):

@GetMapping(path = "/search")
Mono<ItemCollection> getItems(@Valid SearchRequest searchRequest);

@PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE)
Mono<ItemCollection> getItemsPost(@Valid @RequestBody SearchRequest searchRequest);

关于java - Spring WebFlux过滤器在请求对象反序列化后拦截请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60083599/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com