Method 1: Use hibernate-validator annotation method parameter verification
There are too many similar frameworks. Disadvantages: The order of the returned prompt information is not very certain.
Documentation: https://hibernate.org/validator/documentation/
Reference: https://blog.csdn.net/weixin_45080272/article/details/128413908
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
① Add parameter verification annotations on the fields of the entity class, such as @Max, @Min, @NotNull and other verification rules
/**
* 模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省
*/
@ApiModelProperty(value = "模板类型:1-同城寄,2-省内寄,3-经济区互寄,4-跨省", required = true)
@Max(value = 4, message = "类型值必须是1、2、3、4")
@Min(value = 1, message = "类型值必须是1、2、3、4")
@NotNull(message = "模板类型不能为空")
private Integer templateType;
② Add the @@Validated annotation to the corresponding controller class to indicate that parameter verification is enabled.
@Slf4j
@Validated // 开启参数校验
@RestController
@Api(tags = "运费管理")
@RequestMapping("/carriages")
public class CarriageController {
......
}
For form and url parameter verification, add verification rules on the controller method input parameters:
Common verification annotations:
- @Null The annotated element must be null
- @NotNull The annotated element must not be null
- @AssertTrue the annotated element must be true
- @AssertFalse The annotated element must be false
- @Min(value) The annotated element must be a number, and its value must be greater than or equal to the specified minimum value
- @Max(value) The annotated element must be a number, and its value must be less than or equal to the specified maximum value
- @DecimalMin(value) The annotated element must be a number, and its value must be greater than or equal to the specified minimum value
- @DecimalMax(value) The annotated element must be a number, and its value must be less than or equal to the specified maximum value
- @Size(max=, min=) The size of the annotated element must be within the specified range
- @Digits (integer, fraction) The annotated element must be a number and its value must be within the acceptable range
- @Past The annotated element must be a past date
- @Future annotated element must be a future date
- @Pattern(regex=,flag=) The annotated element must conform to the specified regular expression
- Validation annotations provided by Hibernate Validator:
- @NotBlank(message =) Verify that the string is not null and the length must be greater than 0
- @Email The annotated element must be an email address
- @Length(min=,max=) The size of the annotated string must be within the specified range
- @NotEmpty The annotated string must be non-empty
- @Range(min=,max=,message=) The annotated element must be within the appropriate range
Verification within the entity class of the controller method parameters: (You need to add the @Valid annotation in front of the method parameters so that the field verification rules in the entity class can take effect)
@PostMapping
public CarriageDTO saveOrUpdate(@Valid @RequestBody CarriageDTO carriageDto) {
return carriageService.saveOrUpdate(carriageDto);
}
But this operation is too coupled, and annotations must be added to the formal parameter object every time it is used.
Supplement: Use AOP aspect method to perform parameter verification on the request body object when the method enters parameters.
/**
* 请求参数校验切面,统一对Controller中@RequestBody映射的对象进行校验,在Controller方法中无需单独处理
*/
@Aspect // 声明当前类为切面
@Slf4j
@EnableAspectJAutoProxy // 开启AOP注解功能
@Component
public class ValidatedAspect {
@Resource
private Validator validator; //javax提供的参数校验
/**
* 定义切面---在controller方法入参时对请求体对象进行参数校验(校验规则在实体类中)
*
* @param proceedingJoinPoint 切入点对象
* @return
* @throws Throwable
*/
// @Around: 环绕通知,可以在目标方法执行前后进行一些处理,方法参数与原方法一致, 返回值类型与原方法返回值类型一致
// 切点表达式: "execution(* com.sl..controller.*Controller.*(..))",匹配所有controller方法
@Around("execution(* com.sl..controller.*Controller.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 获取@RequestBody映射的对象:请求体对象
Object body = AspectUtil.getBody(proceedingJoinPoint);
// 不为空的body进行拦截校验
if (!ObjectUtil.isEmpty(body)) {
// 进行校验
// validator.validate(body):验证实体对象中的所有约束,他把校验失败的字段信息封装成一个Set集合返回
Set<ConstraintViolation<Object>> validateResult = validator.validate(body);
if (CollUtil.isNotEmpty(validateResult)) {
//如果校验结果不为空,表示没有通过校验,则抛出异常,由统一异常处理机制进行处理,响应400
String info = JSONUtil.toJsonStr(validateResult.stream()
.map(ConstraintViolation::getMessage).collect(Collectors.toList()));
throw new SLException(info, HttpStatus.BAD_REQUEST.value());
}
}
//校验通过,执行原方法:roceedingJoinPoint.proceed(传原方法的入参)
return proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
}
}
/**
* 切面工具类
*
* @author 白豆五
* @date 2023/09/04
* @since JDK8
*/
@Slf4j
public class AspectUtil {
/**
* 获取被拦截方法对象
* @param pjp {@link ProceedingJoinPoint}
* @return {@link Method}
*/
public static Method getMethod(ProceedingJoinPoint pjp) {
//获取参数的类型
Signature sig = pjp.getSignature();
if (sig instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) sig;
return methodSignature.getMethod();
} else {
throw new IllegalArgumentException("It's not method");
}
}
/**
* 解析SPEL表达式
*
* @param key key
* @param method {@link Method}
* @param args {@code Object[]}
* @return key
*/
public static String parse(String key, Method method, Object[] args) {
if (StringUtils.isNotBlank(key) && key.indexOf("#") > -1) {
Pattern pattern = Pattern.compile("(\\#\\{([^\\}]*)\\})");
Matcher matcher = pattern.matcher(key);
List<String> keys = new ArrayList<>();
while (matcher.find()) {
keys.add(matcher.group());
}
if (!CollectionUtils.isEmpty(keys)) {
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
for (String tmp : keys) {
key = key.replace(tmp, parser.parseExpression("#" + tmp.substring(2, tmp.length() - 1)).getValue(context, String.class));
}
return key;
}
}
return key;
}
/**
* 获取请求体
*
* @param pjp {@link ProceedingJoinPoint}
* @return {@code Object}
*/
public static Object getBody(ProceedingJoinPoint pjp) {
Object[] args = pjp.getArgs();
Method method = getMethod(pjp);
if (ObjectUtil.isNotEmpty(args)) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int count = 0; count < parameterAnnotations.length; count++) {
for (Annotation annotation : parameterAnnotations[count]) {
if (annotation instanceof RequestBody) {
return args[count];
}
}
}
}
return null;
}
}
Method 2: Use if statements in the program to verify parameters
The crudest way.
public boolean updateStatus(List<String> ids) {
if(CollUtil.isEmpty(ids)){
return false;
}
}