簡體   English   中英

如何驗證 Spring Boot Rest 響應?

[英]How to validate Spring Boot Rest response?

我用 Spring Boot Rest 實現了控制器:

@RestController
@RequestMapping("/example")
public class ExampleController {

    @Autowired
    private ExampleService exampleService;

    @GetMapping("/{id}")
    public ExampleResponse getExample(@NotNull @PathVariable("id") String id) {
        return exampleService.getExample(id);
    }
}

並回應 DTO:

public class ExampleResponse {

    @NotNull
    private String id;

    @NotNull
    private String otherStuff;

    // setters and getters
}

響應正文未經驗證。 我已經用@Valid注釋了它,但null值仍然通過。 請求驗證效果很好。

如何驗證響應體?

已實現的響應驗證器:

@Aspect
@Component
public class ControllerResponseValidator {

    Logger logger = Logger.getLogger(ControllerResponseValidator.class);

    @Autowired
    private Validator validator;

    @AfterReturning(pointcut = "execution(* com.example.controller.*.*(..))", returning = "result")
    public void validateResponse(JoinPoint joinPoint, Object result) {
        validateResponse(result);
    }

    private void validateResponse(Object object) {

        Set<ConstraintViolation<Object>> validationResults = validator.validate(object);

        if (validationResults.size() > 0) {

            StringBuffer sb = new StringBuffer();

            for (ConstraintViolation<Object> error : validationResults) {
                sb.append(error.getPropertyPath()).append(" - ").append(error.getMessage()).append("\n");
            }

            String msg = sb.toString();
            logger.error(msg);
            throw new RestException(HttpStatus.INTERNAL_SERVER_ERROR, msg);
        }
    }
}

在 Rest Controller 上使用@Validated在必須驗證返回對象的方法上使用@Valid 例如:

休息控制器:

@RestController
@RequestMapping("/tasks")
@Validated
public class TaskController {

    @GetMapping("/{taskId}")
    @Valid
    public TaskDTO getTask(@PathVariable UUID taskId) {
        return convertToDto(taskService.findById(taskId));
    }  

}

DTO類:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ValidTaskDTO
public class TaskDTO {

    @FutureOrPresent
    @NotNull
    private ZonedDateTime dueDate;

    @NotBlank(message = "Title cannot be null or blank")
    private String title;

    private String description;

    @NotNull
    private RecurrenceType recurrenceType;

    @Future
    @NotNull
    private ZonedDateTime repeatUntil;

}

我的返回對象TaskDTO有 null dueDaterepeatUntil 所以錯誤信息將如下所示:

{
  "timestamp": "2021-01-20T11:09:37.303929",
  "status": 400,
  "error": "Bad Request",
  "message": "getTask.<return value>.dueDate: must not be null, getTask.<return value>.repeatUntil: must not be null",
  "path": null
}

我希望這有幫助。 有關自定義類級別約束的詳細信息,請觀看此視頻

您不應該將其注釋為以下代碼段嗎?

 public @ResponseBody ExampleResponse getExample(@NotNull @PathVariable("id") String id) {
        return exampleService.getExample(id);
    }

您可以添加“@Validated @ResponseBody”注釋

public @Validated @ResponseBody getExample(@NotNull @PathVariable("id") String id) {

你期望發生什么? 我認為您應該考慮幾件事。

  1. 如果對象確實不能具有值為null字段,則應在將對象保存到您的存儲庫(無論您喜歡哪種類型)時驗證這一點。 然后如果你的服務返回了一些東西,你就知道它已經有效了,如果它什么都不返回; 您可以為客戶端返回正確的狀態代碼和消息(4xx/5xx)。 您還可以將特定異常映射到某種類型的status code這樣您就可以從代碼中拋出異常,並讓它們由 spring-boot 中的默認異常處理程序捕獲和處理

  2. 如果您的字段可以為null ,但您想在序列化中省略它們,則可以使用jackson annotations @JsonInclude(JsonInclude.Include.NON_NULL)只會序列化響應中的非空值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM