这个帖子网上很多了,但是都是讲理论知识,我呢,喜欢搞代码。既然搞完了,就贴出来备忘一下,也可以分享一下。

重复理论步骤:

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}")@ResponseBodyString 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 blocke.printStackTrace();} catch (IOException e){// TODO Auto-generated catch blocke.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 blocke.printStackTrace();}return false;}/*** 扫码之后设置扫码状态*/public synchronized void scanSuccess(){try{setScan(true);this.notifyAll();} catch (Exception e){// TODO Auto-generated catch blocke.printStackTrace();}}public synchronized void notifyPool(){try{this.notifyAll();} catch (Exception e){// TODO Auto-generated catch blocke.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(){@Overridepublic void run(){// TODO Auto-generated method stubwhile (true){try{Thread.sleep(cleanIntervalSecond*1000);} catch (InterruptedException e){// TODO Auto-generated catch blocke.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")@ResponseBodyString 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}")@ResponseBodyString login(@PathVariable String uuid){ScanPool pool = PoolCache.cacheMap.get(uuid);if(pool == null){return "timeout,scan fail";}pool.scanSuccess();return "scan success";}

ok,结束

对了,附上地址,可以直接运行。项目下下来放入ide,直接run App.java

git:https://code.csdn.net/xiasihua88/spring-boot.git

download:http://download.csdn.net/detail/xiasihua88/9779057



扫二维码自动跳转【java】相关推荐

  1. ios app 解决微信扫二维码不能跳转问题

    ios app 解决微信扫二维码不能跳转问题 参考文章: (1)ios app 解决微信扫二维码不能跳转问题 (2)https://www.cnblogs.com/wuxian/p/4618374.h ...

  2. 一码多用:扫描一个二维码自动跳转支付宝/微信小程序、安卓/iosAPP

    随着支付宝,微信小程序的慢慢崛起,现在很多公司同一款程序都开发了四个版本.支付宝/微信小程序.安卓/iosAPP.但是随着程序的增加,引导用户使用就成了问题.比如,一家店门口如何贴一张二维码.实现用户 ...

  3. 如何实现扫描二维码自动跳转到网页

    二维码在我们的生活中随处可见,比如扫码付款,扫描进入小程序,扫码关注等等.二维码可以存储各种信息,主要包括网址.名片.文本信息.特定代码等.今天就以QR code二维码为例,教大家使用条码软件生成二维 ...

  4. iOS和Android使用同一个二维码自动跳转不同下载页面链接(附生成二维码地址方法)

    一.使用场景 开发了一款App,包括iOS及Android版,到了推广阶段,准备生成二维码让用户扫码下载,那这个二维码该怎么生成?iOS及Andorid各自生成一个二维码让用户区分下载?当然这种方式是 ...

  5. 366API如何做到微信扫二维码无跳转调用外部浏览器页面

    源码使用场景: 1.用来实现微信自动跳转外部浏览器下载app 2.用来实现微信内打开网页链接自动跳转浏览器访问指定页面 3.防止网页链接由于被微信拦截,导致用户无法正常在微信内打开 源码说明: 适用安 ...

  6. PHP扫二维码直接跳地址

    前端: <style> div.file{display:inline-block;width:400px;height:400px;line-height:200px;position: ...

  7. H5+微信公众号扫二维码页面跳转功能 vue实现

    后端生成二维码,二维码里面带有参数 前端在默认页面的声明周期created方法,接收二维码的参数,location.href能获取到二维码携带的参数 有两种情况,一是二维码已失效,不带任何参数:另一种 ...

  8. 微信扫描二维码自动跳转到app下载页面(安卓跳转默认浏览器 苹果跳转苹果商店App Store)

    来源分析 商业分析在微信的使用人数已经高居各通讯APP的榜首的同时,微信成为了我国移动流量最大的平台之一.在次趋势的引导下,很多的商家.体户便抓住了这一机遇,利用微信这个渠道来做产品的推广.以及营销方 ...

  9. java生成二维码扫描跳转到指定的路径URL

    java生成二维码扫描跳转到指定的路径URL 导入依赖 <dependency><groupId>com.google.zxing</groupId><art ...

最新文章

  1. ubuntu中使用apt命令安装ipython失败解决方案
  2. C++知识点4——vector与string简述
  3. OpenFlow Switch — 1.3 规范
  4. Openstack组件实现原理 — Glance架构(V1/V2)
  5. MFC中添加自己定义的消息
  6. HOWTO:如何修改InstallShield的运行环境
  7. 0414-复利计算再升级
  8. 图像检索从入门到进阶
  9. mysql到底可不可以使用join_《Mysql 到底可不可以使用 Join ?》
  10. onvif协议之云台控制
  11. linux管理进程的数据结构,Linux 进程运行的各项指标的监测和一些管理命令的应用...
  12. 量化交易(QuantitativeTrading)
  13. 2022年成都初级审计师考试测试题及答案
  14. mongo按季度统计_三季度国内纯碱市场总结及四季度分析
  15. 一个程序员的成长之路
  16. 大数据要学javaweb吗_大数据运维需要学Java吗?
  17. python读mongodb很慢_Python3.5+Mongodb+Flask Web实战坑点小结【Dog Plus】
  18. mysql查询最近7天的数据,没有数据自动补0
  19. 申宝投资-市场行情整体比较差
  20. 浮动的简介——CSS

热门文章

  1. 最近公共祖先-三(RMQ-ST)
  2. [跨域]前端解决跨域问题
  3. 【upload靶场17-21】二次渲染、条件竞争、黑白名单绕过
  4. 一文读懂常用气体传感器的分类与原理
  5. 饥荒的服务器未响应,饥荒的专业服务器为什么修改了mod的设置之后游戏里没反应?...
  6. 浪潮存储忘记密码、找回密码、重置密码方法,不知道登录地址、管理地址查询方法。适用于AS2150G2、AS2200G2、AS2600G2、AS5300G2、AS5500G2
  7. python+selenium爬取智联招聘信息
  8. 电竞显示器什么牌子好?这三款才是我的菜!
  9. 到底什么是Upnp?[转载]
  10. xlrd API中文文档