国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

由獲取微信access

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-09 07:44:24
文檔

由獲取微信access

由獲取微信access:背景 : access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。開發(fā)者需要進(jìn)行妥善保存。access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù) 獲取 將導(dǎo)致上次 獲取 的acces
推薦度:
導(dǎo)讀由獲取微信access:背景 : access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。開發(fā)者需要進(jìn)行妥善保存。access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù) 獲取 將導(dǎo)致上次 獲取 的acces

背景 : access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。開發(fā)者需要進(jìn)行妥善保存。access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù) 獲取 將導(dǎo)致上次 獲取 的access_token

背景:

access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。開發(fā)者需要進(jìn)行妥善保存。access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù)獲取將導(dǎo)致上次獲取的access_token失效。

1、為了保密appsecrect,第三方需要一個(gè)access_token獲取和刷新的中控服務(wù)器。而其他業(yè)務(wù)邏輯服務(wù)器所使用的access_token均來(lái)自于該中控服務(wù)器,不應(yīng)該各自去刷新,否則會(huì)造成access_token覆蓋而影響業(yè)務(wù);
2、目前access_token的有效期通過(guò)返回的expire_in來(lái)傳達(dá),目前是7200秒之內(nèi)的值。中控服務(wù)器需要根據(jù)這個(gè)有效時(shí)間提前去刷新新access_token。在刷新過(guò)程中,中控服務(wù)器對(duì)外
輸出的依然是老access_token,此時(shí)公眾平臺(tái)后臺(tái)會(huì)保證在刷新短時(shí)間內(nèi),新老access_token都可用,這保證了第三方業(yè)務(wù)的平滑過(guò)渡; 3、access_token的有效時(shí)間可能會(huì)在未來(lái)有調(diào)整,所以中控服務(wù)器不僅需要內(nèi)部定時(shí)主動(dòng)刷新,還需要提供被動(dòng)刷新access_token的接口,這樣便于業(yè)務(wù)服務(wù)器在API調(diào)用獲知access_token已超時(shí)的情況下,可以觸發(fā)access_token的刷新流程。

簡(jiǎn)單起見(jiàn),使用一個(gè)隨servlet容器一起啟動(dòng)的servlet來(lái)實(shí)現(xiàn)獲取access_token的功能,具體為:因?yàn)樵搒ervlet隨著web容器而啟動(dòng),在該servlet的init方法中觸發(fā)一個(gè)線程來(lái)獲得access_token,該線程是一個(gè)無(wú)線循環(huán)的線程,每隔2個(gè)小時(shí)刷新一次access_token。相關(guān)代碼如下:
1)servlet代碼:

public class InitServlet extends HttpServlet 
{
	private static final long serialVersionUID = 1L;

	public void init(ServletConfig config) throws ServletException 
	{
	new Thread(new AccessTokenThread()).start(); 
	}

}

2)線程代碼:

public class AccessTokenThread implements Runnable 
{
	public static AccessToken accessToken;
	
	@Override
	public void run() 
	{
	while(true) 
	{
	try{
	AccessToken token = AccessTokenUtil.freshAccessToken();	// 從微信服務(wù)器刷新access_token
	if(token != null){
	accessToken = token;
	}else{
	System.out.println("get access_token failed------------------------------");
	}
	}catch(IOException e){
	e.printStackTrace();
	}
	
	try{
	if(null != accessToken){
	Thread.sleep((accessToken.getExpire_in() - 200) * 1000);	// 休眠7000秒
	}else{
	Thread.sleep(60 * 1000);	// 如果access_token為null,60秒后再獲取
	}
	}catch(InterruptedException e){
	try{
	Thread.sleep(60 * 1000);
	}catch(InterruptedException e1){
	e1.printStackTrace();
	}
	}
	}
	}
}

3)AccessToken代碼:

public class AccessToken 
{
	private String access_token;
	private long expire_in;	// access_token有效時(shí)間,單位為妙
	
