SpringBoot整合参数校验的两种方式应用实践

背景:SpringBoot秒杀小项目
实现了两种参数校验方式
1.原登录业务逻辑处理使用的正则表达式校验手机号格式输入(未使用Validation参数校验,只是简单实现)
2.更改业务逻辑,实现@IsMobile注解校验手机号,顺便实践一下(自定义@IsMobile注解实现参数校验,具体校验规则中调用了1中Pattern类isMobile方法)

1 What is JSR303校验?

JSR303作为JavaEE 6中的一项子规范,又叫做 Bean Validation

Bean ValidationJavaBean验证定义响应的元数据模型和API。 Java Annotation作为缺省的元数据,通过使用 XML对原有元数据信息进行覆盖、扩展。

实际应用口可以通过 Bean Validation或是自定义的 contraint,例如@ NotNull 、自定义 @IsMobile注解确保数据模型 JavaBean的正确性(接下来会自定义实现 @IsMobile注解,讲述详细实际应用过程)。

由于很多特定需求都需要定制化开发 contraintBean Validation作为一个运行时的数据验证框架,在验证之后验证的错误信息会马上返回。

2 第一种实现参数校验方式

本部分实现方式较简单,自定义了Validator校验工具类,使用Pattern类的compile方法校验手机号格式规则,Matcher类的matches方法返回boolean类型。

ValidatorUtil实现

public class ValidatorUtil {
    //手机号位数校验规则
    private static final Pattern mobile_pattern = Pattern.compile("[1]([3-9])[0-9]{9}$");
    public static boolean isMobile(String mobile){
        //为空直接返回
        if (StringUtils.isEmpty(mobile)){
            return false;
        }
        //根据Pattern.compile的规则校验mobile,返回boolean类型
        Matcher matcher = mobile_pattern.matcher(mobile);
        return matcher.matches();
    }
}

登录业务UserServiceImpl调用ValidatorUtil

public RespBean doLogin(LoginVo loginVo) {
    String mobile = loginVo.getMobile();
    String password = loginVo.getPassword();
    //参数校验,使用springboot-starter-validation JSR303校验
    if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)){
        //在这里调用了枚举类型
        return RespBean.error(RespBeanEnum.LOGIN_ERROR);
    }
    //登录业务逻辑处理
    if (!ValidatorUtil.isMobile(mobile)){
        return RespBean.error(RespBeanEnum.MOBILE_ERROR);
    }
    //获取user
    User user = userMapper.selectById(mobile);
    if (user == null){
        return RespBean.error(RespBeanEnum.LOGIN_ERROR);
    }
    return RespBean.success();

}

LoginController调用UserServiceImpl

public RespBean doLogin(LoginVo loginVo){
    //用来测试用户输入
    //log.info("{}",loginVo);
    return userService.doLogin(loginVo);
}

3 自定义实现@IsMobile自定义校验器

由于作为实践练习,没有做太过复杂的应用场景,只对用户手机号实现了参数校验。

相关代码测试中使用了lombok,也需要引入lombok依赖。


    org.springframework.boot
    spring-boot-starter-validation

    org.projectlombok
    lombok
    true

1.LoginVo用于实现表单输入实体,在需要进行参数校验的实体上添加自定义注解 @IsMobile, @NotNull。在应用中密码采用了md5加密,此处 @Length(min=32).

@Data
public class LoginVo {
    @NotNull()
    //创建的自定义注解
    @IsMobile
    private String mobile;
    @NotNull
    @Length(min=32)
    private String password;
}
  1. @IsMobile自定义注解接口(可以参考@NotNull注解,复制注解接口实现方式)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class})
public @interface IsMobile {
    //加required
    boolean required() default true;
    //
    String message() default "手机号码格式错误";

    Class[] groups() default { };

    Class[] payload() default { };
}
  1. @IsMobile校验规则具体定义IsMobileValidator类实现
public class IsMobileValidator implements ConstraintValidator {
    //
    private boolean required = false;
    @Override
    public void initialize(IsMobile constraintAnnotation) {
        required = constraintAnnotation.required();
    }

    //自定义注解IsMobile的校验规则
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (required){
            return ValidatorUtil.isMobile(value);
        }else {
            if (StringUtils.isEmpty(value)) {
                return true;
            }else {
                return ValidatorUtil.isMobile(value);
            }
        }
    }
}

3.登录业务UserServiceImpl调用ValidatorUtil

public RespBean doLogin(LoginVo loginVo) {
    String mobile = loginVo.getMobile();
    String password = loginVo.getPassword();
    //参数校验,使用springboot-starter-validation JSR303校验
    User user = userMapper.selectById(mobile);
    if (user == null){
        //改造返回值, 异常处理的方式
        //定义完异常之后这样放进去
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
        //return RespBean.error(RespBeanEnum.LOGIN_ERROR);
    }
    //如果用户密码不正确
    if (!MD5Util.formPassToDBPass(password, user.getSalt()).equals(user.getPassword())){
        throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
        //return RespBean.error(RespBeanEnum.LOGIN_ERROR);
    }
    return RespBean.success();
}

4.LoginController调用UserServiceImpl,加入validation校验功能,再次请求时,就会走自定义的 @IsMobile注解规则

@RequestMapping("/doLogin")
@ResponseBody
public RespBean doLogin(@Valid LoginVo loginVo){
    //用来测试用户输入
    //log.info("{}",loginVo);
    //Controller调用service
    return userService.doLogin(loginVo);
}

5.由于在LoginVo的mobile属性中添加了自定义的@IsMobile,在输入手机号不符合规则时会自行判断,不需要在UserServiceimpl中对Mobile进行相关判断,一定程度上也降低了代码冗余,UserServiceimpl只需要对密码进行校验。

4 总结

spring-boot-starter-validation启动器的自动配置类 ValidationAutoConfiguration,本质是注入了一个Validator校验器的实现类

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)

@ConditionalOnMissingBean(Validator.class)

public static LocalValidatorFactoryBean defaultValidator() {
   LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
   MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
   factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
   return factoryBean;
}

Validator接口类定义了校验的方法,利用这些定义的方法,可以实现自己的一套校验逻辑,本质还是利用Validator接口实现。

 Set> validate(T object, Class... groups);
 Set> validateProperty(T object,
                                                     String propertyName,
                                                     Class... groups);

 Set> validateValue(Class beanType,
                                                  String propertyName,
                                                  Object value,
                                                  Class... groups);
......

在学习完SpringBoot之后,作为练习项目中用到了JSP303校验,全文可能存在不太正确的地方,后面会进行一些勘误。

下一篇将总结项目中自定义校验实现后的异常部分的处理。

Original: https://www.cnblogs.com/csrecord/p/16436276.html
Author: IWANNPEACE
Title: SpringBoot整合参数校验的两种方式应用实践

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714293/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球