您好,登錄后才能下訂單哦!
小編給大家分享一下java中如何實現掃二維碼自動跳轉,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
重復理論步驟:
1、進入網站-生成UUID
2、跳轉到二維碼頁面(二維碼包含UUID)
3、二維碼頁面寫一個js,自動請求服務器查詢二維碼是否被掃
4、服務器收到請求,查詢,如果還沒被掃,進入等待,先不返回結果
5、一旦被掃,立即返回結果,頁面js收到響應,做后續處理
OK,步驟是這樣的沒錯,不過有一點缺點,步驟3中如果請求超時怎么辦。
這個微信web登錄有示例,服務器被請求后,持續等待25秒左右,然后結束請求,js端重新發起請求,就這樣25秒為周期,不停發起長鏈接請求。
看下微信web的長連接
不說了,貼代碼了,我這里使用的是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中如何實現掃二維碼自動跳轉”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。