คำอธิบายข้อจำกัดแบบกำหนดเอง
สร้างคำอธิบาย @UniqueEmail แบบกำหนดเองพร้อมการใช้งาน ConstraintValidator
คำอธิบายข้อจำกัดแบบกำหนดเอง เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
เมื่อข้อจำกัดมาตรฐานไม่เพียงพอ
คำอธิบายประกอบการตรวจสอบความถูกต้องของบีนมาตรฐานครอบคลุมกรณีทั่วไป หากต้องใช้กฎเฉพาะโดเมน (เช่น อีเมลไม่ซ้ำ IBAN ที่ถูกต้อง หรือความแข็งแกร่งของรหัสผ่าน) ให้สร้างคำอธิบายประกอบข้อจำกัดแบบกำหนดเอง
การกำหนดคำอธิบายประกอบข้อจำกัด
สร้างคำอธิบายประกอบด้วย @Constraint(validatedBy = ...) พร้อมองค์ประกอบ message, groups และ payload ที่จำเป็น รวมถึงกำหนดการคงอยู่และเป้าหมายที่เหมาะสม
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
@Documented
@Constraint(validatedBy = UniqueEmailValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface UniqueEmail {
String message() default "Email already registered";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}การใช้งาน ConstraintValidator
ใช้งาน ConstraintValidator<UniqueEmail, String> เมธอด initialize จะอ่านองค์ประกอบของคำอธิบายประกอบ ส่วน isValid จะดำเนินการตรวจสอบจริง
@Component
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired private UserRepository repo;
@Override
public boolean isValid(String email, ConstraintValidatorContext ctx) {
if (email == null) return true; // let @NotBlank handle null
return !repo.existsByEmail(email);
}
}การใช้ข้อจำกัดแบบกำหนดเอง
ใช้คำอธิบายประกอบนี้เช่นเดียวกับข้อจำกัดมาตรฐานกับฟิลด์ พารามิเตอร์ หรือค่าที่ส่งคืน
public record CreateUserRequest(
@NotBlank
String name,
@NotBlank @Email @UniqueEmail
String email
) {}ข้อความแบบกำหนดเองพร้อมการแทนค่า
อ้างอิงองค์ประกอบของคำอธิบายประกอบในข้อความด้วย {elementName} ใช้ ctx.buildConstraintViolationWithTemplate() เพื่อเพิ่มข้อความแบบกำหนดเองที่มีข้อมูลแบบไดนามิก
@Constraint(validatedBy = RangeValidator.class)
public @interface InRange {
int min() default 0;
int max() default 100;
String message() default "Must be between {min} and {max}";
// ...
}ข้อจำกัดระดับคลาส
ใช้ข้อจำกัดในระดับคลาสเพื่อตรวจสอบหลายฟิลด์ร่วมกัน เหมาะสำหรับกฎข้ามฟิลด์ เช่น การยืนยันรหัสผ่าน
@Documented
@Constraint(validatedBy = PasswordMatchValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PasswordMatch {
String message() default "Passwords do not match";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}การใช้งานตัวตรวจสอบระดับคลาส
ตัวตรวจสอบจะได้รับออบเจ็กต์ทั้งหมด จึงสามารถเข้าถึงหลายฟิลด์เพื่อทำการตรวจสอบข้ามฟิลด์
public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, ChangePasswordRequest> {
public boolean isValid(ChangePasswordRequest req, ConstraintValidatorContext ctx) {
if (req.getNewPassword() == null) return true;
boolean match = req.getNewPassword().equals(req.getConfirmPassword());
if (!match) {
ctx.disableDefaultConstraintViolation();
ctx.buildConstraintViolationWithTemplate("Passwords do not match")
.addPropertyNode("confirmPassword").addConstraintViolation();
}
return match;
}
}การประกอบข้อจำกัด
สร้างข้อจำกัดเมตาโดยใส่คำอธิบายประกอบข้อจำกัดแบบกำหนดเองด้วยข้อจำกัดที่มีอยู่แล้ว ระบบจะใช้ข้อจำกัดทั้งสองรายการโดยอัตโนมัติ
@NotBlank
@Email
@Size(max = 255)
@Constraint(validatedBy = {})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
String message() default "Invalid email";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}การส่งคืนการละเมิดหลายรายการ
ใช้ ctx.disableDefaultConstraintViolation() และเพิ่มข้อความการละเมิดแยกกันสำหรับแต่ละปัญหาที่พบในการตรวจสอบหนึ่งรอบ
public boolean isValid(String password, ConstraintValidatorContext ctx) {
List<String> issues = new ArrayList<>();
if (password.length() < 8) issues.add("Too short");
if (!password.matches(".*\\d.*")) issues.add("Must contain a digit");
if (issues.isEmpty()) return true;
ctx.disableDefaultConstraintViolation();
issues.forEach(msg -> ctx.buildConstraintViolationWithTemplate(msg).addConstraintViolation());
return false;
}ตัวตรวจสอบที่จัดการโดยสปริง
เนื่องจาก UniqueEmailValidator มีคำอธิบายประกอบ @Component สปริงจึงฉีดรีโพซิทอรีเข้าไปได้ แต่จะทำงานได้ก็ต่อเมื่อตัวตรวจสอบเริ่มต้นผ่านตัวตรวจสอบของสปริง ซึ่ง Spring Boot จะเชื่อมต่อให้โดยอัตโนมัติ
การทดสอบตัวตรวจสอบแบบกำหนดเอง
ทดสอบตัวตรวจสอบแบบยูนิตโดยตรงได้ โดยไม่ต้องใช้บริบทของสปริงสำหรับตรรกะการตรวจสอบที่ไม่มีการพึ่งพาภายนอก ใช้ Validation.buildDefaultValidatorFactory() สำหรับการทดสอบการผสานรวม
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
CreateUserRequest req = new CreateUserRequest("", "bad-email", null);
Set<ConstraintViolation<CreateUserRequest>> violations = validator.validate(req);
System.out.println(violations.size()); // 3ตรวจสอบความเข้าใจอย่างรวดเร็ว
ตัวตรวจสอบข้อจำกัดแบบกำหนดเองใช้อินเทอร์เฟซใด
สรุปทบทวน
สร้าง @interface ด้วย @Constraint(validatedBy=...) และใช้งาน ConstraintValidator ใช้ @Component สำหรับการฉีดการพึ่งพาของสปริง ข้อจำกัดระดับคลาสใช้ตรวจสอบหลายฟิลด์ร่วมกัน และสามารถประกอบข้อจำกัดที่มีอยู่แล้วเพื่อหลีกเลี่ยงการทำซ้ำ
คำถามที่พบบ่อย
บทเรียน “คำอธิบายข้อจำกัดแบบกำหนดเอง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คำอธิบายข้อจำกัดแบบกำหนดเอง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คำอธิบายข้อจำกัดแบบกำหนดเอง”
สร้างคำอธิบาย @UniqueEmail แบบกำหนดเองพร้อมการใช้งาน ConstraintValidator คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “คำอธิบายข้อจำกัดแบบกำหนดเอง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การตรวจสอบ Bean: @NotNull, @Size, @Pattern
- คำอธิบายข้อจำกัดแบบกำหนดเอง
- การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice
- รายละเอียดปัญหา RFC 7807 และการตอบกลับข้อผิดพลาดอย่างสอดคล้อง