参数验证详解
# 参数验证
在Web应用开发中,参数验证是保证数据合法性的重要手段。Spring Boot 提供了 @Validated
注解来简化数据校验,结合若依框架中的全局异常处理,可以实现优雅的参数验证机制。本文将详细介绍如何在若依框架中使用参数验证注解,并扩展介绍自定义注解和分组校验的应用。
# 一、Spring Boot 参数验证注解详解
Spring Boot 提供了多种内置的注解,用于在字段级别或方法级别对数据进行验证。以下是常用的参数验证注解:
注解名称 | 功能 |
---|---|
@Xss | 检查该字段是否存在跨站脚本工具 |
@Null | 检查该字段是否为空 |
@NotNull | 不能为null |
@NotBlank | 不能为空,常用于检查空字符串 |
@NotEmpty | 不能为空,多用于检测List是否size为0 |
@Max | 该字段的值只能小于或等于该值 |
@Min | 该字段的值只能大于或等于该值 |
@Past | 检查该字段的日期是否在过去 |
@Future | 检查该字段的日期是否是属于将来的日期 |
@Email | 检查是否是一个有效的Email地址 |
@Pattern | 被注释的元素必须符合指定的正则表达式 |
@Range | 被注释的元素必须在指定的范围内 |
@Size | 检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等 |
@Length | 检查所属字段的长度是否在min和max之间, 仅用于字符串 |
@AssertTrue | 用于boolean字段,该字段只能为true |
@AssertFalse | 该字段的值只能为false |
# 二、基本使用
Spring Boot 默认引入了基础的验证包,因此可以直接在控制器中使用 @Validated
注解对请求参数进行验证。
# 1. 在 Controller 中使用 @Validated
在控制器的方法上使用 @Validated
注解,可以对传入的实体对象进行验证。如果验证失败,框架会自动抛出异常,并交由全局异常处理器处理。
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 新增用户
*
* @param user 用户信息
* @return 操作结果
*/
@PostMapping("/add")
public AjaxResult add(@Validated @RequestBody SysUser user)
{
// 业务逻辑
return AjaxResult.success("用户新增成功");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2. 在实体类字段上使用验证注解
在实体类的字段上,可以使用各种验证注解来约束数据的合法性。如果数据不符合验证要求,则会返回对应的错误信息。
public class SysUser {
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
private String userName;
@Email(message = "邮箱格式不正确")
@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
private String email;
@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
private String phonenumber;
// Getters and Setters
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
提示:验证注解可以放在字段上,也可以放在字段的
getter
方法上。一般推荐放在字段上,简洁明了。
# 三、自定义注解校验
除了Spring Boot 提供的内置注解外,开发者还可以根据业务需求自定义注解,实现特定的校验逻辑。以下是自定义 @Xss
注解的示例。
# 1. 定义 @Xss
注解
首先,定义一个自定义注解 @Xss
,并指定校验器为 XssValidator
。
package com.ruoyi.common.annotation;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义XSS校验注解
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Constraint(validatedBy = { XssValidator.class })
public @interface Xss
{
String message() default "不允许任何脚本运行";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 2. 实现 XssValidator
校验器
接下来,实现 XssValidator
校验器,定义具体的校验逻辑。例如,检查字符串中是否包含HTML标签。
package com.ruoyi.common.validator;
import com.ruoyi.common.annotation.Xss;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 自定义XSS校验注解实现
*
* @author ruoyi
*/
public class XssValidator implements ConstraintValidator<Xss, String>
{
private final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
@Override
public boolean isValid(String value, ConstraintValidatorContext context)
{
return !containsHtml(value); // 验证内容是否包含HTML标签
}
private boolean containsHtml(String value)
{
if (value == null) {
return false;
}
Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value);
return matcher.matches();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3. 使用自定义注解
最后,可以在实体类的字段上使用自定义注解 @Xss
进行XSS校验。
public class SysUser {
@Xss(message = "登录账号不能包含脚本字符")
@NotBlank(message = "登录账号不能为空")
@Size(min = 0, max = 30, message = "登录账号长度不能超过30个字符")
private String loginName;
// Getters and Setters
}
2
3
4
5
6
7
8
9
# 四、自定义分组校验
在实际开发中,可能会遇到不同场景下需要对同一实体类的不同字段进行不同的验证。例如,在新增操作时某些字段为必填,但在更新操作时可能不再强制要求。这时可以使用 groups
属性来实现分组校验。
# 1. 定义分组接口
首先,定义两个接口 Add
和 Edit
,分别用于标识新增和编辑操作。
public interface Add {}
public interface Edit {}
2
3
# 2. 在 Controller 中使用分组
在控制器方法中,使用 @Validated
注解指定具体的验证分组。
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 新增用户
*
* @param user 用户信息
* @return 操作结果
*/
@PostMapping("/add")
public AjaxResult add(@Validated(Add.class) @RequestBody SysUser user)
{
// 业务逻辑
return AjaxResult.success("用户新增成功");
}
/**
* 编辑用户
*
* @param user 用户信息
* @return 操作结果
*/
@PostMapping("/edit")
public AjaxResult edit(@Validated(Edit.class) @RequestBody SysUser user)
{
// 业务逻辑
return AjaxResult.success("用户编辑成功");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 3. 在实体类字段上使用分组
在实体类的字段上,通过 groups
属性指定不同的验证分组。
public class SysUser {
// 仅在新增时验证
@NotNull(message = "用户ID不能为空", groups = {Add.class})
private Long userId;
// 在新增和修改时验证
@NotBlank(message = "用户账号不能为空", groups = {Add.class, Edit.class})
private String userName;
// 仅在修改时验证
@NotNull(message = "修改时手机号码不能为空", groups = {Edit.class})
private String phonenumber;
// Getters and Setters
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 五、总结
通过合理使用Spring Boot的参数验证机制,可以极大地提高代码的健壮性和可维护性。在若依框架中,结合全局异常处理和自定义注解,能够实现灵活且强大的数据校验。
基础验证: 使用Spring Boot自带的注解对常见的字段验证进行处理,如空值、范围、格式等。
自定义验证: 可以通过自定义注解和校验器实现更复杂的业务逻辑验证。
分组校验: 通过分组校验可以在不同的业务场景下对同一实体类进行不同的验证,提升代码的灵活性。