Рубрики
Без рубрики

Проверьте Свои Конечные Точки С Помощью Spring

Что Мы Хотим Сделать? 🤔 Примените проверку к объектам, которые мы получаем в конечной точке… С тегом web dev, java, учебное пособие, программирование.

Что Мы Хотим Сделать? 🤔

Примените проверку к объектам, которые мы получаем на контроллерах конечных точек от клиентов.

Какое Первое Решение Приходит На Ум? 🧠

это просто, верно? напишите функции, которые проверяют эти объекты.

Допустим, у нас есть конечная точка для добавления новых отправлений. 🚚

Давайте начнем с классов DTO (Объект передачи данных)

@RequiredArgsConstructor @Getter  
public class ShipmentComponentDTO {  
    private final String productCode;  
}
@RequiredArgsConstructor @Getter  
public class ShipmentDTO {  
    private final String productCode;  
    private final int count;  
    private final List shipmentComponentDTOs;  
}

Сейчас, контроллер

@RestController  
public class ShipmentController {  
    @PostMapping("/shipment/add")  
    public ResponseEntity addShipment(@RequestBody ShipmentDTO shipmentDTO){  
        if (shipmentDTO.getProductCode() == null)  
            return ResponseEntity.badRequest().body("Product code can't be null");  

        if (shipmentDTO.getCount() <= 0)  
            return ResponseEntity.badRequest().body("Count can't be negative or zero");  

        if (!allComponentsAreValid(shipmentDTO))  
            return ResponseEntity.badRequest().body("Component product code can't be null");  

        return ResponseEntity.ok(":)");  
    }  

    private boolean allComponentsAreValid(ShipmentDTO shipmentDTO) {  
        List shipmentComponentDTOs = shipmentDTO.getShipmentComponentDTOs();  

        return shipmentComponentDTOs != null &&  
                shipmentComponentDTOs.size() > 0 &&  
                shipmentComponentDTOs.  
                stream().  
                allMatch(shipmentComponentDTO -> shipmentComponentDTO.getProductCode() != null);  
    }  
}

Обратите внимание на всю ту утомительную ручную работу, которую нам приходилось выполнять. 🤕

Неужели никто не может помочь нам сделать эту задачу более увлекательной? 😏

Пожалуйста, познакомьтесь с валидатором Javax. 🥳

  • Он предоставляет набор аннотаций, которые используются с полями класса.
  • Они действуют как ограничения.
    • это поле не должно быть пустым
    • этот список должен иметь минимальный размер 5
    • и многое другое…

Как это сделать? 👀

Для объекта, который мы хотим проверить

  • Мы аннотируем поля, которые хотим проверить, аннотациями из javax.validation.constraints
  • Затем мы аннотируем параметр контроллера, который мы хотим проверить.

  • Затем мы должны перехватить ошибку, выданную валидатором, и вернуть правильный ответ пользователю.

Давайте закодируем это 🦾

Вот объекты DTO

@RequiredArgsConstructor @Getter  
public class ShipmentComponentDTO {  
    @NotBlank(message = "Component product code can't be null")  
    private final String productCode;  
    // required by the javax validation code  
  public ShipmentComponentDTO() {  
        this.productCode = "";  
    }  
}
@RequiredArgsConstructor @Getter  
public class ShipmentDTO {  
    @NotBlank(message = "Product code can't be null")  
    private final String productCode;  
    @Min(1)  
    private final int count;  

    @Size(min = 1, message = "Component product code can't be empty")  
    @NotNull(message = "Component product code can't be null")  
    @Valid  
  private final List shipmentComponentDTOs;  
}

Хорошо, что это были за аннотации? 👇

  • Не чистый
    • Это поле не может быть нулевым или пустым строка
  • Минута
    • это целое число должно иметь минимальное значение мы уточняем
  • Размер
    • размер этого массива должен быть в пределах границ мы уточняем
  • не полный
    • Это поле не должно быть пустым
  • Действительный
    • Проверьте поля в этом объекте

Итак, вот контроллер 👇

@RestController  
public class ShipmentController_Validation {  
    @PostMapping("validation/shipment/add")  
    public ResponseEntity addShipment(@RequestBody @Validated ShipmentDTO shipmentDTO){  
        return ResponseEntity.ok(":)");  
    }  
}

Что это была за аннотация @Validated? 🤨

  • он сообщает Spring запустить механизм проверки для этого объекта в соответствии с его аннотациями проверки (Не пустыми и т.д.)

Наконец, давайте перехватим исключение, выданное валидатором, и сгенерируем правильный ответ

@Order(Ordered.HIGHEST_PRECEDENCE)  
@ControllerAdvice  
public class ValidationAdvice{  
    @ResponseStatus(BAD_REQUEST)  
    @ResponseBody  
 @ExceptionHandler(MethodArgumentNotValidException.class)  
    public ResponseEntity methodArgumentNotValidException(MethodArgumentNotValidException ex) {  
        BindingResult result = ex.getBindingResult();  
        List fieldErrors = result.getFieldErrors();  
        String errorMessage = fieldErrors.get(0).getDefaultMessage();  
        return ResponseEntity.badRequest().body(errorMessage);  
    }  
}

В заключение ✍️

  • Представьте, что у вас есть API со множеством конечных точек, которые нам нужно проверить. Какой метод был бы лучше?
  • Валидатор.

Код на GitHub

Оригинал: “https://dev.to/jarjanazy/validate-your-endpoints-using-spring-4l3e”