先实现一个自定义注解
@Target({ElementType.METHOD}) // 作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时起作用
public @interface ServiceSwitch {
/**
* 业务开关的key(不同key代表不同功效的开关)
*/
String switchKey();
// 提示信息,默认值可在使用注解时自行定义。
String message() default "该功能已被关闭,请联系管理员";
}
编写一个切面类,用于拦截需要进行开关操作的接口
@Aspect
@Component
@Slf4j
@AllArgsConstructor
public class ServiceSwitchAOP {
private final StringRedisTemplate redisTemplate;
/**
* 定义切点,使用了@ServiceSwitch注解的类或方法都拦截
*/
@Pointcut("@annotation(com.jy.demo.annotation.ServiceSwitch)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) {
// 获取被代理的方法的参数
Object[] args = point.getArgs();
// 获取被代理的对象
Object target = point.getTarget();
// 获取通知签名
MethodSignature signature = (MethodSignature) point.getSignature();
try {
// 获取被代理的方法
Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());
// 获取方法上的注解
ServiceSwitch annotation = method.getAnnotation(ServiceSwitch.class);
// 核心业务逻辑
if (annotation != null) {
String switchKey = annotation.switchKey();
String message = annotation.message();
// 从redis中获取启用状态
String configVal = redisTemplate.opsForValue().get(switchKey);
// 这里0代表已关闭
if ("0".equals(configVal)) {
// 开关关闭,则返回提示,返回类自行封装也可以使用SpringBoot中的ResponseEntity
return new Result<>(HttpStatus.FORBIDDEN.value(), message);
}
}
// 放行
return point.proceed(args);
} catch (Throwable e) {
// 自定义的业务异常
throw new BusinessException(e.getMessage(), e);
}
}
}
应用
/**
* 测试
*/
@ServiceSwitch(switchKey = "test")
public Result test() {
// ...实现具体业务逻辑
return new Result(HttpStatus.OK.value(), "测试");
}