亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

springboot如何通過接口實(shí)現(xiàn)動(dòng)態(tài)二維碼的定時(shí)刷新

 更新時(shí)間:2025年05月27日 08:35:11   作者:古渡藍(lán)按  
這篇文章主要為大家詳細(xì)介紹了springboot如何通過接口實(shí)現(xiàn)動(dòng)態(tài)二維碼的定時(shí)刷新功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

一、需求場景

在Web應(yīng)用中,動(dòng)態(tài)二維碼常用于以下場景:

  • 登錄驗(yàn)證:微信掃碼登錄、APP掃碼授權(quán)
  • 支付場景:支付寶/微信支付碼定時(shí)刷新
  • 票務(wù)系統(tǒng):電子票二維碼防截屏盜用
  • 會(huì)員系統(tǒng):動(dòng)態(tài)會(huì)員碼累計(jì)積分

二、技術(shù)方案設(shè)計(jì)

1、 整體流程

三、前端部分

大致流程

1、請求后端接口(按照現(xiàn)有項(xiàng)目格式即可)

2、后端接口的返回類型定義(byte[])

3、前端接收時(shí)定義響應(yīng)類型(重點(diǎn):responseType: 'arraybuffer')

4、對后端返回?cái)?shù)據(jù)進(jìn)行轉(zhuǎn)化:arrayBufferToBase64

5、對數(shù)據(jù)和標(biāo)簽進(jìn)行綁定

具體實(shí)現(xiàn)

1、獲取后端 二維碼 圖片接口

	import {
		generateMemberCode
	} from '@/api/inter/member-code.js';

data() {
			return {
				codeImg: '',
				timer: null, // 添加定時(shí)器引用,
			}
		},
		onShow() {
			// 立即加載一次
			this.makeMemberCode();

			// 設(shè)置定時(shí)器(注意保存引用)
			this.timer = setInterval(() => {
				this.makeMemberCode();
			}, 30000);
		},
		onHide() {
			// 頁面隱藏時(shí)清除定時(shí)器
			if (this.timer) {
				clearInterval(this.timer);
				this.timer = null;
			}
		},
        methods: {
			async makeMemberCode() {
				const memberId = 1; // 使用假數(shù)據(jù)中的 id
				const memberName = '張三'; // 使用假數(shù)據(jù)中的 nickname
				const params = {
					memberId,
					memberName
				};
				try {
                    // 調(diào)用后端接口(這里可改成符合你項(xiàng)目的請求方式)
					const response = await generateMemberCode(params);
					console.log('完整響應(yīng):', response);

					// 調(diào)試數(shù)據(jù)類型
					console.log('響應(yīng)數(shù)據(jù)類型:', typeof response);

					// 處理二進(jìn)制數(shù)據(jù)(適用于小程序)
					if (typeof response === 'object' && response instanceof ArrayBuffer) {
						const base64 = uni.arrayBufferToBase64(response);
						this.codeImg = `data:image/png;base64,${base64}`;
						console.log('新的 codeImg:', this.codeImg); // 調(diào)試輸出
					} else if (typeof response.data === 'string') {
						this.codeImg = `data:image/png;base64,${response.data}`;
					}
					// 處理URL
					else if (response.data.imageUrl) {
						this.codeImg = response.data.imageUrl;
					}
				} catch (error) {
					console.error('請求失敗:', error);
					uni.showToast({
						title: '會(huì)員碼加載失敗',
						icon: 'none'
					});
				}
			}
        }

上面部分用到的代碼: member-code.js

import { HttpClient } from '@/api/utils/request.js'; // 確保路徑正確
import api from '../../config/api.js'; // 導(dǎo)入 API 配置

const http = new HttpClient(api.base);


/**
 * 獲取后端二維碼
 */
export async function generateMemberCode(params) {
    try {
        const response = await http.getbuffer('/api/wx/generate-qrcode',params);
        console.log('Response:', response);
        return response; // 返回響應(yīng)數(shù)據(jù)
    } catch (error) {
        console.error('Error:', error);
        throw error; // 繼續(xù)拋出錯(cuò)誤以供上層處理
    }
}

請求接口工具類:request.js

