扫二维码自动跳转【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,结束

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

以上所述是小编给大家介绍的java扫二维码自动跳转详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Java Web实现session过期后自动跳转到登陆页功能【基于过滤器】

    本文实例讲述了Java Web实现session过期后自动跳转到登陆页功能.分享给大家供大家参考,具体如下: 通过过滤器的方式实现 session过期后自动跳转到登陆页 过滤器只在与servlet规范2.3版兼容的服务器上有作用.如果你的Web应用需要支持旧版服务器,就不能使用过滤器. 一.建立基本过滤器 建立一个过滤器涉及下列五个步骤: 1)建立一个实现Filter接口的类SessionFilter .这个类需要三个方法,分别是:doFilter.init和destroy.doFilter方法

  • java Struts2 在拦截器里的跳转问题

    复制代码 代码如下: java.lang.IllegalStateException at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:405) at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:725) at org.apache.struts2.dispatcher.Dispatcher.servi

  • java实现301跳转和重定向的方法

    java301跳转和重定向 复制代码 代码如下: response.setStatus(301); response.setHeader("Location","http://www.baidu.com"); //---分割线--- response.sendRedirect("http://baidu.com"); 以上就是本文的全部内容了,希望大家能够喜欢.

  • 详解JAVA后端实现统一扫码支付:微信篇

    最近做完了一个项目,正好没事做,产品经理就给我安排了一个任务. 做一个像收钱吧这样可以统一扫码收钱的功能. 一开始并不知道是怎么实现的,咨询了好几个朋友,才知道大概的业务流程:先是开一个网页用来判断支付平台,是微信还是支付宝,判断过后就好办了,直接照搬微信支付和支付宝的官方文档.不过微信的文档感觉有点坑,得多花点心思. 现在讲讲怎么实现微信支付网页支付,也就是公众号支付: 1.判断支付平台,在判断是微信平台时,必须使用window.location打开网页,使用其他方法在IOS版微信无法打开网页

  • java实现二维码扫码授权登陆

    假设现在有2个设备,A设备需要扫码授权登陆,B设备是已经登陆了的设备.然后实现如下: 一.A设备生成生成二维码: A设备向服务器请求getLoginCode接口,这个接口根据请求的sessionId进行base64或其他加密方式进行加密,然后以此作为二维码的值,并将这个loginCode写到redis里,设置5分钟过期.然后将这个loginCode返回给A设备,A设备以此值来生成登陆的二维码. 二.B设备扫码授权 B设备来扫A设备的二维码的时候,携带二维码的值,请求授权登陆的接口scanConf

  • java实现网站微信扫码支付

    一.网站微信扫码支付开发并没有现成的java示例,总结一下自己微信扫码支付心得 二.首先去微信公众平台申请账户 https://mp.weixin.qq.com ** 三.账户开通.开发者认证之后就可以进行微信支付开发了 1.微信统一下单接口调用获取预支付id,以及生成二维码所需的codeUrl /** * 保存订单,并生成二维码所需的codeUrl * * @param request * @param response * @param notifyURLBuf * @param order

  • Java微信支付之公众号支付、扫码支付实例

    微信支付现在已经变得越来越流行了,随之也出现了很多以可以快速接入微信支付为噱头的产品,不过方便之余也使得我们做东西慢慢依赖第三方,丧失了独立思考的能力,这次打算分享下我之前开发过的微信支付. 一 .H5公众号支付 要点:正确获取openId以及统一下单接口,正确处理支付结果通知,正确配置支付授权目录 H5的支付方式是使用较为广泛的方式,这种支付方式主要用于微信内自定义菜单的网页,依赖手机上安装的微信客户端,高版本的微信才支持微信支付,下面按我的流程注意说明 1  编写用于支付的页面,由于是测试用

  • java servlet 几种页面跳转的方法

    Servlet: 当然,在servlet中,一般跳转都发生在doGet, doPost等方法里面. 1) redirect 方式 response.sendRedirect("/a.jsp"); 页面的路径是相对路径.sendRedirect可以将页面跳转到任何页面,不一定局限于本web应用中,如: response.sendRedirect("http://www.jb51.net"); 跳转后浏览器地址栏变化. 这种方式要传值出去的话,只能在url中带param

  • java实现在SSM下使用支付宝扫码支付功能

    本文实例为大家分享了java使用支付宝扫码支付的具体代码,供大家参考,具体内容如下 准备工作 首先开通支付宝沙箱的测试账号,里面会有消费者账户和收款方账户 手机扫码下载手机端app 基础配置 所需jar包 AlipayConfig package com.alipay.config; import java.io.FileWriter; import java.io.IOException; import java.util.ResourceBundle; /* * *类名:AlipayConf

  • 扫二维码自动跳转【java】详解

    这个帖子网上很多了,但是都是讲理论知识,我呢,喜欢搞代码.既然搞完了,就贴出来备忘一下,也可以分享一下. 重复理论步骤: 1.进入网站-生成UUID 2.跳转到二维码页面(二维码包含UUID) 3.二维码页面写一个js,自动请求服务器查询二维码是否被扫 4.服务器收到请求,查询,如果还没被扫,进入等待,先不返回结果 5.一旦被扫,立即返回结果,页面js收到响应,做后续处理 OK,步骤是这样的没错,不过有一点缺点,步骤3中如果请求超时怎么办. 这个微信web登录有示例,服务器被请求后,持续等待25

  • Python识别二维码的两种方法详解

    目录 前言 pyzbar + PIL cv2 前言 最近在搜寻资料时,发现了一则10年前的新闻:二维码将成线上线下关键入口.从今天的移动互联网来看,支付收款码/健康码等等与我们息息相关,二维码确实成为了我们生活中不可或缺的一部分. 在学习Python处理二维码的过程中,我们看到的大多是“用python生成酷炫二维码”.“用Python制作动图二维码”之类的文章.而关于使用Python批量识别二维码的教程,并不多见.所以今天我会给大家分享两种批量识别二维码的Python技巧! pyzbar + P

  • iOS和Android用同一个二维码实现跳转下载链接的方法

    前言 最近一个项目需要iOS和安卓使用一个二维码,让扫描的机器自己识别操作系统实现跳转到相应的下载链接.比如iPhone用微信进行扫描就让他跳转appStore的下载页面,安卓机器使用微信扫描就直接跳浏览器下载.但是这二维码还有一个需求就是,用户已经下载了这个app,当用户打开app进入到注册页面时,再次扫描这个二维码时,自动填写邀请码进行注册.那么该如何实现,细节就不说了,直接上代码. 使用js实现,其实代码非常简单. 使用时直接拷贝代码,改掉相应的链接就好. PS:该链接在微信环境打开时还是

  • 超简单Android集成华为HMS Scankit 扫码SDK实现扫一扫二维码

    前言 最近要做一个停车场扫码收费的app,在网上搜了一圈,首先接触到了ZXing,上手试了下,集成过程不复杂,但是感觉效果欠佳,比如距离稍微远点儿就扫不出来了,另外角度对的不好,反光或者光线比较暗的时候,成功率也比较低,集成好给我们老大看了下,感觉不是很满意.最近偶尔看到了华为一个发布会里面有介绍扫码功能,稍微研究了下,居然是一款免费扫码神器,官方称之为Scan Kit,号称还同时支持Android和iOS,半信半疑上手搞了一把发现效果还真不错!测了下发现对于一些有反光,污损,形变,超远距离的场

  • php 解决扫描二维码下载跳转问题

    php 解决扫描二维码下载跳转问题 首先我们指定一个url,比如 http://it.lovepet.vip 用这个地址生成二维码,二维码的生成方式有很多种,到网上搜搜就知道. 我们可以新建一个index.php放在改网站目录下.编辑index.php加入 $agent=strtolower($agent=strtolower(_SERVER['HTTP_USER_AGENT']); $iphone=(strpos(iphone=(strpos($agent, 'iphone')) ? true

  • Flutter实现扫二维码功能

    本文实例为大家分享了Flutter实现扫二维码功能的具体代码,供大家参考,具体内容如下 首先在pubspec.yaml中添加: dependencies:   qrscan: ^0.3.2   event_bus: ^2.0.0 在androd清单文件中加入以下权限: <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="andr

  • Java数据结构实现二维数组与稀疏数组转换详解

    基本介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: ①记录数组一共有几行几列,有多少个不同的值(0除外). ②把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模. 二维数组转稀疏数组: ①遍历原始的二维数组,得到有效数据的个数 sum(除0外不同值) ②根据 sum 创建稀疏数组 sparseArr int[sum+1][3] ③将二维数组的有效数据数据存入到稀疏数组 (稀疏数组的第一行,三列分别记录二维数组

  • 对python实现二维函数高次拟合的示例详解

    在参加"数据挖掘"比赛中遇到了关于函数高次拟合的问题,然后就整理了一下源码,以便后期的学习与改进. 在本次"数据挖掘"比赛中感觉收获最大的还是对于神经网络的认识,在接近一周的时间里,研究了进40种神经网络模型,虽然在持续一周的挖掘比赛把自己折磨的惨不忍睹,但是收获颇丰.现在想想也挺欣慰自己在这段时间里接受新知识的能力.关于神经网络方面的理解会在后续博文中补充(刚提交完论文,还没来得及整理),先分享一下高次拟合方面的知识. # coding=utf-8 import

  • 基于python 二维数组及画图的实例详解

    1.二维数组取值 注:不管是二维数组,还是一维数组,数组里的数据类型要一模一样,即若是数值型,全为数值型 #二维数组 import numpy as np list1=[[1.73,1.68,1.71,1.89,1.78], [54.4,59.2,63.6,88.4,68.7]] list3=[1.73,1.68,1.71,1.89,1.78] list4=[54.4,59.2,63.6,88.4,68.7] list5=np.array([1.73,1.68,1.71,1.89,1.78])

  • python中读入二维csv格式的表格方法详解(以元组/列表形式表示)

    如何去读取一个没有表头的二维csv文件(如下图所示)? 并以元组的形式表现数据: ((1.0, 0.0, 3.0, 180.0), (2.0, 0.0, 2.0, 180.0), (3.0, 0.0, 1.0, 180.0), (4.0, 0.0, 0.0, 180.0), (5.0, 0.0, 3.0, 178.0)) 方法一,使用python内建的数据处理库: #python自带的库 rows = open('allnodes.csv','r',encoding='utf-8').readl

随机推荐