JSR 303中提出了Bean Validation,表示JavaBean的校验,Hibernate Validation是其具体实现,并对其进行了一些扩展,添加了一些实用的自定义校验注解。
? Spring中集成了这些内容,你可以在Spring中以原生的手段来使用校验功能,当然Spring也对其进行了一点简单的扩展,以便其更适用于Java web的开发。
写得有点凌乱,大家自己体会吧
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>xxx</version>
</dependency>
针对form表单提交或者@RequestBody
加了@Validated
方式,
内部可以使用
@ApiModelProperty(value = "用户主键", required = true)
@NotNull(message = "用户主键不能为空", groups = UpdateGroup.class)
@NotBlank(message = "用户名不能为空", groups = UpdateGroup.class)
private String userId;
@ApiModelProperty(value = "用户名", required = true)
@NotNull(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
@NotBlank(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
private String userName;
@NotNull(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
@NotBlank(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty(value = "密码", required = true)
private String password;
@NotNull(message = "性别不能为空", groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty(value = "性别", required = true)
private GenderEnum gender;
其中有很多日常使用的规则注解如@Email
,@Url
等等
还有下面列举的一些常规的检查
这边也可以组合hibernate-validator
校验注解
注意如果想使用嵌套对象需要使用@Valid注解可以进行嵌套校验
比如我很多时候新增和修改的DTO
只是存在主键或者其他的一些少量字段差异而已,但是自己又不想去CV
。
首先swagger可以使用来忽略api文档的显示
@ApiOperationSupport(ignoreParameters = "xxx")
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
/**
* Specify one or more validation groups to apply to the validation step
* kicked off by this annotation.
* <p>JSR-303 defines validation groups as custom annotations which an application declares
* for the sole purpose of using them as type-safe group arguments, as implemented in
* {@link org.springframework.validation.beanvalidation.SpringValidatorAdapter}.
* <p>Other {@link org.springframework.validation.SmartValidator} implementations may
* support class arguments in other ways as well.
*/
Class<?>[] value() default {};
}
从源码可以知道@Validated
支持组,那么我们就得去创建组比如我创建了
AddGroup
public interface AddGroup {}
// 第二种写法
public interface AddGroup extends Default {}
理论的东西或者跟深层次的东西可以看源码。
核心这些是通过BeanPostProcesso
r后置处理器实现的
这个可以定义注解生效的顺序
@Target({ TYPE })
@Retention(RUNTIME)
@Documented
public @interface GroupSequence {
Class<?>[] value();
}
@GroupSequence({UpdateGroup.class, UpdateExpensiveGroup.class})
public interface ComplexUpdateGroup {}
这边可以定义分组顺序,上述先进行UpdateGroup
,再去进行UpdateExpensiveGroup
实现自定义的校验器
public class ValidUserConstraintValidator implements ConstraintValidator<ValidUser, UserDTO> {
@Autowired
private UserService userService;
@Override
public boolean isValid(UserDTO userDTO, ConstraintValidatorContext context) {
String validResult = this.userService.valid(userDTO);
if (StringUtils.isBlank(validResult)) {
return true;
}
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(validResult).addConstraintViolation();
return false;
}
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
@Constraint(validatedBy = ValidUserConstraintValidator.class)
public @interface ValidUser {
String message() default "用户已存在";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Data
@ApiModel("用户请求对象")
@ValidUser(groups = {AddGroup.class, UpdateGroup.class})
public class UserDTO implements Serializable {
private static final long serialVersionUID = 6715147416524554153L;
@ApiModelProperty(value = "用户主键", required = true)
@NotNull(message = "用户主键不能为空", groups = UpdateGroup.class)
@NotBlank(message = "用户名不能为空", groups = UpdateGroup.class)
private String userId;
@ApiModelProperty(value = "用户名", required = true)
@NotNull(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
@NotBlank(message = "用户名不能为空", groups = {AddGroup.class, UpdateGroup.class})
private String userName;
@NotNull(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
@NotBlank(message = "密码不能为空", groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty(value = "密码", required = true)
private String password;
@NotNull(message = "性别不能为空", groups = {AddGroup.class, UpdateGroup.class})
@ApiModelProperty(value = "性别", required = true)
private GenderEnum gender;
public static User of(UserDTO userDTO) {
return UserMapper.MAPPER.from(userDTO);
}
@Mapper
interface UserMapper {
UserMapper MAPPER = Mappers.getMapper(UserMapper.class);
/**
* DTO转DO
*
* @param userDTO DTO
* @return DO
*/
User from(UserDTO userDTO);
}
}
https://gitee.com/youxiaxiaomage/java-practices/tree/master/yxxmg-mybatis-plus-sample#mapstruct%E7%AE%80%E5%8C%96%E9%A2%86%E5%9F%9F%E5%AF%B9%E8%B1%A1dtodovo%E4%B9%8B%E9%97%B4%E7%9A%84%E8%BD%AC%E6%8D%A2