阅读量:2
1.新建操作类型枚举(这里的IEnum是我自定义的http请求拦截接口,不需要的话可以不用实现)
@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.新建校验注解
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SmsValidate { /** * 操作类型 * @return */ OperationType operationType() default OperationType.LOGIN_BY_PWD; }
3.创建验证码校验接口
public interface ISmsValidate { /** * 短信验证码手机号 * @return */ String mobile(); /** * 短信验证码内容 * @return */ String smsCode(); }
4.controller方法请求参数,实现ISmsValidate接口
@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切面类
@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缓存
补一个自定义断言类
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); } }