class HttpClient {
	constructor(baseURL) {
		this.baseURL = baseURL;
	}

async getbuffer(url, params = {}) {
		try {
			//await this.checkTokenAndNavigate(); // 在發(fā)送請求前檢查 token
			const queryString = this.buildQueryString(params);
			const fullURL = `${this.baseURL}${url}${queryString}`;
	
			return new Promise((resolve, reject) => {
				uni.request({
					url: fullURL,
					method: 'GET',
					header: {
						'Content-Type': 'application/json',
						'X-Auth-Token': `${uni.getStorageSync('token')}` // 如果需要在 header 中發(fā)送 token
					},
					responseType: 'arraybuffer', // 指定響應(yīng)類型為 arraybuffer
					success: (response) => {
						resolve(response.data);
					},
					fail: (error) => {
						console.error('GET request error:', error);
						reject(error);
					}
				});
			});
		} catch (error) {
			// 如果 checkTokenAndNavigate 拋出錯(cuò)誤(例如沒有 token),則這里處理錯(cuò)誤
			return Promise.reject(error);
		}
	}
    buildQueryString(params) {
	  if (!params || Object.keys(params).length === 0) {
	    return '';
	  }
	  return '?' + Object.keys(params)
	    .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
	    .join('&');
	}
}

export {
	HttpClient
};

接口地址Api 配置類:API.js

// 生產(chǎn)環(huán)境
const prod = {
  base: "http://XXXXXX:8099",
};

// 開發(fā)環(huán)境
const dev = {
  base: "http://XXXXXXX:8099",
};

// 默認(rèn)生產(chǎn)環(huán)境
let api = prod;

// 如果是開發(fā)環(huán)境
if (process.env.NODE_ENV === "development") {
  api = dev;
}

// 微信小程序和App的打包方式建議為生產(chǎn)環(huán)境,所以這塊直接條件編譯賦值()
// #ifdef MP-WEIXIN || APP-PLUS
// 這個(gè)直接使用的是 dev 地址
api = dev;
// #endif

export default {
  ...api,
};

2、模板進(jìn)行渲染

	<view class="qrcode d-flex just-content-center align-items-center">
					<image :src="`${codeImg}`" style="width: 350rpx; height: 350rpx;"></image>
				</view>

四、后端部分

具體實(shí)現(xiàn)

1、添加依賴

<!-- ZXing Core and Java SE -->
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>core</artifactId>
        <version>3.4.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId>
        <version>3.4.1</version>
    </dependency>

2、接口實(shí)現(xiàn)controller

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.nio.file.FileSystems;
import java.util.HashMap;
import java.util.Map;

@RestController
public class QRCodeController {

    @GetMapping("/generate-qrcode")
    public ResponseEntity<byte[]> generateQRCode(
            @RequestParam String memberId,
            @RequestParam String memberName) throws WriterException {
        
        // 構(gòu)建二維碼內(nèi)容(內(nèi)容可根據(jù)自己業(yè)務(wù)動(dòng)態(tài)修改)
        // 建議加上唯一標(biāo)識,安全碼、起始時(shí)間、狀態(tài)等,保證二維碼安全性
        String qrContent = "Member ID: " + memberId + ", Member Name: " + memberName;

        // 設(shè)置二維碼參數(shù)
        int width = 300;
        int height = 300;
        String imageFormat = "PNG"; // 圖片格式

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        // 生成二維碼
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(qrContent, BarcodeFormat.QR_CODE, width, height, hints);

        // 將二維碼寫入字節(jié)數(shù)組輸出流
        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, pngOutputStream);

        // 返回二維碼圖片
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_PNG);
        return new ResponseEntity<>(pngOutputStream.toByteArray(), headers, HttpStatus.OK);
    }
}

接口測試

GET http://localhost:8080/generate-qrcode?memberId=12345&memberName=JohnDoe

前端處理后端的數(shù)據(jù)時(shí),在一定要指定相應(yīng)類型:responseType: 'arraybuffer'

五、效果展示

六、安全性設(shè)計(jì)

風(fēng)險(xiǎn)防御方案
二維碼盜用30秒短時(shí)效性 + 單次有效性驗(yàn)證
接口的暴力請求限流策略(如Guava RateLimiter)
中間人 攻擊全站HTTPS + 數(shù)據(jù)簽名
XSS攻擊前端輸入過濾 + CSP安全策略

