专栏文章 AOP 切面&自定义注解 用户快速登录

CC · 2019年02月13日 · 最后由 CC 回复于 2019年02月18日 · 2311 次阅读

这段时间在重写接口测试框架,为了确保对核心业务做全面的校验,因此也增加了 快速登录这块功能

参考官方文档
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop

自定义注解 QuickLogin

package com.hero.common.annotation;

import java.lang.annotation.*;

/**
 * @Des: 自定义注解--用户快速登录
 * @Auther: 飞狐
 * @Date: 2019/2/1
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface QuickLogin {

    String name() default "";

    String password() default "";
}

AOP 切面

支持 token 过期 401 时,自动重新登录


@Aspect
@Component
public class UserQuickLoginAspect {

    private Log LOG = LogFactory.getLog(UserQuickLoginAspect.class);

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private UserAccountDAO userAccountDAO;

    @Autowired
    private CommonUserInfoService commonUserInfoService;

    @Before(value = "@annotation(quickLogin)")
    public Object doUserLogin(QuickLogin quickLogin) throws Throwable {
        String name = quickLogin.name();
        String password = quickLogin.password();
        Reporter.log("快速登录:" + name + "/" + password);

        LocalUserInfo localUserInfo = commonUserInfoService.getLocalUserInfo(name);

        if(null == localUserInfo){
            return commonUserInfoService.userLoginByPassword(convert2UserLoginRequestInfo(quickLogin));
        }

        Long userId = localUserInfo.getUserId();

        DynamicMethodDataSourceHolder.set(name,userId.toString());

        //试下head方法,确定不是401
        Result result = userInfoService.headUserProfile(name);

        MiniResponse miniResponse = (MiniResponse) result.getRes();

        if (miniResponse.getCode() != HttpStatus.OK.value()) {
            return commonUserInfoService.userLoginByPassword(convert2UserLoginRequestInfo(quickLogin));
        }
        return result;

    }


    private UserLoginRequestInfo convert2UserLoginRequestInfo(QuickLogin quickLogin){
        UserLoginRequestInfo userLoginRequestInfo = new UserLoginRequestInfo();
        userLoginRequestInfo.setUserName(quickLogin.name());
        userLoginRequestInfo.setPassword(quickLogin.password());
        userLoginRequestInfo.setAppSource(quickLogin.appSource());
        return userLoginRequestInfo;
    }


}

ThreadLocal 处理,主要减少本地文件读写,直接线程变量中进行处理

/**
 * 本地线程缓存变量,存储userId
 * Created by huqingen on 2018/6/26.
 */
public class DynamicMethodDataSourceHolder {

    public static final ThreadLocal<Map<String,String>> hodler = new ThreadLocal<>();


    public static Map<String,String> get(){
        return hodler.get();
    }

    public static void set(Map<String,String> map){
        hodler.set(map);
    }

    public static void set(String key,String value){
        Map<String,String> map = hodler.get();
        if(map == null){
            map = Maps.newHashMap();
        }

        map.put(key,value);
        set(map);
    }

    public static void clean(){
        hodler.remove();
    }

}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 3 条回复 时间 点赞

都用上 spring 了

具体是在什么时候用啊,什么场景,怎么调用的?

CC #3 · 2019年02月18日 Author

陈大大,主要目的还是解决理解免登处理,代码解耦,不把登录代码写入到对应测试接口中
调用方式:

@Component("userSceneService")
public class UserSceneService{
  @Autowired
    private UserInfoService userInfoService;

  @QuickLogin(name = "18000000005",password = "123456")
    public Result checkUserProfile(){

        String userName = "18000000005";

        Result result = userInfoService.getUserProfileByAnnotation(userName);

        MiniResponse miniResponse = (MiniResponse) result.getRes();

        HeroAssert.assertEquals(miniResponse.getCode(), HttpStatus.SC_OK,"HTTP状态码为200");

        return result;
    }
}

新写这套框架,目标是解决核心接口校验 (缓存/es/db),及抽离这个校验方法,后续直接用到 app 自动化上,顺带 锻炼测试童鞋的代码编写能力~纯 web 页面形式的接口测试,主要写些非核心类的接口

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册