	public String getAccess_token() {
	return access_token;
	}
	public void setAccess_token(String access_token) {
	this.access_token = access_token;
	}
	public long getExpire_in() {
	return expire_in;
	}
	public void setExpire_in(long expire_in) {
	this.expire_in = expire_in;
	}
}

4)servlet在web.xml中的配置

 
 initServlet
 com.sinaapp.wx.servlet.InitServlet
 0
 

因?yàn)閕nitServlet設(shè)置了load-on-startup=0,所以保證了在所有其它servlet之前啟動(dòng)。

其它servlet要使用access_token的只需要調(diào)用 AccessTokenThread.accessToken即可。

引出多線程并發(fā)問(wèn)題:

1)上面的實(shí)現(xiàn)似乎沒(méi)有什么問(wèn)題,但是仔細(xì)一想,AccessTokenThread類中的accessToken,它存在并發(fā)訪問(wèn)的問(wèn)題,它僅僅由AccessTokenThread每隔2小時(shí)更新一次,但是會(huì)有很多線程來(lái)讀取它,它是一個(gè)典型的讀多寫少的場(chǎng)景,而且只有一個(gè)線程寫。既然存在并發(fā)的讀寫,那么上面的代碼肯定是存在問(wèn)題的。

一般想到的最簡(jiǎn)單的方法是使用synchronized來(lái)處理:

public class AccessTokenThread implements Runnable 
{
	private static AccessToken accessToken;
	
	@Override
	public void run() 
	{
	while(true) 
	{
	try{
	AccessToken token = AccessTokenUtil.freshAccessToken();	// 從微信服務(wù)器刷新access_token
	if(token != null){
	AccessTokenThread.setAccessToken(token);
	}else{
	System.out.println("get access_token failed");
	}
	}catch(IOException e){
	e.printStackTrace();
	}
	
	try{
	if(null != accessToken){
	Thread.sleep((accessToken.getExpire_in() - 200) * 1000);	// 休眠7000秒
	}else{
	Thread.sleep(60 * 1000);	// 如果access_token為null,60秒后再獲取
	}
	}catch(InterruptedException e){
	try{
	Thread.sleep(60 * 1000);
	}catch(InterruptedException e1){
	e1.printStackTrace();
	}
	}
	}
	}

	public synchronized static AccessToken getAccessToken() {
	return accessToken;
	}

	private synchronized static void setAccessToken(AccessToken accessToken) {
	AccessTokenThread2.accessToken = accessToken;
	}
}

accessToken變成了private,setAccessToken也變成了private,增加了同步synchronized訪問(wèn)accessToken的方法。

那么到這里是不是就完美了呢?就沒(méi)有問(wèn)題了呢?仔細(xì)想想,還是有問(wèn)題,問(wèn)題出在AccessToken類的定義上,它提供了public的set方法,那么所有的線程都在使用AccessTokenThread.getAccessToken()獲得了所有線程共享的accessToken之后,任何線程都可以修改它的屬性?。。?!而這肯定是不對(duì)的,不應(yīng)該的。

2)解決方法一:

我們讓AccessTokenThread.getAccessToken()方法返回一個(gè)accessToken對(duì)象的copy,副本,這樣其它的線程就無(wú)法修改AccessTokenThread類中的accessToken了。如下修改AccessTokenThread.getAccessToken()方法即可:

	public synchronized static AccessToken getAccessToken() {
	AccessToken at = new AccessToken();
	at.setAccess_token(accessToken.getAccess_token());	
	at.setExpire_in(accessToken.getExpire_in());
	return at;
	}

也可以在AccessToken類中實(shí)現(xiàn)clone方法,原理都是一樣的。當(dāng)然setAccessToken也變成了private。

3)解決方法二:

既然我們不應(yīng)該讓AccessToken的對(duì)象被修改,那么我們?yōu)槭裁床粚ccessToken定義成一個(gè)“不可變對(duì)象”?相關(guān)修改如下:

