Java自定义注解并实现
业务需求
半个月前,测试和我说:“如果商家被禁用了,那他就只能提现和查看自己的信息,不能修改。”
这把当时的我难住了。因为我们的商家是在一张表里的,所有的登录却是查的用户表,那怎么判断商家登录的他的商店是否被禁用了呢?我想到了一个以前从来没有尝试过的办法:AOP。
设计是这样的:被禁用的商家想要登录,没问题,可以,但他要想发货,操作商品,那不行,只有解封了才可以操作。在他禁用这段时间,他只能查看他的订单和商品情况,噢,还有可以提现。
于是乎,我东琢磨西琢磨,便琢磨出了这个注解。
代码赏析
1. 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 自定义注解
/**
* 商家操作限制
*
* @author: YCL
* @date: 2021-09-09 12:43:35
*/
@Target({
ElementType.TYPE,//作用于类上
ElementType.METHOD,//作用于方法上
})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationIntercept {
/**
* 默认拦截
*
* @return
*/
boolean intercept() default true;
}
3. 注解实现
A. 首先,定义一个类,啥都不继承
/**
* 操作限制实现
*
* @author: YCL
* @date: 2021-09-09 12:49:50
*/
@Aspect //标明是切面编程
@Configuration
@Component
public class OperationInterceptAspect {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private MallStoreService mallStoreService;
}
B. 解析注解
/**
* 这里不能用@annotation(), 不然类上面使用这个注解无效, 得使用@within()
*/
@Pointcut("@within(ycl.important.annocation.OperationIntercept)")
public void pointcut(){
}
/**
* 一般来说,鼠标悬停在 pointcut() 上加上ctrl键点击会跑到上面的方法,如果没跳就看看类开头的 @Aspect 加了没有
*
* 导包:
* org.aspectj.lang.JoinPoint
* org.aspectj.lang.reflect.MethodSignature
* java.lang.reflect.Method
* org.springframework.web.context.request.RequestContextHolder
*/
@Before("pointcut()")
public void before(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
OperationIntercept annotation = method.getAnnotation(OperationIntercept.class);
//是否校验, 我这边设置了为true就校验
boolean intercept = true;
if (annotation != null)
intercept = annotation.intercept();
if (!intercept)
return;
//获取request,项目的请求头token是被request带过来的,所以这里必须要request
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
if (attributes == null)
return;
HttpServletRequest request = (HttpServletRequest) attributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
if (request == null)
return;
Long id = mallStoreService.getUserId(request);
Long mall = mallStoreService.selectIdByUserId(id);
String s = stringRedisTemplate.opsForValue().get(RedisConstant.MERCHANT_DISABLE + mall);
if (StrUtil.isNotBlank(s))
throw new IllegalArgumentException("抱歉, 您被禁用, 无法操作");
}
到此,这个注解就结束啦!接下来测试一下
测试
1. 后台禁用
现在如图可以看到,登录上去后用户id 是3,对应的商店id 是 1。
现在把这个3468给禁用掉
redis里出现一个商家被禁用标志
2. 在商品的api上配置注解
挖个坑:这个注解可以作用在类上和方法上。如果在一个配置上这个注解的类里面,一个方法配置不校验,另一个不配置会怎么样呢?
再挖个坑:那如果在一个没有配置这个注解的类里面,一个方法加上这个注解,另一个不加,又会怎么样呢?
坑 1 图
坑 2 图
3. 商家操作
我们先看看这个商店发布的商品的 id 是多少
A. 我们来看看坑一的查商品,能不能查到
B. 来看看坑一的商品下架
C. 再看看第二个坑的主页
D. 第二个坑的第二个
总结
- 当我们在类上配置了这个注解后,因为本注解默认是校验,所以里面的所有方法都会一同被校验,这时当我们需要某个方法不需要校验时再单独给他配置一下就可以了。
- 当我们在类上不配置这个注解后,下面的所有注解就都用不了了。
为什么呢?按照常理来说,这个配置放不放在类上,和方法是无影响的呀?
好吧,我也不清楚他咋会这样……也算挖了第三个坑,以后来填了……
结语
希望我们同代码一起携手共进,一起为自己的目标努力!!
由衷感谢您的观看,您的收获和支持就是我的最大动力!!再次感谢!!