Spring MVC 數據綁定後,必須驗證合法性。本文以 Hibernate Validator (JSR-303/349/380 參考實現) 為例,從依賴引入、Validator Bean 配置、模型註解驗證、Controller @Valid + BindingResult、國際化訊息配置、JSP 表單錯誤顯示 六大步驟,提供可直接運行的完整範例。
<dependencies>
<!-- JSR-380 API -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
</dependency>
<!-- Hibernate Validator 實現 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.2.5.Final</version>
</dependency>
<!-- 表達式語言 (EL) 依賴,支援訊息插值 -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<!-- spring-mvc.xml -->
<mvc:annotation-driven validator="validator" conversion-service="conversionService"/>
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/validation"/>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="120"/>
</bean>
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
public class UserForm {
@NotBlank(message = "{user.name.notblank}")
@Size(min = 2, max = 20, message = "{user.name.size}")
private String name;
@Min(value = 0, message = "{user.age.min}")
@Max(value = 150, message = "{user.age.max}")
private Integer age;
@NotBlank(message = "{user.email.notblank}")
@Email(message = "{user.email.invalid}")
private String email;
// getter/setter 省略
}
user.name.notblank=姓名不能為空 user.name.size=姓名長度需在 2-20 字符之間 user.age.min=年齡不能小於 0 user.age.max=年齡不能大於 150 user.email.notblank=電子郵件不能為空 user.email.invalid=電子郵件格式不正確
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/register")
public String showForm(Model model) {
model.addAttribute("userForm", new UserForm());
return "register";
}
@PostMapping("/register")
public String register(@Valid @ModelAttribute("userForm") UserForm form,
BindingResult result, Model model) {
// 有錯誤回表單頁,錯誤訊息自動綁定到 result
if (result.hasErrors()) {
return "register";
}
// 業務邏輯...
return "redirect:/user/success";
}
}
<%@ taglib prefix="form" uri="https://www.springframework.org/tags/form" %> <form:form modelAttribute="userForm" method="post"> <!-- 全局錯誤 --> <form:errors path="*" cssClass="error-block" /><br/> 姓名: <form:input path="name" /> <form:errors path="name" cssClass="error-inline" /><br/> 年齡: <form:input path="age" /> <form:errors path="age" cssClass="error-inline" /><br/> 郵箱: <form:input path="email" /> <form:errors path="email" cssClass="error-inline" /><br/> <input type="submit" value="註冊" /> </form:form>
| 註解 | 適用類型 | 說明 |
|---|---|---|
| @NotNull | 任意 | 不為 null |
| @NotBlank | CharSequence | 不為 null、去空白後長度 > 0 |
| @NotEmpty | Collection/Map/Array/CharSequence | 不為 null、size/length > 0 |
| @Size(min, max) | Collection/Map/Array/CharSequence | 長度/大小範圍 |
| @Min/@Max | 數值/CharSequence | 數值下限/上限 |
| @DecimalMin/@DecimalMax | BigDecimal/String | 精確小數範圍 |
| CharSequence | Email 格式 (正則) | |
| @Pattern(regexp) | CharSequence | 自訂正則 |
| @Past/@Future | Date/Calendar/LocalDate | 過去/未來日期 |
| @Valid | 巢狀物件 | 遞歸驗證子物件 |
@NotNull(groups = UpdateGroup.class),Controller @Validated(UpdateGroup.class)。ConstraintValidator,註解標註 @Constraint(validatedBy = ...)。@Validated,參數加 @NotNull 等,AOP 攔截驗證。Spring MVC + Hibernate Validator 以「註解聲明規則、@Valid 觸發驗證、BindingResult 收集錯誤、MessageSource 國際化訊息、form:errors 顯示」標準流程,實現聲明式數據驗證。**新專案請直接使用 Jakarta Bean Validation 3.0 (Hibernate Validator 8.x) + Spring Boot 3.x**,配置更簡潔 (@EnableValidation 自動裝配)。