ตัวอย่างการเขียน Spring-boot Reactive Manual Validation
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>build-info</id>
<goals>
<goal>build-info</goal>
</goals>
<configuration>
<additionalProperties>
<java.version>${java.version}</java.version>
</additionalProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
spring-boot-starter-validation
เป็น Dependency สำหรับการทำ Validation (ตั้งแต่ Spring-boot 2.3 RELEASE เป็นต้นไป มีการตัด Validationjavax.validation.*
ออก ต้อง Add Dependencies เข้าไปเอง อ้างอิงจาก Spring Boot 2.3 Release Notes)com.google.guava
เป็น Dependency Utilities Codes ของ Google ชื่อ Guava
@SpringBootApplication
public class AppStarter {
public static void main(String[] args) {
SpringApplication.run(AppStarter.class, args);
}
}
@Data
public class LoginRequest {
@NotBlank(message = "Required")
@Length(max = 50, message = "More than {max} characters")
private String username;
@NotBlank(message = "Required")
@Length(min = 8, max = 50, message = "Must between {min} to {max} characters")
private String password;
}
- @NotBlank คือ ห้ามเป็น null หรือ ค่าว่าง
- @Length คือ ต้องมีขนาดตามที่ระบุ
อ่านเพิ่มเติม : https://beanvalidation.org/
public interface ManualValidator {
void validate(final Object object);
void validate(final Object object, final List<Class<?>> groupClasses);
}
@Slf4j
@Component
@RequiredArgsConstructor
public class ManualValidatorImpl implements ManualValidator {
private final Validator validator;
public void validate(final Object object) {
validate(object, null);
}
public void validate(final Object object, final List<Class<?>> groupClasses) {
final BindingResult bindingResult = new BindException(object, "");
final WebExchangeBindException e = new WebExchangeBindException(fakeMethodParameter(), bindingResult);
final List<Class<?>> classes = new ArrayList<>();
if (groupClasses != null) {
classes.addAll(groupClasses);
}
classes.add(Default.class);
ValidationUtils.invokeValidator(validator, object, e, classes);
if (e.hasErrors()) {
throw e;
}
}
private MethodParameter fakeMethodParameter(){
try {
final Method method = getClass().getDeclaredMethod("fakeMethodParameter");
return new MethodParameter(method, -1);
} catch (final Exception e) {
log.warn("fakeMethodParameter error => ", e);
return null;
}
}
}
@Slf4j
@RestController
@RequiredArgsConstructor
public class LoginController {
private final ManualValidator manualValidator;
@PostMapping("/login")
public void login(@RequestBody LoginRequest req) {
manualValidator.validate(req);
log.debug("username => {}", req.getUsername());
log.debug("password => {}", req.getPassword());
}
}
เหมือนหัวข้อ spring-boot-reactive-validation
cd ไปที่ root ของ project จากนั้น
$ mvn clean package
$ mvn spring-boot:run
เปิด browser แล้วเข้า http://localhost:8080
POST : http://localhost:8080/login
ได้ผลลัพธ์
{
"error": "invalid_request",
"error_status": 400,
"error_description": "Validate fail",
"error_at": "2020-09-13T11:08:16.465196",
"error_trace_id": "D68354E5",
"error_uri": "https://developer.pamarin.com/document/error/",
"error_on": "0",
"error_fields": [
{
"name": "username",
"code": "not_blank",
"description": "Required"
},
{
"name": "password",
"code": "not_blank",
"description": "Required"
}
],
"error_data": {},
"state": null
}