<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答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
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

        由獲取微信access

        來源:懂視網(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均來自于該中控服務(wù)器,不應(yīng)該各自去刷新,否則會(huì)造成access_token覆蓋而影響業(yè)務(wù);
        2、目前access_token的有效期通過返回的expire_in來傳達(dá),目前是7200秒之內(nèi)的值。中控服務(wù)器需要根據(jù)這個(gè)有效時(shí)間提前去刷新新access_token。在刷新過程中,中控服務(wù)器對(duì)外
        輸出的依然是老access_token,此時(shí)公眾平臺(tái)后臺(tái)會(huì)保證在刷新短時(shí)間內(nèi),新老access_token都可用,這保證了第三方業(yè)務(wù)的平滑過渡; 3、access_token的有效時(shí)間可能會(huì)在未來有調(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)單起見,使用一個(gè)隨servlet容器一起啟動(dòng)的servlet來實(shí)現(xiàn)獲取access_token的功能,具體為:因?yàn)樵搒ervlet隨著web容器而啟動(dòng),在該servlet的init方法中觸發(fā)一個(gè)線程來獲得access_token,該線程是一個(gè)無線循環(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ā)問題:

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

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

        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訪問accessToken的方法。

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

        2)解決方法一:

        我們讓AccessTokenThread.getAccessToken()方法返回一個(gè)accessToken對(duì)象的copy,副本,這樣其它的線程就無法修改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ì)象之后,就無法修改了。改修改要求AccessTokenUtil.freshAccessToken()中返回的AccessToken的對(duì)象只能通過有參的構(gòu)造函數(shù)來創(chuàng)建。同時(shí)AccessTokenThread的setAccessToken也要修改成private,getAccessToken無須返回一個(gè)副本了。

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

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

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

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

        4)解決方法三:

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

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

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quá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
        主站蜘蛛池模板: 亚洲精品无码永久在线观看你懂的| 国国内清清草原免费视频99 | 免费一级毛suv好看的国产网站| 无码中文字幕av免费放| 亚洲国产亚洲综合在线尤物| 青娱乐免费在线视频| 亚洲人成人77777网站不卡| 97无码免费人妻超级碰碰夜夜| 亚洲嫩草影院在线观看| 亚洲中文无码永久免费| 亚洲熟妇丰满xxxxx| 日本无吗免费一二区| 免费激情网站国产高清第一页| www.亚洲色图.com| 精品国产污污免费网站| 久久99亚洲网美利坚合众国| 91免费在线播放| 亚洲国产精品无码中文lv| 亚洲AⅤ优女AV综合久久久| 中文字幕无码免费久久9一区9 | 特级做A爰片毛片免费看无码| 亚洲精品国偷自产在线| 五月婷婷在线免费观看| 亚洲AV无码成人精品区狼人影院| 亚洲XX00视频| 香港a毛片免费观看 | 亚洲午夜国产精品无码老牛影视 | av无码久久久久不卡免费网站| 亚洲AV男人的天堂在线观看| 亚洲第一黄色网址| 久久午夜免费鲁丝片| 亚洲人成人无码.www石榴| 久久亚洲中文字幕精品一区四| 99热在线观看免费| 亚洲狠狠婷婷综合久久| 亚洲无av在线中文字幕| 无码乱肉视频免费大全合集| 一级毛片**免费看试看20分钟| 亚洲色成人网一二三区| 亚洲阿v天堂在线2017免费| 亚洲免费在线视频|