如果原始POST有效负载已映射到对象,则它在其余控制器中是否可用?

时间:2019-11-04 15:08:12

标签: rest spring-boot

我有一个POST端点,其中包含一些重要数据的JSON有效负载应通过摘要进行存档。

@RestController
public class SomeController {

  @PostMapping(value = "/api/some")
  public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some) {
    archiveAndDigest(rawJsonPostPayloadSomeHowFromCurrentContext());
    someService(some);
    return new ResponseEntity<ResponseStatus>(
      ResponseStatus.builder()
...
        .build(),
        HttpStatus.CREATED
      );
  }

控制器端点太具有表现力和方便性(确保内容类型,解析并验证输入有效载荷),以至于不能丢弃原始字符串输入,并且需要手工完成所有这些操作。输入的有效负载必须保留用于审核。

1 个答案:

答案 0 :(得分:0)

可以获取原始JSON值而不是反序列化的对象。

我可以想到两种方法。

第一我不推荐

这样,您无法使用Spring Validator中的。

以字符串形式接收JSON,然后使用ObjectMapper将原始值转换为对象。

@RestController
public class SomeController {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(String rawRequest) {
        log.info("Raw value: {}", rawRequest);

        ObjectMapper mapper = new ObjectMapper();
        Some some = mapper.readValue(rawRequest, Some.class);
        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}

第二名我更喜欢

将对象作为对象接收(就像您所做的一样),然后使用ObjectMapper从对象获取JSON原始值

这样,您可以使用Spring Validator。

@RestController
public class SomeController {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some) {
        ObjectMapper mapper = new ObjectMapper();

        String rawJsonValue mapper.writeValueAsString(some);
        log.info("Raw value: {}", rawJsonValue);

        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}

我更喜欢梯子,但是请记住,不会打印对象中不存在的JSON请求中发送的任何属性。发生这种情况是因为mapper.writeValueAsString(some)将基于对象的属性生成JSON。

更新

您可以将HttpServletRequest定义为方法的参数。这样,Spring将提供当前请求并将其传递给参数。

@RestController
public class SomeController {

    @PostMapping(value = "/api/some")
    public ResponseEntity<ResponseStatus> postSome(@Valid @RequestBody Some some, HttpServletRequest request) {
        String rawValue = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));

        System.out.println(rawValue);

        someService(some);

        return new ResponseEntity<ResponseStatus> (ResponseStatus.builder()
        ...
        .build(), HttpStatus.CREATED);
    }
}