Spring MVC 整合 JSR-303 Bean Validation,讓驗證邏輯以註解形式宣告於領域模型,Controller 僅需加上 @Valid 即可自動觸發驗證。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
注意:validation-api 只定義介面,必須搭配實作(如 hibernate-validator),否則啟動會報錯。
| 註解 | 說明 |
|---|---|
@NotNull | 值不能為 null |
@NotEmpty | 字串/集合/陣列長度 > 0 |
@Size(min, max) | 長度範圍 |
@Pattern(regexp) | 符合正則表達式 |
@Email | Email 格式(Hibernate Validator 擴充) |
@Digits(integer, fraction) | 數字位數限制 |
@Past / @Future | 日期必須在過去/未來 |
public class User implements Serializable {
@Size(min = 1, max = 32, message = "帳號長度應在 1-32 字元")
private String username;
@NotEmpty(message = "密碼不得為空")
private String password;
@NotEmpty(message = "Email 不得為空")
@Email(message = "Email 格式錯誤")
private String email;
@Size(min = 11, max = 11, message = "手機號碼必須 11 碼")
private String cellphone;
// getter/setter 省略
}
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired private UserService userService;
@PostMapping("/register")
public String register(@Valid User user, Errors errors) {
if (errors.hasErrors()) {
return "register"; // 返回表單頁,錯誤訊息自動綁定
}
// 业务逻辑...
return "redirect:/user/" + user.getUsername();
}
}
<%@ taglib prefix="sf" uri="https://www.springframework.org/tags/form" %>
<sf:form method="POST" commandName="user">
<!-- 顯示所有欄位錯誤 -->
<sf:errors path="*" element="div" cssClass="errors" />
<table>
<tr><td>帳號:</td><td><sf:input path="username" cssErrorClass="errors" /></td></tr>
<tr><td>密碼:</td><td><sf:password path="password" cssErrorClass="errors" /></td></tr>
<tr><td>Email:</td><td><sf:input path="email" cssErrorClass="errors" /></td></tr>
<tr><td>手機:</td><td><sf:input path="cellphone" cssErrorClass="errors" /></td></tr>
</table>
<input type="submit" value="註冊" />
</sf:form>
Spring MVC 透過 MultipartResolver 支援檔案上傳,建議使用 Servlet 3.0+ 容器原生支援(StandardServletMultipartResolver)。
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
// 單檔 2MB,總請求 4MB,暫存目錄 /tmp/uploads
registration.setMultipartConfig(
new MultipartConfigElement("/tmp/uploads", 2_097_152, 4_194_304, 0)
);
}
}
@Bean
public MultipartResolver multipartResolver() throws IOException {
return new StandardServletMultipartResolver();
}
@PostMapping("/{username}/avatar")
public String uploadAvatar(@PathVariable String username,
@RequestPart("icon") MultipartFile icon) throws IOException {
// 建議使用唯一檔名避免衝突
String destPath = "/var/www/uploads/" + username + "_" + System.currentTimeMillis() + ".jpg";
icon.transferTo(new File(destPath));
return "userProfile";
}
<form method="post" enctype="multipart/form-data">
<label>上傳頭像:</label>
<input type="file" name="icon" accept="image/jpeg, image/png" />
<button type="submit">上傳</button>
</form>
List<MultipartFile> 或 MultipartFile[],前端 name 相同且加上 multiple 屬性。icon.getContentType()、icon.getSize(),或自訂 Validator 註解(如 @ValidFile)搭配 @Valid 使用。enctype 遺漏、或檔案大小超過 MultipartConfig 限制。hibernate-validator 依賴存在、@Valid 正確標註、Errors/BindingResult 緊跟在 @Valid 參數之後。server.xml 的 Connector 加 URIEncoding="UTF-8";或使用 UUID 重命名檔案。