# Spring 表单验证

## Spring 表单验证在 Spring MVC 中，表单验证是通过一系列的注解来完成的。

### `@NotNull`

- **作用**：确保字段值不为空。
- **用法**：用于字段、方法参数或返回值上，表示该字段不能为空。如果字段为空，将验证失败并返回相应的错误信息。
- 示例

```java
@NotNull(message = "用户名不能为空")
private String username;
```

### `@NotEmpty`

- **作用**：确保字段不为空，并且不为一个空字符串。
- **用法**：用于字符串、集合等类型，验证字段不仅不能为空，而且不能为空字符串。
- 示例

```java
@NotEmpty(message = "密码不能为空")
private String password;
```

### `@NotBlank`

- **作用**：确保字段不为空，并且不为一个空白字符串（即非空白字符）。
- **用法**：类似于 `@NotEmpty`，但除了不为空，还要求去除空白字符后不能为零长度。
- 示例

```java
@NotBlank(message = "电子邮件不能为空")
private String email;
```

### `@Size(min, max)`

- **作用**：验证字段的大小，适用于字符串、集合、数组等类型。
- **用法**：可以设置最小值和最大值来限制字段的长度或集合的大小。
- 示例

```java
@Size(min = 6, max = 20, message = "密码长度必须在6到20之间")
private String password;
```

### `@Email`

- **作用**：验证字段是否符合有效的电子邮件格式。
- **用法**：用于验证字符串字段是否为有效的电子邮件地址格式。
- 示例

```java
@Email(message = "请输入有效的电子邮件地址")
private String email;
```

### `@Pattern(regexp)`

- **作用**：根据正则表达式验证字段值。
- **用法**：可以根据自定义的正则表达式来验证字段的内容。
- 示例

```java
@Pattern(regexp = "^\\d{10}$", message = "请输入有效的手机号码")
private String phoneNumber;
```

### `@Min(value)` **和** `@Max(value)`

- **作用**：确保数字类型字段的值在指定范围内。
- **用法**：`@Min` 用于验证值是否大于等于指定的最小值，`@Max` 用于验证值是否小于等于指定的最大值。
- 示例

```java
@Min(value = 18, message = "年龄不能小于18岁")
@Max(value = 100, message = "年龄不能大于100岁")
private int age;
```

### `@DecimalMin(value)` **和** `@DecimalMax(value)`

- **作用**：用于验证浮动值是否在指定范围内，类似于 `@Min` 和 `@Max`，但适用于 `BigDecimal` 或 `Double` 类型的数值。
- **用法**：`@DecimalMin` 验证值是否大于等于指定的最小值，`@DecimalMax` 验证值是否小于等于指定的最大值。
- 示例

```java
@DecimalMin(value = "0.0", inclusive = true, message = "价格不能小于0")
private BigDecimal price;
```

### `@Future`

- **作用**：验证日期字段的值是否为将来日期。
- **用法**：用于 `java.util.Date`、`java.time.LocalDate` 或 `java.time.LocalDateTime` 等日期类型的字段。
- 示例

```java
@Future(message = "日期必须是未来的时间")
private LocalDate eventDate;
```

### `@Past`

- **作用**：验证日期字段的值是否为过去的日期。
- **用法**：类似于 `@Future`，但是验证日期必须是过去的时间。
- 示例

```java
@Past(message = "出生日期必须是过去的时间")
private LocalDate birthDate;
```

### `@AssertTrue`

- **作用**：验证字段值是否为 `true`。
- **用法**：适用于布尔类型字段，如果值不是 `true`，则验证失败。
- 示例

```java
@AssertTrue(message = "必须接受条款和条件")
private boolean acceptedTerms;
```

### `@AssertFalse`

- **作用**：验证字段值是否为 `false`。
- **用法**：适用于布尔类型字段，如果值不是 `false`，则验证失败。
- 示例

```java
@AssertFalse(message = "不能接受条款")
private boolean declinedTerms;
```

### `@Valid` **和** `@Validated`

- **作用**：触发嵌套对象的验证。
- **用法**：当你有嵌套对象（如表单中的对象属性是另一个对象），使用 `@Valid` 或 `@Validated` 注解来递归验证该对象。
- 示例

