微信测试账号 (3)-微信接口权限 access_token

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangb_java/article/details/78092376

有许多功能,需要我们主动调用微信的接口,比如修改公众号菜单,主动给用户发消息等。此时微信会对我们的权限进行验证,这个权限就是access_token。

appID和appsecret

登录测试账号时有两个参数,appID是公众号的唯一标识,appsecret就是密钥。关于密钥是什么,参考web安全(1)

获取access_token

用你的appID和appsecret替换以下代码xxx即可。

		String appId="xxxxxxxxxxx";
		String appSecret="xxxxxxxxxxx"; 
		String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={1}&secret={2}";
		Map map = restTemplate.getForObject(url,Map.class,appId,appSecret);

返回参数

以上返回值map中有两个参数

access_token:就是微信接口的请求权限。

expires_in:过期时间(秒),目前是7200,即两小时。

注意事项

1.请求接口后会刷新access_token,之前的access_token会过期,但是在5分钟之内,新老access_token都可以用。

2.请求接口每天是有请求次数限制的,获取以后要自己缓存起来,每隔一段时间(比如1个半小时)刷新一次。(定时任务)

3.微信官方说两小时有效期在以后有可能会调整,除了上面主动定时刷新,还需要进行被动刷新。即写入缓存时要同时记录写入时间,而读取缓存时要用读取时间与写入时间做对比,如果超出expires_in参数内的时间,就去刷新。这段代码纯逻辑,自行实现。

4.很多缓存都有过期机制,即在一定时间后就会被系统清理。通过这一特点,可以指定如1个半小时过期,这样可以省略上面第3条的逻辑代码。每次读取缓存如果发现为null,就说明它过期被自动清理了,此时就去刷新。可参考spring boot缓存

并发锁

微信在此提到了并发问题,即不要同时多个线程去请求access_token接口,否则会互相覆盖,并且无端增加接口请求次数,可能造成该接口不可用。下面是spring服务层的一段伪代码,使用synchronized来实现并发锁。

	//同步数据
	Map<String,Object> accessTokenMap = new HashMap<String,Object>();
	//被动刷新并返回,每次获取accessToken时进行检查 
	public String getToken(){
		accessTokenMap = "从缓存读取accessToken及相关信息";
		if("验证是否超时,或是否为null,超时则进入if块")){
			synchronized (accessTokenMap) {
				if("验证是否超时,或是否为null,超时则进入if块"){
					accessTokenMap = "刷新accessToken";
				}	
			}
		}
		return accessTokenMap.get("access_token").toString();
	}
	//主动刷新并返回,由定时任务触发。如果采用注意事项4的方案,可省略
	public String updateToken(){
		synchronized (accessTokenMap) {
			accessTokenMap = "刷新accessToken";
		}
		return accessTokenMap.get("access_token").toString();
	}

1.accessTokenMap就是我们要锁住的对象,包含access_toke及其写入时间,过期时间都存储在里面。

2.先看下面的updateToken方法,这是由定时任务触发的主动刷新。不需要检查是否过期,直接强制刷新。 之所以加synchronized锁,是为了锁住被动刷新,即在主动刷新的时候不允许被动刷新。

3.getToken方法就是被动刷新,我们都知道要先判断是否超时,但为什么要判断两次?synchronized外层的判断是为了尽量不要进入synchronized锁,以提高性能,因为大多数请求应该都是没有超时的。synchronized内层的判断是在并发时,并发排名较后的线程后进入synchronized块时,accessTokenMap已经被排名较前的线程刷新过了,已经不超时了,也就不需要再去刷新一次。

猜你喜欢

转载自blog.csdn.net/wangb_java/article/details/78092376
今日推荐