• 关于开发中使用AOP的坑


    关于开发中使用AOP的坑

    在一次分布式宾馆管理系统中使用AOP开发中,PointCut连接点是一个注解类@LoginToken,通过该注解类获取前端传送的Token值,直接封装成User,还能根据Token判断用户是否登录,但是在开发中,发现注解类切入点表达式一直报错

    注解类@LoginToken

    @Documented
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginToken {
      
    }
    

    注解实现类,如果要经过网关,还需要在网关中配置

    zuul:
     sensitive-headers:
    
    /**
    * 根据token返回用户登录的对象,如果没有登录或者token验签错误,返回null
    * @param pro
    * @param loginToken
    * @return
    * @throws Throwable
    */
    @Aspect
    @Slf4j
    @Component
    public class LoginTokenAOP2 {
       
        @Around("@annotation(loginToken)")//自定义@Around增强,pointcut连接点是使用@@annotation
        //------------------------------注意看这里----------------------------------
        public Object tokenHandler(LoginToken loginToken,ProceedingJoinPoint pro) throws Throwable{
        //-------------------------------------------------------------------------
            log.info("注解生效");
            //1、获取请求头
    
            //2、判断用户是否携带token
            if(StringUtils.isEmpty(token)){
                response.setContentType("application/json;charset=utf8");
                ObjectMapper mapper = new ObjectMapper();
                response.getWriter().write(mapper.writeValueAsString(ResultInfo.error("您还没有登录")));
                return null;
            }
            //3、获取用户的登录信息
            String id = JWTUtils.getClaim(token, "id");
    
            if(loginToken.isLogin() && StringUtils.isEmpty(id)){
                response.setContentType("application/json;charset=utf8");
                ObjectMapper mapper = new ObjectMapper();
                response.getWriter().write(mapper.writeValueAsString(ResultInfo.error("您还没有登录")));
                return null;
            }
            //4、封装
            User loginUser = new User();
            loginUser.setId(Integer.parseInt(id));
            log.info("loginUser="+loginUser);
    
            //5、获取切点的参数
            Object[] args = pro.getArgs();
            for (Object arg : args) {
                if(arg.getClass().equals(User.class)){
                    arg = loginUser;//将用户信息封装到切入点
                }
            }
            Object proceed = pro.proceed(args);
            return proceed;//1、获取request对象
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = servletRequestAttributes.getRequest();
    
            //2、获取请求头
            String token = request.getHeader("Authorization");
            log.info("token="+token);
    
            User user = null;
    
            //3、判断用户是否携带token
            if(!StringUtils.isEmpty(token)){
                //4、token进行验签
                ResultInfo require = JWTUtils.require(token);
                if(require.isStatus()){
                    user = new User();
                    //5、获取用户数据
                    String id = JWTUtils.getClaim(token, "id");
                    String username = JWTUtils.getClaim(token, "username");
                    user.setId(Integer.parseInt(id));
                    user.setUsername(username);
                }
            }
    
            //6、获取切点的参数
            Object[] args = pro.getArgs();
            //细节:使用增强for循环是不能对数据的值进行改变
    //        for (Object arg : args) {
    //            if(arg.getClass().equals(User.class)){
    //                arg = user;//将用户信息封装到切入点
    //                break;
    //            }
    //        }
            for (int i = 0; i < args.length; i++) {
                if(args[i].getClass().equals(User.class)){
                    args[i] = user;
                }
            }
            log.info("user="+user);
            //7、执行方法
            Object proceed = pro.proceed(args);
            return proceed;
        }
    }
    

    Caused by: java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut

    经过各种debug发现是参数的顺序错误,将顺序置换即可

    //------------------------------注意看这里----------------------------------
        public Object tokenHandler(LoginToken loginToken,ProceedingJoinPoint pro) throws Throwable{
    //-------------------------------------------------------------------------
    

    修改后

    //------------------------------注意看这里----------------------------------
        public Object tokenHandler(ProceedingJoinPoint, proLoginToken loginToken) throws Throwable{
    //-------------------------------------------------------------------------
    

    修改后程序正常执行,如果还没正常执行,请检查注解的变量名称和表达式的是否保持一致

  • 相关阅读:
    Oracle分页之一:最普通的分页方式
    MSSQL存储过程学习笔记一:关于存储过程
    MSSQL自动备份数据库
    小试JQuery的AutoComplete插件
    利用面向对象的方式来使用JS
    Oracle分页之三:利用PagerView来实现无刷新GridView
    由于 ASP.NET 进程标识对全局程序集缓存没有读权限,因此未能执行请求。错误: 0x80131902
    终端服务器超出最大允许连接数
    从苹果的Siri说起:云搜索与人工智能
    [转]为什么我们程序员难晋升
  • 原文地址:https://www.cnblogs.com/codeli/p/13674220.html
Copyright © 2020-2023  润新知