中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中如何實現掃二維碼自動跳轉

發布時間:2021-07-19 10:35:51 來源:億速云 閱讀:978 作者:小新 欄目:編程語言

小編給大家分享一下java中如何實現掃二維碼自動跳轉,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

重復理論步驟:

1、進入網站-生成UUID

2、跳轉到二維碼頁面(二維碼包含UUID)

3、二維碼頁面寫一個js,自動請求服務器查詢二維碼是否被掃

4、服務器收到請求,查詢,如果還沒被掃,進入等待,先不返回結果

5、一旦被掃,立即返回結果,頁面js收到響應,做后續處理

OK,步驟是這樣的沒錯,不過有一點缺點,步驟3中如果請求超時怎么辦。

這個微信web登錄有示例,服務器被請求后,持續等待25秒左右,然后結束請求,js端重新發起請求,就這樣25秒為周期,不停發起長鏈接請求。

看下微信web的長連接

java中如何實現掃二維碼自動跳轉

java中如何實現掃二維碼自動跳轉

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

1、生成UUID

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

2、生成二維碼,頁面部分

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

頁面js:

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

3、頁面js自動請求服務器查詢是否被掃

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

4、服務器收到請求,這里服務器端的事情還是蠻多的,分解一下

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

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

3、查詢是否被掃,對應$.post("/pool", { uuid : "${uuid}"}......,這時候有一個等待的功能(緩存中的對象來控制,這個對象的鍵就是UUID)

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

5、上面說了好多次對象了,對的,都是同一個,接著貼代碼了

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); //容錯率
			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;
	}

看到對象ScanPool沒有,這就是那個對象,PoolCache是那個緩存,既然說了,先貼這兩個類。

ScanPool.java

public class ScanPool
{
 
	//創建時間
	private Long createTime = System.currentTimeMillis();
	
	//登錄狀態
	private boolean scanFlag = false;
	
	public boolean isScan(){
		return scanFlag;
	}
	
	public void setScan(boolean scanFlag){
		this.scanFlag = scanFlag;
	}
	
	/**
	 * 獲取掃描狀態,如果還沒有掃描,則等待固定秒數
	 * @param wiatSecond 需要等待的秒數
	 * @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;
	}
	
	/**
	 * 掃碼之后設置掃碼狀態
	 */
	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
{
	//緩存超時時間 10分鐘
	private static Long timeOutSecond = 600L;
	
	//每半小時清理一次緩存
	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("檢測["+uuid+"]是否登錄");
		
		ScanPool pool = PoolCache.cacheMap.get(uuid);
		
		if(pool == null){
			return "timeout";
		}
		
		//使用計時器,固定時間后不再等待掃描結果--防止頁面訪問超時
		new Thread(new ScanCounter(uuid)).start();
		
		boolean scanFlag = pool.getScanStatus();
		if(scanFlag){
			return "success";
		}else{
			return "fail";
		}
	}

這里看到,有一個防止頁面請求超時的,是寫了一個計時器,達到固定時長就停掉,返回一個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,結束

以上是“java中如何實現掃二維碼自動跳轉”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高青县| 锦州市| 运城市| 巫山县| 乃东县| 高清| 米林县| 兴义市| 汶上县| 新沂市| 清水河县| 江达县| 新河县| 潮州市| 凉山| 邹平县| 天祝| 思南县| 通化市| 郸城县| 汨罗市| 革吉县| 洛浦县| 迭部县| 黔南| 泸州市| 周宁县| 岳阳市| 汶上县| 静安区| 高碑店市| 黔东| 盐边县| 邵武市| 凉山| 明溪县| 桐庐县| 同德县| 缙云县| 贞丰县| 道真|