2021-04-21-自定义注解+aop实际应用

元注解

  • @Documented:注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解
  • @Target:注解的作用目标
    @Target(ElementType.TYPE)——接口、类、枚举、注解
    @Target(ElementType.FIELD)——字段、枚举的常量
    @Target(ElementType.METHOD)——方法
    @Target(ElementType.PARAMETER)——方法参数
    @Target(ElementType.CONSTRUCTOR) ——构造函数
    @Target(ElementType.LOCAL_VARIABLE)——局部变量
    @Target(ElementType.ANNOTATION_TYPE)——注解
    @Target(ElementType.PACKAGE)——包
  • @Retention表示注解的有效范围
    RetentionPolicy.SOURCE - 当前注解只在源代码中有效,一旦编译成class文件,注解就会丢失
    RetentionPolicy.CLASS - 注解在源码和字节码中有效,一旦运行就会丢失
    RetentionPolicy.RUNTIME - 注解在源码、字节码和运行时都会保留

注解定义方法

  • 语法:方法返回值类型 方法名() [default 默认值] ;

  • 注意:
    1、注解中方法的名字如果刚好叫value,则使用注解时,可以忽略方法名
    2、如果使用注解时,需要设置多个方法的返回值,则value不能省略
    3、如果一个方法的返回值是数组类型,并且只需要设置一个值时,大括号可以省略
    4、如果在使用的时候不想给某个方法赋值,需要在定义该方法的时候设置默认值。

  • 举例

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsLogin {

    int value() default 0;

    String[] values() default {};
}

SpringBoot整合自定义注解+aop

  • 添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

  • 自定义注解
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsLogin {
    boolean mustUser() default false;
}

  • 自定义切面实现全局有用
@Aspect // 标记这是一个切面
@Component // 让Spring容器识别到
public class LoginAOP {

    @Around("@annotation(IsLogin)") // 对加了这个@IsLogin的方法进行环绕
    public Object handlerLogin(ProceedingJoinPoint point){
        Object proceed = null;
        try {
            System.out.println("环绕开始。。。");
            proceed = point.proceed();
            System.out.println("环绕结束。。。");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}


  • Controller方法使用
    @RequestMapping(value = "/to1")
    @IsLogin
    public String to1(){
        System.out.println("SSOController.to1");
        return "login";
    }
}

AOP统一身份认证

  • 添加依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

 <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.1.8.RELEASE</version>
    <scope>provided</scope>
</dependency>

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

<dependency>
    <groupId>com.qf.test</groupId>
    <artifactId>shop_entity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

  • 自定义登录注解
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsLogin {
    boolean mustUser() default false;
}

  • AOP全局登录认证
@Aspect // 标记这是一个切面
@Component // 让Spring容器识别到
public class LoginAOP {

    @Autowired
    private RedisTemplate redisTemplate;

    @Around("@annotation(IsLogin)") // 对加了这个@IsLogin的方法进行环绕
    public Object handlerLogin(ProceedingJoinPoint point){

        // 1.获取目标法方法
        MethodSignature methodSignature = (MethodSignature)point.getSignature();
        Method method = methodSignature.getMethod();

        // 2.得到isLogin注解
        IsLogin isLogin = method.getAnnotation(IsLogin.class);


        // 3.获取req对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        // 4.获取token
        String userTokenKey = CookieUtils.getValue("userToken");

        User user = null;
        if(!StringUtils.isEmpty(userTokenKey)){
            // 从redis中查询token
            user = (User) redisTemplate.opsForValue().get(userTokenKey);
        }

        // 5.判断是否登录
        if(user == null){
            // 3.判断是否需要注入user对象
            if(isLogin.mustUser()){

                // 记录当前url
                String returnUrl = request.getRequestURL().toString();
                try {
                    returnUrl = URLEncoder.encode(returnUrl,"utf-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                // 强制跳转到的登录页面
                return "redirect:http://localhost:8084/toLogin?returnUrl="+returnUrl;
            }
        }

        // 给user参数赋值
        Object[] args = point.getArgs();
        for(int i =0;i<args.length;i++){
            if(args[i] != null && args[i].getClass() == User.class){
                args[i]=user;
                break;
            }
        }

        Object proceed = null;
        try {
            // 调用目标方法
            proceed = point.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值