验证短信登录或注册

Bo(business object)
封装业务对象的属性

  • 只包含业务对象的属性;
  • 只包含业务方法;
  • 两者都包含。
    service层和web层进行数据交换用BO
    从业务模型角度看,见UML元件领域模型中的领域对象。
    通过调用DAO方法,结合PO,VO进行业务操作。把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。
    image

因为验证登录注册需要手机号验证码 我们封装一个手机号验证码的BO


import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

public class RegisterLoginBO {
    @NotBlank(message = "手机号不能为空")
    private String mobile;
    @NotBlank(message = "验证码不能为空")
    private String smsCode;

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getSmsCode() {
        return smsCode;
    }

    public void setSmsCode(String smsCode) {
        this.smsCode = smsCode;
    }
}

Vaild 注解以及BindingResult类
当对类中的字段进行校验我们一般有两种方法
方法一: 在业务代码中直接使用if语句判断字段是否为空 但是这种方法不好 会导致代码冗余度高
方法二: 使用vaild注解 交给spring处理即可

导包


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

@Null
限制只能为null

@NotNull
限制必须不为null

@AssertFalse
限制必须为false

@AssertTrue
限制必须为true

@DecimalMax(value)
限制必须为一个不大于指定值的数字

@DecimalMin(value)
限制必须为一个不小于指定值的数字

@Digits(integer,fraction)
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future
限制必须是一个将来的日期

@Max(value)
限制必须为一个不大于指定值的数字

@Min(value)
限制必须为一个不小于指定值的数字

@Past
限制必须是一个过去的日期

@Pattern(value)
限制必须符合指定的正则表达式

@Size(max,min)
限制字符长度必须在min到max之间

@Past
验证注解的元素值(日期类型)比当前时间早

@NotEmpty
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@NotBlank
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格

@Email
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

在类中添加即可
image

之后在controller方法中添加vaild注解即可

BindingResult 类中封装的valid注解中引发的错误
image

boolean hasErrors();中判断是否有错误
bindResult.getFieldErrors(); 获取所有字段
fieldError.getField() 获取字段
fieldError.getDefaultMessage()) 获取错误

因为别的controller可能会用到此方法 所以要封装到baseController中

    /**
     * 循环取出BO中的错误并返回
     * @param bindResult
     * @return
     */
    protected Map<String, String> getBindResultErrors(BindingResult bindResult) {
        Map<String, String> errorsMap = new HashMap<>();

        List<FieldError> fieldErrors = bindResult.getFieldErrors();
        fieldErrors.forEach((fieldError -> {
            errorsMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        }));

        return errorsMap;
    }

验证思路
首先判断字段是否合法 也就是手机号和验证码是否为非空
其次redis中的字段是否匹配

    @Override
    public GraceJSONResult doLogin(RegisterLoginBO registerLoginBO, BindingResult bindResult) {
        // 01 首先判断字段是否有错
        if (bindResult.hasErrors()) {
            Map<String, String> bindResultErrors = getBindResultErrors(bindResult);

            return GraceJSONResult.errorMap(bindResultErrors);
        }

        // 02 判断手机号和验证码是否匹配

        String mobile = registerLoginBO.getMobile();
        String smsCode = registerLoginBO.getSmsCode();
        String redisSMSCode = redisOperator.get(MOBILE_SMS_CODE + ":" + mobile);

        if (StringUtils.isBlank(redisSMSCode) || !smsCode.equals(redisSMSCode)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
        }


        return GraceJSONResult.ok();
    }

首先获取到手机号 验证码
在根据手机号获取到redis中的验证码
判断验证码是否为空 也就是在redis中查询不到
其次在判断前端传入的验证码是否和redis中的验证码匹配 若匹配直接返回ok

分组校验

根据不同的功能进行校验 如当进行删除操作时必须传入id 当进行插入操作时因为id时自增的 可以不用传入id
首先创建另个接口用于不同分组

public interface UpdateValid {
}

public interface AddValid {
}

使用group参数来进行分组
image
Null注解表示必须为空 当进行更新操作时 必须传入品牌id 当进行插入操作时 必须不指定id
然后在controller中定义所需操作即可
image

自定义校验注解

首先我们定义一个注解 注解上的注解可以看系统定义的注解 基本都一样 其中Constraint注解用于定义校验器
我们还在接口体中定义了一个values方法 用于记录传入的列表
message表示自定义的错误信息 校验失败默认会显示该信息 参数为包名
之后在resource中定义一个名为ValidationMessages.properties的文件 文件中配置之前写入message
image

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = { ValueListConstrain.class }
)
public @interface ValueList {
    String message() default "{com.lyra.mail.common.valueList.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    int[] values();
}

校验器
校验器范形方法1为自定义的注解 2为注解传入的类型
然后方法体 可以使用constraintAnnotation传入的values参数 这里传入的是1 0 然后使用isValid来进行校验 若set中不包含statusCode传入的参数 则表示校验失败
image

public class ValueListConstrain implements ConstraintValidator<ValueList, Integer> {
    private final Set<Integer> set = new HashSet<>();

    @Override
    public void initialize(ValueList constraintAnnotation) {
        for (int value : constraintAnnotation.values()) {
            set.add(value);
        }
    }

    @Override
    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
        return set.contains(integer);
    }
}
posted @   RainbowMagic  阅读(541)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示