1.新建操作类型枚举(这里的IEnum是我自定义的http请求拦截接口,不需要的话可以不用实现)
java
@Getter
@AllArgsConstructor
public enum OperationType implements IEnum<Integer> {
/**
* 注册
*/
SIGN_UP(0),
/**
* 密码登录
*/
LOGIN_BY_PWD(1),
/**
* 验证码登录
*/
LOGIN_BY_SMS(2),
/**
* 忘记密码
*/
FORGET_PWD(3),
/**
* 修改密码
*/
MODIFY_PWD(4);
@JsonValue
private final int code;
@Override
public Integer getCode(){
return code;
}
}
2.新建校验注解
java
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SmsValidate {
/**
* 操作类型
* @return
*/
OperationType operationType() default OperationType.LOGIN_BY_PWD;
}
3.创建验证码校验接口
java
public interface ISmsValidate {
/**
* 短信验证码手机号
* @return
*/
String mobile();
/**
* 短信验证码内容
* @return
*/
String smsCode();
}
4.controller方法请求参数,实现ISmsValidate接口
java
@Data
public class LoginBySmsDto implements ISmsValidate {
@NotBlank(message = "用户名/手机号不能为空")
@IsMobile
private String username;
@NotBlank(message = "短信验证码不能为空")
private String code;
@Override
public String mobile() {
return this.getUsername();
}
@Override
public String smsCode() {
return this.getCode();
}
}
5.添加aop切面类
java
@Aspect
@Component
public class SmsValidateAop {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Pointcut(value = "@annotation(com.tfyt.common.annotation.SmsValidate)")
public void pointCut(){}
@Before(value = "pointCut()")
public void before(JoinPoint joinPoint){
SmsObj smsObj = getSmsObj(joinPoint);
Object cacheCode = redisTemplate.opsForValue().get(RedisKeyConstant.CACHE_SMS_CODE + smsObj.getOperationType() + ":" + smsObj.getMobile());
BusinessAssert.notTrue(Objects.equals(cacheCode,smsObj.getCode()),"手机验证码不正确");
}
@AfterReturning(value = "pointCut()")
public void after(JoinPoint joinPoint){
SmsObj smsObj = getSmsObj(joinPoint);
redisTemplate.delete(RedisKeyConstant.CACHE_SMS_CODE + smsObj.getOperationType() + ":" + smsObj.getMobile());
}
@Data
@AllArgsConstructor
@NoArgsConstructor
private static class SmsObj{
private String mobile;
private String code;
private Integer operationType;
}
private SmsObj getSmsObj(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
SmsValidate annotation = signature.getMethod().getAnnotation(SmsValidate.class);
BusinessAssert.isNull(annotation,"系统异常:未查询到注解");
BusinessAssert.isNull(annotation.operationType(),"系统异常:未配置操作类型");
Object[] args = joinPoint.getArgs();
ISmsValidate arg = null;
if(args[0] instanceof ISmsValidate){
arg = (ISmsValidate) args[0];
}
BusinessAssert.isNull(arg,"请输入用户名和手机验证码");
return new SmsObj(arg.mobile(), arg.smsCode(), annotation.operationType().getCode());
}
}
6.往controller的方法上注解
@SmsValidate(operationType = OperationType.LOGIN_BY_SMS)
重启springboot项目,调用接口即可生效,校验通过后会自动删除redis缓存
补一个自定义断言类
java
public class BusinessAssert {
public static void notTrue(boolean condition, String msg){
isTrue(!condition, msg);
}
public static void isTrue(boolean condition, String msg){
if(condition){
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),msg);
}
}
public static void nonNull(Object object,String msg){
if(null!=object){
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),msg);
}
}
public static void isNull(Object object,String msg){
if(null==object){
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),msg);
}
}
public static void isCollectionEmpty(Collection<?> collection,String msg){
if(collection == null || collection.isEmpty()){
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),msg);
}
}
public static void isCollectionNotEmpty(Collection<?> collection,String msg){
if(collection != null && !collection.isEmpty()){
throw new BusinessException(HttpStatus.BAD_REQUEST.value(),msg);
}
}