public class AccessToken 
{
	private final String access_token;
	private final long expire_in;	// access_token有效時(shí)間,單位為妙
	
	public AccessToken(String access_token, long expire_in)
	{
	this.access_token = access_token;
	this.expire_in = expire_in;
	}
	
	public String getAccess_token() {
	return access_token;
	}
	
	public long getExpire_in() {
	return expire_in;
	}
}

如上所示,AccessToken所有的屬性都定義成了final類型了,只提供構(gòu)造函數(shù)和get方法。這樣的話,其他的線程在獲得了AccessToken的對(duì)象之后,就無(wú)法修改了。改修改要求AccessTokenUtil.freshAccessToken()中返回的AccessToken的對(duì)象只能通過(guò)有參的構(gòu)造函數(shù)來(lái)創(chuàng)建。同時(shí)AccessTokenThread的setAccessToken也要修改成private,getAccessToken無(wú)須返回一個(gè)副本了。

注意不可變對(duì)象必須滿足下面的三個(gè)條件:

a) 對(duì)象創(chuàng)建之后其狀態(tài)就不能修改;

b) 對(duì)象的所有域都是final類型;

c) 對(duì)象是正確創(chuàng)建的(即在對(duì)象的構(gòu)造函數(shù)中,this引用沒(méi)有發(fā)生逸出);

4)解決方法三:

還有沒(méi)有其他更加好,更加完美,更加高效的方法呢?我們分析一下,在解決方法二中,AccessTokenUtil.freshAccessToken()返回的是一個(gè)不可變對(duì)象,然后調(diào)用private的AccessTokenThread.setAccessToken(AccessToken accessToken)方法來(lái)進(jìn)行賦值。這個(gè)方法上的synchronized同步起到了什么作用呢?因?yàn)閷?duì)象時(shí)不可變的,而且只有一個(gè)線程可以調(diào)用setAccessToken方法,那么這里的synchronized沒(méi)有起到"互斥"的作用(因?yàn)橹挥幸粋€(gè)線程修改),而僅僅是起到了保證“可見(jiàn)性”的作用,讓修改對(duì)其它的線程可見(jiàn),也就是讓其他線程訪問(wèn)到的都是最新的accessToken對(duì)象。而保證“可見(jiàn)性”是可以使用volatile來(lái)進(jìn)行的,所以這里的synchronized應(yīng)該是沒(méi)有必要的,我們使用volatile來(lái)替代它。相關(guān)修改代碼如下:

public class AccessTokenThread implements Runnable 
{
	private static volatile AccessToken accessToken;
	
	@Override
	public void run() 
	{
	while(true) 
	{
	try{
	AccessToken token = AccessTokenUtil.freshAccessToken();	// 從微信服務(wù)器刷新access_token
	if(token != null){
	AccessTokenThread2.setAccessToken(token);
	}else{
	System.out.println("get access_token failed");
	}
	}catch(IOException e){
	e.printStackTrace();
	}
	
	try{
	if(null != accessToken){
	Thread.sleep((accessToken.getExpire_in() - 200) * 1000);	// 休眠7000秒
	}else{
	Thread.sleep(60 * 1000);	// 如果access_token為null,60秒后再獲取
	}
	}catch(InterruptedException e){
	try{
	Thread.sleep(60 * 1000);
	}catch(InterruptedException e1){
	e1.printStackTrace();
	}
	}
	}
	}

	private static void setAccessToken(AccessToken accessToken) {
	AccessTokenThread2.accessToken = accessToken;
	}
public static AccessToken getAccessToken() {
return accessToken;
} }

也可以這樣改:

public class AccessTokenThread implements Runnable 
{
	private static volatile AccessToken accessToken;
	
