数据校验是很重要的,数据不正确程序都跑不起来
数据校验分为前端和后端的数据校验,前端数据校验主要是判空校验,作用明显但是在数据逻辑处理上真正的用处并不大
数据校验在后端程序中在Service 结构层中完成(精简Controller层);其实大部分的业务逻辑都在Service 中完成
后端数据校验:
主要是使用在javaBean 和Controller 中
一.JSR303
JSR303 :是Java为bean 数据合法性校验所提供的一个标准规范,叫做: Bean Validation;是一个运行时的数据校验框架,在验证之后错误的信息会被马上返回
JSR303 定义了一套可以标注在成员变量,属性方法上的校验注解
例如:
@Entity
public class User {
@NotNull(message = "用户名不能为空")
private String name;
@NotBlank(message = "年龄不能为空")
@Range(min = 0, max = 120, message = "年龄只能从0-120岁")
private String age;
@Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", message = "出生日期格式不正确")
private String birthday;
}
@NutNull:
@NotBlank:
二 .Hibernate Validator
使用时需要添加的依赖:hibernate-validator
是JSR303 的一个实现,支持所有的标准校验注解,同时还有一些拓展注解
例如:
@Email :验证是否是合法的邮件地址
@ReditCardNumber: 验证是否是合法的信息用卡号码
@Range(min,max,message):验证书信之是否在合适的范围内
...
实践
- 使用在Entity 中,在数据与数据库操作之前(Service 层中进行校验)
以用户注册操作为例:
相关类: user Model (属性上有相关的校验注解)ValiidationResult(封装结果) ValidatorImp(创建校验器validator),封装的异常类:将校验的异常信息封装在异常中向外抛出
1. ValidationResult:
public class ValidationResult {
//校验结果 true false
private boolean hasError=false;
//存放错误信息
private Map<String,String> errorMsgMap = new HashMap<>();
public boolean isHasError() {
return hasError;
}
public void setHasError(boolean hasError) {
this.hasError = hasError;
}
public Map<String, String> getErrorMsgMap() {
return errorMsgMap;
}
public void setErrorMsgMap(Map<String, String> errorMsg) {
this.errorMsgMap = errorMsg;
}
/**
* 实现通用的方法:格式化错误信息
* 校验model 的时候,出错的有可能不止一个字段,所以可能会有很多的错误
* 要将这些错误拼接为一个字符串
*/
public String getErrorMsg(){
return StringUtils.join(errorMsgMap.values(),',');
}
}
2. ValidatorImp
@Component
public class ValidatorImp implements InitializingBean{
//要包装出一个 Validator
private Validator validator;//javax 接口定义的validator 的一个工具;对象:javax.Validation 一个工具(校验器)
//实现校验方法并返回校验结果
public ValidationResult validator(Object bean){
ValidationResult validationResult = new ValidationResult();
//传入要校验的Object,如果校验出现错误 那么相关的信就会保存在set 中
Set<ConstraintViolation<Object>> constraintViolationSet = validator.validate(bean);
if(constraintViolationSet.size()>0){ //有错误
validationResult.setHasError(true);
//遍历set 中的错误信息保存到 ValidationResult 的Map 中
constraintViolationSet.forEach( n->{ //jdk 特有的lamp 表达式
String errorMsg = n.getMessage(); //获取错误信息
String propertyName = n.getPropertyPath().toString();// 获取错误的字段
validationResult.getErrorMsgMap().put(propertyName,errorMsg);
});
}
return validationResult;
}
//程序启动,springbean 初始化完成之后会回调 ValidatorImplement 的afterPropertoesSet 这个方法
@Override
public void afterPropertiesSet() throws Exception {
//通过工厂方法将hibernate validator 实例化(校验器)
this.validator = Validation.buildDefaultValidatorFactory().getValidator();
}
}
3. 使用
public void redisterUser(UserModel userModel) throws BusinessException {
//数据校验
// if(userModel.getUname()==null||userModel.getPassword()==null){
// throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR.setErrorMsg("传入的参数不合法"));
// }
ValidationResult result = validatorImp.validator(userModel);
if(result.isHasError()){
throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,result.getErrorMsg());//将校验错误的信息封装到异常中抛出
}
//model - entity
User user = convertFromUserModel(userModel);
//入库
userRepository.save(user);
}
- 在Controller 校验前端传入的参数(使用较少)
注:在类或者方法上添加注解@Validted,在获取参数前面添加校验注解
@Controller
@RequestMapping("/user")
@Validated
public class UserController {
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public String getUser(
/** 如果只有少数参数,直接把参数写到Controller层,然后在Controller层进行验证就可以了 */
@Min(value = 1, message = "id最小只能1")
@Max(value = 99, message = "id最大只能99")
@RequestParam(name = "userid", required = true) Integer userid) {
return userid+"";
}
}