diff --git a/pom.xml b/pom.xml index 53ef577..b5a6160 100644 --- a/pom.xml +++ b/pom.xml @@ -2,10 +2,11 @@ 4.0.0 + org.springframework.boot spring-boot-starter-parent - 2.7.1 + 3.3.5 @@ -15,7 +16,7 @@ spring-validation - 17 + 21 ${java.version} ${java.version} UTF-8 @@ -28,15 +29,11 @@ spring-boot-starter-validation - - io.swagger.core.v3 - swagger-annotations - 2.2.1 - + org.springdoc - springdoc-openapi-ui - 1.6.9 + springdoc-openapi-starter-webmvc-ui + 2.6.0 diff --git a/src/main/java/org/sadtech/example/springvalidation/controller/ErrorHandlingControllerAdvice.java b/src/main/java/org/sadtech/example/springvalidation/controller/ErrorHandlingControllerAdvice.java index 6961524..8cf391b 100644 --- a/src/main/java/org/sadtech/example/springvalidation/controller/ErrorHandlingControllerAdvice.java +++ b/src/main/java/org/sadtech/example/springvalidation/controller/ErrorHandlingControllerAdvice.java @@ -1,5 +1,6 @@ package org.sadtech.example.springvalidation.controller; +import jakarta.validation.ConstraintViolationException; import org.sadtech.example.springvalidation.dto.ValidationErrorResponse; import org.sadtech.example.springvalidation.dto.Violation; import org.springframework.http.HttpStatus; @@ -9,7 +10,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; -import javax.validation.ConstraintViolationException; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/org/sadtech/example/springvalidation/controller/PersonController.java b/src/main/java/org/sadtech/example/springvalidation/controller/PersonController.java index 9fbb042..dadf9c7 100644 --- a/src/main/java/org/sadtech/example/springvalidation/controller/PersonController.java +++ b/src/main/java/org/sadtech/example/springvalidation/controller/PersonController.java @@ -2,7 +2,12 @@ package org.sadtech.example.springvalidation.controller; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.RequiredArgsConstructor; import org.sadtech.example.springvalidation.dto.PersonDto; +import org.sadtech.example.springvalidation.service.PersonService; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -13,16 +18,18 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; +import java.time.LocalDate; +import java.util.List; @Validated @RestController +@RequiredArgsConstructor @RequestMapping("/api/person") @Tag(name = "Пользователи системы", description = "Валидация на уровне контроллера") public class PersonController { + private final PersonService personService; + @PostMapping @Operation(summary = "Сохранение пользователя") public ResponseEntity save(@Valid @RequestBody PersonDto personDto) { @@ -45,4 +52,15 @@ public class PersonController { return ResponseEntity.ok("valid"); } + @GetMapping("birthday") + @Operation(summary = "Получить пользователей в диапазоне ДР") + public ResponseEntity> getByPersonBirthday( + @RequestParam("from") LocalDate from, + @RequestParam("to") LocalDate to + ) { + return ResponseEntity.ok( + personService.getAllByHappyBirthdayBetween(from, to) + ); + } + } diff --git a/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerGroupValid.java b/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerGroupValid.java index 0c7bcd3..eac53fb 100644 --- a/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerGroupValid.java +++ b/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerGroupValid.java @@ -1,6 +1,7 @@ package org.sadtech.example.springvalidation.controller; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import org.sadtech.example.springvalidation.dto.PersonDto; import org.sadtech.example.springvalidation.valid.Marker; import org.springframework.http.ResponseEntity; @@ -11,7 +12,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.validation.Valid; @Validated @RestController diff --git a/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerNoValidation.java b/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerNoValidation.java index 46de153..415ac67 100644 --- a/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerNoValidation.java +++ b/src/main/java/org/sadtech/example/springvalidation/controller/PersonControllerNoValidation.java @@ -12,9 +12,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController +@RequiredArgsConstructor @RequestMapping("/api/no-valid/person") @Tag(name = "Пользователи системы 2", description = "Валидация на уровне сервиса") -@RequiredArgsConstructor public class PersonControllerNoValidation { private final PersonService personService; diff --git a/src/main/java/org/sadtech/example/springvalidation/dto/Address.java b/src/main/java/org/sadtech/example/springvalidation/dto/Address.java new file mode 100644 index 0000000..75f7cca --- /dev/null +++ b/src/main/java/org/sadtech/example/springvalidation/dto/Address.java @@ -0,0 +1,18 @@ +package org.sadtech.example.springvalidation.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class Address { + + @NotBlank + private String state; + + @NotBlank + private String city; + +} diff --git a/src/main/java/org/sadtech/example/springvalidation/dto/PersonDto.java b/src/main/java/org/sadtech/example/springvalidation/dto/PersonDto.java index 5a9d5cd..2ce5c3d 100644 --- a/src/main/java/org/sadtech/example/springvalidation/dto/PersonDto.java +++ b/src/main/java/org/sadtech/example/springvalidation/dto/PersonDto.java @@ -1,23 +1,23 @@ package org.sadtech.example.springvalidation.dto; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import jakarta.validation.constraints.Pattern; import lombok.Getter; import lombok.Setter; import org.sadtech.example.springvalidation.valid.CapitalLetter; import org.sadtech.example.springvalidation.valid.Marker; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Null; -import javax.validation.constraints.Pattern; - @Entity @Getter @Setter @@ -46,4 +46,7 @@ public class PersonDto { ) private String ipAddress; + @Transient + private Address address; + } diff --git a/src/main/java/org/sadtech/example/springvalidation/service/PersonService.java b/src/main/java/org/sadtech/example/springvalidation/service/PersonService.java index 3059daf..d8dc6c4 100644 --- a/src/main/java/org/sadtech/example/springvalidation/service/PersonService.java +++ b/src/main/java/org/sadtech/example/springvalidation/service/PersonService.java @@ -1,10 +1,14 @@ package org.sadtech.example.springvalidation.service; +import jakarta.validation.Valid; import org.sadtech.example.springvalidation.dto.PersonDto; +import org.sadtech.example.springvalidation.valid.LocalDateBetween; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import javax.validation.Valid; +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; @Service @Validated @@ -14,4 +18,10 @@ public class PersonService { // do something } + @LocalDateBetween + public List getAllByHappyBirthdayBetween(LocalDate from, LocalDate to) { + System.out.println("valid"); + return Collections.emptyList(); + } + } diff --git a/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetter.java b/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetter.java index c966cff..501161d 100644 --- a/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetter.java +++ b/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetter.java @@ -1,7 +1,8 @@ package org.sadtech.example.springvalidation.valid; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; diff --git a/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetterValidator.java b/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetterValidator.java index 1ea360d..6fbd28b 100644 --- a/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetterValidator.java +++ b/src/main/java/org/sadtech/example/springvalidation/valid/CapitalLetterValidator.java @@ -1,7 +1,8 @@ package org.sadtech.example.springvalidation.valid; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class CapitalLetterValidator implements ConstraintValidator { diff --git a/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetween.java b/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetween.java new file mode 100644 index 0000000..6577910 --- /dev/null +++ b/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetween.java @@ -0,0 +1,23 @@ +package org.sadtech.example.springvalidation.valid; + +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface LocalDateBetween { + + String message() default "Дата невалидна"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetweenValidator.java b/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetweenValidator.java new file mode 100644 index 0000000..b7b8a6c --- /dev/null +++ b/src/main/java/org/sadtech/example/springvalidation/valid/LocalDateBetweenValidator.java @@ -0,0 +1,28 @@ +package org.sadtech.example.springvalidation.valid; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import jakarta.validation.constraintvalidation.SupportedValidationTarget; +import jakarta.validation.constraintvalidation.ValidationTarget; + +import java.time.LocalDate; + +@SupportedValidationTarget(ValidationTarget.PARAMETERS) +public class LocalDateBetweenValidator implements ConstraintValidator { + + @Override + public boolean isValid(Object[] value, ConstraintValidatorContext context) { + final Object objDateFrom = value[0]; + final Object objDateTo = value[1]; + + if ( + !(objDateFrom instanceof final LocalDate dateFrom) + || !(objDateTo instanceof final LocalDate dateTo) + ) { + throw new IllegalArgumentException("Illegal method signature, expected two parameters of type LocalDate."); + } + + return dateFrom.isAfter(LocalDate.now()) && dateFrom.isBefore(dateTo); + } + +}