	@Override
	public void run() 
	{
	while(true) 
	{
	try{
	AccessToken token = AccessTokenUtil.freshAccessToken();	// 從微信服務(wù)器刷新access_token
	if(token != null){
	accessToken = token;
	}else{
	System.out.println("get access_token failed");
	}
	}catch(IOException e){
	e.printStackTrace();
	}
	
	try{
	if(null != accessToken){
	Thread.sleep((accessToken.getExpire_in() - 200) * 1000);	// 休眠7000秒
	}else{
	Thread.sleep(60 * 1000);	// 如果access_token為null,60秒后再獲取
	}
	}catch(InterruptedException e){
	try{
	Thread.sleep(60 * 1000);
	}catch(InterruptedException e1){
	e1.printStackTrace();
	}
	}
	}
	}

	public static AccessToken getAccessToken() {
	return accessToken;
	}
}

還可以這樣改:

public class AccessTokenThread implements Runnable 
{
 public static volatile AccessToken accessToken;
 
 @Override
 public void run() 
 {
 while(true) 
 {
 try{
 AccessToken token = AccessTokenUtil.freshAccessToken(); // 從微信服務(wù)器刷新access_token
 if(token != null){
 accessToken = token;
 }else{
 System.out.println("get access_token failed");
 }
 }catch(IOException e){
 e.printStackTrace();
 }
 
 try{
 if(null != accessToken){
 Thread.sleep((accessToken.getExpire_in() - 200) * 1000); // 休眠7000秒
 }else{
 Thread.sleep(60 * 1000); // 如果access_token為null,60秒后再獲取
 }
 }catch(InterruptedException e){
 try{
 Thread.sleep(60 * 1000);
 }catch(InterruptedException e1){
 e1.printStackTrace();
 }
 }
 }
 }
}

accesToken變成了public,可以直接是一個(gè)AccessTokenThread.accessToken來(lái)訪問(wèn)。

其實(shí)這個(gè)問(wèn)題的關(guān)鍵是:在多線程并發(fā)訪問(wèn)的環(huán)境中如何正確的發(fā)布一個(gè)共享對(duì)象。

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

由獲取微信access

由獲取微信access:背景 : access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。開發(fā)者需要進(jìn)行妥善保存。access_token的存儲(chǔ)至少要保留512個(gè)字符空間。access_token的有效期目前為2個(gè)小時(shí),需定時(shí)刷新,重復(fù) 獲取 將導(dǎo)致上次 獲取 的acces
推薦度:
標(biāo)簽: 微信 背景 獲取
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 亚洲福利视频 | 国产91精品一区二区麻豆亚洲 | 91精品国产乱码久久久久久 | 一级毛片黄 | 亚洲欧美一区二区三区久久 | 麻豆91视频 | 日韩欧美区 | 成人毛片在线播放 | 亚洲日韩视频 | 亚洲自拍另类 | 国产a视频精品免费观看 | 国产成人一区二区三区小说 | 久久久久国产一级毛片高清版 | 国产91久久久久久久免费 | 日韩欧美色综合 | 国产短视频精品一区二区三区 | 亚洲欧美日韩中另类在线 | 91精品啪国产在线观看免费牛牛 | 欧美高清第一页 | 国产成人亚洲欧美三区综合 | 国产 日韩 欧美在线 | 人人添人人澡人人澡人人人爽 | 91精品国产91热久久p | 国产亚洲视频在线观看 | 国产在线精品一区二区 | 国产毛片一区二区 | 日韩国产在线播放 | 亚洲电影资源 | 精品一区二区三区五区六区 | 国产精品日韩欧美一区二区三区 | 日韩欧美亚| 成人久久精品 | 中文国产成人精品少久久 | 欧美视频在线免费 | 亚洲天堂一区二区三区 | 中文字字幕| 亚洲欧美日韩国产综合 | 国产色在线视频 | 国产又黄又a又潮娇喘视频 国产淫视频 | 国产区在线免费观看 | 国产区在线视频 |