七、總結(jié)

關(guān)鍵技術(shù)棧

  • 前端定時(shí)器 + 二進(jìn)制流處理
  • 后端二維碼生成 + 狀態(tài)管理
  • 高效的緩存策略

最佳實(shí)踐建議

  • 始終為二維碼添加時(shí)效性和唯一性標(biāo)識
  • 敏感操作需二次確認(rèn)(如掃碼后的授權(quán)確認(rèn))
  • 監(jiān)控二維碼使用率,優(yōu)化生成策略

通過前后端協(xié)作,動(dòng)態(tài)二維碼既能提升用戶體驗(yàn),又能有效保障系統(tǒng)安全性。

以上就是springboot如何通過接口實(shí)現(xiàn)動(dòng)態(tài)二維碼的定時(shí)刷新的詳細(xì)內(nèi)容,更多關(guān)于springboot動(dòng)態(tài)二維碼刷新的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JAVA遍歷一個(gè)文件夾中的所有文件的小例子

    JAVA遍歷一個(gè)文件夾中的所有文件的小例子

    在實(shí)際項(xiàng)目中給定一文件夾,得到這個(gè)文件夾下所有的文件這樣的需求并不是很多,更多的是查找或是刪除某一具體的文件
    2013-10-10
  • Spring Boot中的屬性綁定的實(shí)現(xiàn)

    Spring Boot中的屬性綁定的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Boot中的屬性綁定的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • UniApp?+?SpringBoot?實(shí)現(xiàn)微信支付和退款功能

    UniApp?+?SpringBoot?實(shí)現(xiàn)微信支付和退款功能

    這篇文章主要介紹了UniApp?+?SpringBoot?實(shí)現(xiàn)微信支付和退款功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Java中的ArrayList、LinkedList、HashSet等容器詳解

    Java中的ArrayList、LinkedList、HashSet等容器詳解

    這篇文章主要介紹了Java中的ArrayList、LinkedList、HashSet等容器詳解,集合表示一組對象,稱為其元素,有些集合允許重復(fù)元素,而另一些則不允許,有些是有序的,有些是無序的,需要的朋友可以參考下
    2023-08-08
  • 一文帶你掌握J(rèn)ava?SPI的原理和實(shí)踐

    一文帶你掌握J(rèn)ava?SPI的原理和實(shí)踐

    在Java中,我們經(jīng)常會(huì)提到面向接口編程,這樣減少了模塊之間的耦合,更加靈活,Java?SPI?(Service?Provider?Interface)就提供了這樣的機(jī)制,本文就來講講它的原理與具體使用吧
    2023-05-05
  • java編程數(shù)據(jù)類型全面詳解教程新手必入

    java編程數(shù)據(jù)類型全面詳解教程新手必入

    這篇文章主要為大家介紹了java編程數(shù)據(jù)類型全面詳解教程,強(qiáng)烈推薦新手入,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • Java類和對象的設(shè)計(jì)原理

    Java類和對象的設(shè)計(jì)原理

    這篇文章主要介紹了Java類和對象的設(shè)計(jì)原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • Arrays.sort(arr)是什么排序及代碼邏輯

    Arrays.sort(arr)是什么排序及代碼邏輯

    在學(xué)習(xí)過程中觀察到Arrays.sort(arr)算法可以直接進(jìn)行排序,但不清楚底層的代碼邏輯是什么樣子,今天通過本文給大家介紹下Arrays.sort(arr)是什么排序,感興趣的朋友一起看看吧
    2022-02-02
  • 淺談SpringCloud之Ribbon詳解

    淺談SpringCloud之Ribbon詳解

    這篇文章主要介紹了淺談SpringCloud之Ribbon,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)SpringCloud的小伙伴們有很大的幫助,需要的朋友可以參考下
    2021-05-05
  • Java中fail-fast和fail-safe的使用

    Java中fail-fast和fail-safe的使用

    fail-fast和fail-safe是兩種不同的迭代器行為,特別是在遍歷集合時(shí)遇到并發(fā)修改的情況,本文主要介紹了Java中fail-fast和fail-safe的使用,感興趣的可以了解一下
    2024-08-08

最新評論