最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

一、需求場(chǎng)景

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

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

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

1、 整體流程

三、前端部分

大致流程

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

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

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

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

5、對(duì)數(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() {
			// 頁(yè)面隱藏時(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)目的請(qǐ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('請(qǐng)求失敗:', 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ò)誤以供上層處理
    }
}

請(qǐng)求接口工具類:request.js

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

async getbuffer(url, params = {}) {
		try {
			//await this.checkTokenAndNavigate(); // 在發(fā)送請(qǐng)求前檢查 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ò)誤(例如沒(méi)有 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",
};

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

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

// 如果是開(kāi)發(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í),安全碼、起始時(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);

        // 將二維碼寫(xiě)入字節(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);
    }
}

接口測(cè)試

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)證
接口的暴力請(qǐng)求限流策略(如Guava RateLimiter)
中間人 攻擊全站HTTPS + 數(shù)據(jù)簽名
XSS攻擊前端輸入過(guò)濾 + CSP安全策略

七、總結(jié)

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

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

最佳實(shí)踐建議

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

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

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

相關(guān)文章

  • 如何更優(yōu)雅地獲取spring boot yml中的值

    如何更優(yōu)雅地獲取spring boot yml中的值

    這篇文章主要給大家介紹了關(guān)于如何更優(yōu)雅地獲取spring boot yml中值的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • JAVA String.valueOf()方法的用法說(shuō)明

    JAVA String.valueOf()方法的用法說(shuō)明

    這篇文章主要介紹了JAVA String.valueOf()方法的用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Springboot Druid 自定義加密數(shù)據(jù)庫(kù)密碼的幾種方案

    Springboot Druid 自定義加密數(shù)據(jù)庫(kù)密碼的幾種方案

    這篇文章主要介紹了Springboot Druid 自定義加密數(shù)據(jù)庫(kù)密碼的步驟,幫助大家更好的理解和使用springboot,感興趣的朋友可以了解下
    2020-12-12
  • Java如何生成隨機(jī)數(shù)不了解下嗎

    Java如何生成隨機(jī)數(shù)不了解下嗎

    我們?cè)趯W(xué)習(xí) Java 基礎(chǔ)時(shí)就知道可以生成隨機(jī)數(shù),可以為我們枯燥的學(xué)習(xí)增加那么一丟丟的樂(lè)趣,本文就來(lái)和大家介紹Java生成隨機(jī)數(shù)的常用方法,需要的可以參考下
    2023-08-08
  • Java生成Markdown格式內(nèi)容完整代碼示例

    Java生成Markdown格式內(nèi)容完整代碼示例

    這篇文章主要介紹了將Java對(duì)象數(shù)據(jù)生成為Markdown文本,并提供了一個(gè)MarkdownUtil工具類進(jìn)行處理,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • Java的CollectionUtils工具類詳解

    Java的CollectionUtils工具類詳解

    這篇文章主要介紹了Java的CollectionUtils工具類詳解,CollectionUtils工具類是在apache下的,而不是springframework下的,個(gè)人覺(jué)得在真實(shí)項(xiàng)目中CollectionUtils,可以使你的代碼更加簡(jiǎn)潔和安全,需要的朋友可以參考下
    2023-05-05
  • Java中String類(StringBuffer、StringBuilder)相關(guān)(最新推薦)

    Java中String類(StringBuffer、StringBuilder)相關(guān)(最新推薦)

    Java中的String類是不可變的,存儲(chǔ)在字符串常量池中,提供了多種方法用于操作字符串,為了提高效率,可以使用StringBuilder或StringBuffer,本文介紹Java中String類(StringBuffer、StringBuilder)相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • 與近日火爆的ChatGPT聊Elasticsearch源碼

    與近日火爆的ChatGPT聊Elasticsearch源碼

    這篇文章主要為大家分享了與近日火爆的ChatGPT聊Elasticsearch源碼的話題內(nèi)容,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Java Kafka分區(qū)發(fā)送及消費(fèi)實(shí)戰(zhàn)

    Java Kafka分區(qū)發(fā)送及消費(fèi)實(shí)戰(zhàn)

    本文主要介紹了Kafka分區(qū)發(fā)送及消費(fèi)實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java實(shí)戰(zhàn)員工績(jī)效管理系統(tǒng)的實(shí)現(xiàn)流程

    Java實(shí)戰(zhàn)員工績(jī)效管理系統(tǒng)的實(shí)現(xiàn)流程

    只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+Mysql+Maven+HTML實(shí)現(xiàn)一個(gè)員工績(jī)效管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2022-01-01

最新評(píng)論

镇巴县| 抚松县| 威远县| 慈溪市| 文山县| 扶余县| 河源市| 宣化县| 北辰区| 平定县| 塔河县| 长汀县| 靖边县| 屏山县| 子洲县| 潢川县| 三亚市| 金门县| 门源| 焉耆| 依安县| 武强县| 原阳县| 呼玛县| 梓潼县| 外汇| 盈江县| 普定县| 阳新县| 玛纳斯县| 凌云县| 浦江县| 前郭尔| 景德镇市| 乌拉特中旗| 榆社县| 怀化市| 松桃| 历史| 阜平县| 金华市|