```java
@Valid
private Address address;
```

### `@Digits(integer, fraction)`

- **作用**：验证数字字段的有效性，确保字段值是一个有效的数字，并且整数部分和小数部分的位数符合指定要求。
- **用法**：`integer` 参数用于指定数字的整数部分的最大位数，`fraction` 参数用于指定小数部分的最大位数。
- 示例

```java
@Digits(integer = 5, fraction = 2, message = "金额应为最大5位整数和2位小数")
private BigDecimal amount;
```

- 这个例子验证金额字段的最大值为 `99999.99`（即最多5位整数和2位小数）。

### `@CreditCardNumber`

- **作用**：验证信用卡号的有效性，确保其符合信用卡的常见格式，通常包括 Luhn 算法的验证。
- **用法**：该注解用于验证信用卡号的格式是否有效。
- 示例

```java
@CreditCardNumber(message = "请输入有效的信用卡号")
private String creditCardNumber;
```

- 该注解会根据常见的信用卡规则（如 VISA、MasterCard 等）验证输入的信用卡号是否合法。

### `@Range(min, max)`（不是 Spring 内置的，但通常来自 Hibernate Validator）

- **作用**：验证字段值是否在指定的范围内。常用于 `Integer`、`Long`、`Double` 等数值类型的字段。
- **用法**：指定字段的有效范围，当值不在范围内时会验证失败。
- 示例

```java
@Range(min = 1, max = 100, message = "数字必须在1到100之间")
private int quantity;
```

- 该注解会验证 `quantity` 字段的值是否在 `1` 到 `100` 之间。

### `@URL`

- **作用**：验证字段是否为有效的 URL 格式。
- **用法**：用于字符串类型的字段，验证其是否符合有效的 URL 格式。
- 示例

```java
@URL(message = "请输入有效的网址")
private String website;
```

### `@Valid` **与** `@Validated`

- **作用**：用于嵌套对象的验证，确保嵌套对象的字段也进行验证。
- **用法**：这两个注解会触发嵌套对象的验证，通常用于嵌套的复杂表单数据结构。
- 示例

```java
@Valid
private Address address;
```

- 如果 `Address` 类中有字段使用了验证注解，`@Valid` 会递归地验证 `Address` 对象的所有字段。

### `@FutureOrPresent`

- **作用**：验证日期或时间字段的值是否是当前日期（包括今天）或未来的日期。
- **用法**：该注解用于日期和时间字段，确保其为今天或将来的日期。
- 示例：

```java
@FutureOrPresent(message = "事件日期必须是今天或将来")
private LocalDate eventDate;
```

### `@PastOrPresent`

- **作用**：验证日期或时间字段的值是否是当前日期（包括今天）或过去的日期。
- **用法**：与 `@FutureOrPresent` 相反，确保字段是过去或今天的日期。
- 示

```java
@PastOrPresent(message = "出生日期必须是过去的时间或今天")
private LocalDate birthDate;
```

### `@Null`

- **作用**：验证字段是否为 `null`。如果字段不为空，则验证失败。
- **用法**：该注解可以用于字段或方法参数上，确保字段值必须为 `null`。
- 示例

```java
@Null(message = "该字段必须为null")
private String nickname;
```

### `@ScriptAssert(lang, script)`

- **作用**：通过自定义脚本验证字段值。
- **用法**：允许使用自定义脚本（如 JavaScript）来执行复杂的验证逻辑。需要指定脚本语言和脚本内容。
- 示例

```java
@ScriptAssert(lang = "javascript", script = "_this.password == _this.confirmPassword", message = "密码和确认密码必须一致")
private String password;
private String confirmPassword;
```

- 这个注解可以用于检查两个字段值是否一致。

### `@UniqueElements`（Hibernate Validator 扩展）

- **作用**：确保集合中的元素是唯一的，常用于 List 或 Set 类型字段。
- **用法**：适用于集合类型字段，确保集合中的元素不重复。
- 示例

```java
@UniqueElements(message = "列表中的元素必须唯一")
private List<String> tags;
```
