扫二维码自动跳转【java】

4 篇文章 0 订阅
3 篇文章 0 订阅


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


重复理论步骤:

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,结束


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

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

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


       



  • 14
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Java二维码跳转可以通过使用Zxing库来实现。Zxing库是Google提供的用于处理二维码的开源库,使用Zxing库可以将二维码描并解码,然后将解码后的结果用于跳转到指定的网页或应用。 首先,需要在Java代码中导入Zxing库以便使用。接着,需要使用描器来二维码并将解码结果存储在一个字符串变量中。代码如下: ``` import com.google.zxing.BarcodeFormat; import com.google.zxing.MultiFormatReader; import com.google.zxing.Result; import com.google.zxing.common.BitMatrix; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.qrcode.QRCodeReader; import com.google.zxing.qrcode.QRCodeWriter; public class QRCodeScanner { public static void main(String[] args) throws Exception { QRCodeReader reader = new QRCodeReader(); MultiFormatReader multiFormatReader = new MultiFormatReader(); String filePath = "path/to/your/qr/code.png"; File qrCodeImgFile = new File(filePath); BufferedImage bufferedImage = ImageIO.read(qrCodeImgFile); LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result = reader.decode(bitmap); String content = result.getText(); System.out.print(content); // use the content to open a website or an app } } ``` 此时,通过解码结果content,可在Java中使用content来调用浏览器打开相应的链接,或调用应用程序打开相应的页面。例如: ``` if (Desktop.isDesktopSupported()) { Desktop.getDesktop().browse(new URI(content)); } else { Runtime runtime = Runtime.getRuntime(); runtime.exec("xdg-open " + content); } ``` 以上就是在Java二维码跳转的实现方法,可以根据具体需求进行相应的修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值