自定义注解参数校验
2020-11-18 本文已影响0人
帮我的鸵鸟盖个章
使用自定义注解校验参数,能使我们更加专注业务本身,而不用去写大量重复的校验,代码也更加简洁。
先自定义注解,并自定义校验实现
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.x.enums.CheckType;
/**
* 常用校验 枚举
*/
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = Check.CheckValidator.class)// 注意这里,指出了自定义的校验方法
public @interface Check {
String message() default ""; // 自定义异常返回信息
CheckType type(); // 自定义校验字段
Class<?>[] groups() default {};
Class<? extends javax.validation.Payload>[] payload() default {};
/**
* 校验实现
* 实现ConstraintValidator接口,这是个泛型接口,泛型中第一个是自定义的注解,第二个是注解使用的类型。
* 这里就是我们调用的字段校验方法
*/
class CheckValidator implements ConstraintValidator<Check,Object>{
private CheckType type;
@Override
public void initialize(Check constraintAnnotation) {
this.type=constraintAnnotation.type();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return CheckType.validate(type,value);
}
}
}
定义枚举,主要是不同字段+不同的验证规则。并实现真正的校验
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
* 常用校验类型
*/
public enum CheckType {
/**
* 手机号验证枚举
*/
MOBILE("Mobile", "手机", "^1[0-9]{10}$"),
SHOT_DATE("Date", "短日期格式", "yyyyMMdd"),
TOOLOOG_DATE("Date", "短日期格式", "yyyyMMddHHmmssSSS"),
DATE("Date", "常用时间格式", "yyyy-MM-dd HH:mm:ss"),
/**
* 请求流水号验证枚举
*/
REQUEST_NO("RequestNo", "请求流水号", "^[0-9a-zA-Z]{32}");
public String value;
public String label;
public String regular;
private CheckType(String value, String label, String regular) {
this.value = value;
this.label = label;
this.regular = regular;
}
public static CheckType with(String value) {
for (CheckType type : CheckType.values()) {
if (type.value.equalsIgnoreCase(value)) {
return type;
}
}
return null;
}
/**
* 校验方法
* 验证传入的枚举值,是否符合规则
* @param type
* @return true:验证成功;false:验证失败
*/
public static boolean validate(CheckType type, Object obj) {
if (null == obj || null == type) {
//空不校验
return true;
}
if (!(obj instanceof String)) {
//不是String 返回false
return false;
}
String str = obj.toString();
if (StringUtils.isEmpty(str)) {
//空字符串不校验
return true;
}
//日期格式不适用正则
if ("Date".equals(type.value)) {
SimpleDateFormat sdf = new SimpleDateFormat(type.regular);
try {
sdf.parse(str);
} catch (Exception e) {
return false;
}
return true;
}
//使用正则校验
return Pattern.matches(type.regular, str);
}
}
定义一个dto,对里面的字段使用自己的注解
package com.mayn.external.dto;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
import com.x.annotation.Check;
import com.x.enums.CheckType;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class UserDto implements Serializable{
/**
* 32位流水号
*/
@Check(type=CheckType.REQUEST_NO,message="请求流水号格式错误")
private String requestNo;
@Check(type=CheckType.TOOLOOG_DATE,message="时间戳格式不正确,格式:yyyyMMddHHmmssSSS")
@NotBlank(message="时间戳不能为空")
private String timestamp;
}
controller测试
@RestController
@RequestMapping("/valid")
public class TestValidController {
@PostMapping("/login")
public Object test(@RequestBody @Valid UserDto user) {
return request.toString();
}
}
@Valid
注解会对UserDto
中加了Check
的字段进行校验。