最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

掃二維碼自動(dòng)跳轉(zhuǎn)【java】詳解

 更新時(shí)間:2019年05月06日 10:30:03   作者:開(kāi)發(fā)無(wú)難事  
這篇文章主要介紹了java掃二維碼自動(dòng)跳轉(zhuǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

這個(gè)帖子網(wǎng)上很多了,但是都是講理論知識(shí),我呢,喜歡搞代碼。既然搞完了,就貼出來(lái)備忘一下,也可以分享一下。

重復(fù)理論步驟:

1、進(jìn)入網(wǎng)站-生成UUID

2、跳轉(zhuǎn)到二維碼頁(yè)面(二維碼包含UUID)

3、二維碼頁(yè)面寫(xiě)一個(gè)js,自動(dòng)請(qǐng)求服務(wù)器查詢二維碼是否被掃

4、服務(wù)器收到請(qǐng)求,查詢,如果還沒(méi)被掃,進(jìn)入等待,先不返回結(jié)果

5、一旦被掃,立即返回結(jié)果,頁(yè)面js收到響應(yīng),做后續(xù)處理

OK,步驟是這樣的沒(méi)錯(cuò),不過(guò)有一點(diǎn)缺點(diǎn),步驟3中如果請(qǐng)求超時(shí)怎么辦。

這個(gè)微信web登錄有示例,服務(wù)器被請(qǐng)求后,持續(xù)等待25秒左右,然后結(jié)束請(qǐng)求,js端重新發(fā)起請(qǐng)求,就這樣25秒為周期,不停發(fā)起長(zhǎng)鏈接請(qǐng)求。

看下微信web的長(zhǎng)連接

不說(shuō)了,貼代碼了,我這里使用的是spring-boot ,spring版本是4.3.6

1、生成UUID

@RequestMapping("/")
	String index(HttpServletRequest request,HttpServletResponse response)
	{
		System.out.println("進(jìn)入首頁(yè),先生成UUID");
		
		request.setAttribute("uuid", UUID.randomUUID());
		
		return "pages/index";
	}

2、生成二維碼,頁(yè)面部分

<body>
	<div class="main">
		<div class="title">
			<img id="qrcode" alt="" src="">
		</div>
		<div id="result" class="title"></div>
	</div>
 
</body>

頁(yè)面js:

$(function() {
		// 文檔就緒
		$("#qrcode").attr("src", "/qrcode/${uuid}");
	 $("#result").html("使用手機(jī)掃描二維碼");
		keepPool();//一加載就進(jìn)入自動(dòng)請(qǐng)求-見(jiàn)步驟3
	});

3、頁(yè)面js自動(dòng)請(qǐng)求服務(wù)器查詢是否被掃

function keepPool(){
		$.post("/pool", {
   uuid : "${uuid}",
  }, function(data) {
   if(data=='success'){
    $("#result").html("登錄成功");
   }else if(data=='timeout'){
   	$("#result").html("登錄超時(shí),請(qǐng)刷新重試");
   }else{
    keepPool();
   }
  });
	}

4、服務(wù)器收到請(qǐng)求,這里服務(wù)器端的事情還是蠻多的,分解一下

1、首先要生成二位碼,對(duì)應(yīng) $("#qrcode").attr("src", "/qrcode/${uuid}");

2、生成二位碼后,需要將uuid放入到緩存,我是將UUID作為建,新建一個(gè)對(duì)象作為值(這里可以采用redis),我為了學(xué)習(xí)方便,自己寫(xiě)了個(gè)緩存

3、查詢是否被掃,對(duì)應(yīng)$.post("/pool", { uuid : "${uuid}"}......,這時(shí)候有一個(gè)等待的功能(緩存中的對(duì)象來(lái)控制,這個(gè)對(duì)象的鍵就是UUID)

4、被掃后,立馬通知等待者(這里是通過(guò)緩存中的對(duì)象來(lái)通知消息的)

5、上面說(shuō)了好多次對(duì)象了,對(duì)的,都是同一個(gè),接著貼代碼了

4.1-4.2 生成二位碼,我這里使用的google的zxing

@RequestMapping("/qrcode/{uuid}")
	@ResponseBody
	String createQRCode(@PathVariable String uuid,HttpServletResponse response)
	{
		System.out.println("生成二維碼");
		
		String text = "http://172.20.16.194:8080/login/"+uuid;
		int width = 300; 
		int height = 300; 
		String format = "png"; 
		//將UUID放入緩存
		ScanPool pool = new ScanPool();
		PoolCache.cacheMap.put(uuid, pool);
		try
		{
			Map<EncodeHintType, Object> hints= new HashMap<EncodeHintType, Object>(); 
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
			//hints.put(EncodeHintType.MARGIN, 1);
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //容錯(cuò)率
			BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height,hints);
			MatrixToImageWriter.writeToStream(bitMatrix, format, response.getOutputStream());
		} catch (WriterException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

看到對(duì)象ScanPool沒(méi)有,這就是那個(gè)對(duì)象,PoolCache是那個(gè)緩存,既然說(shuō)了,先貼這兩個(gè)類。

ScanPool.java

public class ScanPool
{
 
	//創(chuàng)建時(shí)間
	private Long createTime = System.currentTimeMillis();
	
	//登錄狀態(tài)
	private boolean scanFlag = false;
	
	public boolean isScan(){
		return scanFlag;
	}
	
	public void setScan(boolean scanFlag){
		this.scanFlag = scanFlag;
	}
	
	/**
	 * 獲取掃描狀態(tài),如果還沒(méi)有掃描,則等待固定秒數(shù)
	 * @param wiatSecond 需要等待的秒數(shù)
	 * @return
	 */
	public synchronized boolean getScanStatus(){
		try
		{
			if(!isScan()){ //如果還未掃描,則等待
				this.wait();
			}
			if (isScan())
			{
				return true;
			}
		} catch (InterruptedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 掃碼之后設(shè)置掃碼狀態(tài)
	 */
	public synchronized void scanSuccess(){
		try
		{
			setScan(true);
			this.notifyAll();
		} catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public synchronized void notifyPool(){
		try
		{
			this.notifyAll();
		} catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
 
	public Long getCreateTime()
	{
		return createTime;
	}
 
	public void setCreateTime(Long createTime)
	{
		this.createTime = createTime;
	}
 
}

PoolCache.java

public class PoolCache
{
	//緩存超時(shí)時(shí)間 10分鐘
	private static Long timeOutSecond = 600L;
	
	//每半小時(shí)清理一次緩存
	private static Long cleanIntervalSecond = 1800L;
	
	public static Map<String, ScanPool> cacheMap = new HashMap<String, ScanPool>();
	
	static{
		new Thread(new Runnable()
		{
			
			@Override
			public void run()
			{
				// TODO Auto-generated method stub
				while (true)
				{
					try
					{
						Thread.sleep(cleanIntervalSecond*1000);
					} catch (InterruptedException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					clean();
				}
			}
			
			public void clean(){
				if(cacheMap.keySet().size() > 0){
					Iterator<String> iterator = cacheMap.keySet().iterator();
					while (iterator.hasNext())
					{
						String key = iterator.next();
						ScanPool pool = cacheMap.get(key);
						if(System.currentTimeMillis() - pool.getCreateTime() > timeOutSecond * 1000){
							cacheMap.remove(key);
						}
					}
				}
			}
		}).start();
	}
 
}

4.3.查詢是否被掃

@RequestMapping("/pool")
	@ResponseBody
	String pool(String uuid){
		System.out.println("檢測(cè)["+uuid+"]是否登錄");
		
		ScanPool pool = PoolCache.cacheMap.get(uuid);
		
		if(pool == null){
			return "timeout";
		}
		
		//使用計(jì)時(shí)器,固定時(shí)間后不再等待掃描結(jié)果--防止頁(yè)面訪問(wèn)超時(shí)
		new Thread(new ScanCounter(uuid)).start();
		
		boolean scanFlag = pool.getScanStatus();
		if(scanFlag){
			return "success";
		}else{
			return "fail";
		}
	}

這里看到,有一個(gè)防止頁(yè)面請(qǐng)求超時(shí)的,是寫(xiě)了一個(gè)計(jì)時(shí)器,達(dá)到固定時(shí)長(zhǎng)就停掉,返回一個(gè)fail,這里我就不貼了,有需要的可以下載我源碼看

4.4.被掃后

@RequestMapping("/login/{uuid}")
	@ResponseBody
	String login(@PathVariable String uuid){
		
		ScanPool pool = PoolCache.cacheMap.get(uuid);
		
		if(pool == null){
			return "timeout,scan fail";
		}
		
		pool.scanSuccess();
		
		return "scan success";
	}

ok,結(jié)束

源碼下載地址:http://xz.jb51.net:81/201905/yuanma/springboot(jb51.net).rar

以上所述是小編給大家介紹的java掃二維碼自動(dòng)跳轉(zhuǎn)詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Java @Pointcut注解表達(dá)式案例詳解

    Java @Pointcut注解表達(dá)式案例詳解

    這篇文章主要介紹了Java @Pointcut注解表達(dá)式案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • MyBatis實(shí)現(xiàn)動(dòng)態(tài)SQL的方法

    MyBatis實(shí)現(xiàn)動(dòng)態(tài)SQL的方法

    動(dòng)態(tài)SQL是MyBatis強(qiáng)大特性之一,極大的簡(jiǎn)化我們拼裝SQL的操作,本文主要介紹了MyBatis實(shí)現(xiàn)動(dòng)態(tài)SQL的方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • springboot實(shí)現(xiàn)瀏覽器截屏并添加文字

    springboot實(shí)現(xiàn)瀏覽器截屏并添加文字

    大家好,本篇文章主要講的是springboot實(shí)現(xiàn)瀏覽器截屏并添加文字,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • IDEA實(shí)用好用插件推薦及使用方法教程詳解(必看)

    IDEA實(shí)用好用插件推薦及使用方法教程詳解(必看)

    這篇文章主要介紹了IDEA實(shí)用好用插件推薦及使用方法教程,本文通過(guò)實(shí)例截圖相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • maven 在執(zhí)行package,install,deploy時(shí)使用clean與不使用clean的不同之處

    maven 在執(zhí)行package,install,deploy時(shí)使用clean與不使用clean的不同之處

    有時(shí)候用mvn install后,新改的內(nèi)容不生效,一定要后來(lái)使用mvn clean install 才生效,由于之前沒(méi)有做記錄,以及記不清是什么情況下才會(huì)出現(xiàn)的問(wèn)題,于是想看看clean和不clean的區(qū)別,感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • Java序列化和反序列化_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java序列化和反序列化_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    把對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化,把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化。接下來(lái)通過(guò)本文給大家介紹Java序列化和反序列化及主要的兩種用途,感興趣的的友參考下吧
    2017-05-05
  • Java private修飾符失效的原因

    Java private修飾符失效的原因

    在Java編程里,使用private關(guān)鍵字修飾了一個(gè)成員,只有成員內(nèi)部可以訪問(wèn),其余成員都不可訪問(wèn),今天說(shuō)明一下private功能失效的問(wèn)題。
    2020-10-10
  • mybatis注解與xml常用語(yǔ)句匯總

    mybatis注解與xml常用語(yǔ)句匯總

    最近一直在用mybatis,由于需要使用到了動(dòng)態(tài)sql,遇到了一些問(wèn)題,現(xiàn)在來(lái)總結(jié)一下,經(jīng)驗(yàn)教訓(xùn)。下面這篇文章主要給大家總結(jié)介紹了mybatis注解與xml常用語(yǔ)句的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09
  • Java如何使用JWT實(shí)現(xiàn)Token認(rèn)證機(jī)制

    Java如何使用JWT實(shí)現(xiàn)Token認(rèn)證機(jī)制

    JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)上安全地傳輸信息的簡(jiǎn)潔的、URL 安全的表示方法,本文主要介紹了Java如何使用JWT實(shí)現(xiàn)Token認(rèn)證機(jī)制,需要的可以參考下
    2024-10-10
  • java自定義ClassLoader加載指定的class文件操作

    java自定義ClassLoader加載指定的class文件操作

    這篇文章主要介紹了java自定義ClassLoader加載指定的class文件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02

最新評(píng)論

虎林市| 涡阳县| 古交市| 永德县| 浠水县| 京山县| 淮北市| 彰化县| 山东| 张家口市| 茌平县| 香港| 乃东县| 治县。| 岢岚县| 连南| 汶上县| 桦川县| 五常市| 仁布县| 自治县| 喀什市| 晋江市| 贞丰县| 平遥县| 绍兴县| 浏阳市| 盘锦市| 南江县| 西安市| 左权县| 无极县| 长丰县| 祁连县| 祁东县| 洛扎县| 格尔木市| 嘉义市| 麦盖提县| 德令哈市| 思南县|