当前位置: 首页 > article >正文

vue3 前端路由权限控制与字典数据缓存实践(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
  • 3. 实战

前言

🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF

从实战中出发:

在这里插入图片描述

1. 基本知识

Vue3 和 Java 通信时如何进行字典数据管理

需要了解字典数据的结构。通常,字典数据包含一个键和一个值,有时候还有一些额外的属性,比如颜色类型或 CSS 类,这些在前端展示时可能会用到

库来发送 HTTP 请求到后端,获取这些字典数据。

需要分析如何在前端存储和管理这些字典数据。Pinia 是一个推荐的 Vue
通过 Pinia,可以定义一个字典 store,用来存储所有获取到的字典数据。这样,所有组件都可以方便地访问这些数据,而不需要每次都通过 API 获取.另外,前端缓存也是一个重要的考虑因素。由于字典数据通常是静态的或变化不大,可以在前端缓存这些数据,减少对后端的请求次数,提高应用的响应速度。Vue 的hooks,比如 useCache

如何在路由和权限控制中使用这些字典数据

在用户登录后,前端需要获取字典数据以完成菜单加载和路由动态生成。这里需要与 Vue Router 结合,根据字典数据生成对应的路由配置,确保用户只能访问其权限范围内的功能。还需要处理字典数据的更新和缓存的失效。如果字典数据有更新,前端需要有一个机制来刷新缓存,确保用户使用的是最新的数据。这可能涉及到设置缓存的有效期,或者在有更新时手动清除缓存并重新获取数据

字典数据管理是一个重要的组成部分,字典数据通常包括各种下拉列表、状态标识等,用于在页面中展示和交互

特别是当使用 Vue3 与 Java 后端进行通信时,字典数据的获取、存储、管理和reload都成为关键点

  1. 字典数据通常包括以下几个要素:
  • 字典类型(dictType):表示字典的分类,如用户状态、订单状态等
  • 字典值(dictValue):具体的一个字典项,包含 value 和 label,有时还包括额外属性如颜色或 CSS 类
  • 其他属性:根据业务需求,可能还包括颜色类型、排序顺序等
interface DictDataVO {dictType: string;value: string;label: string;colorType?: string;cssClass?: string;
}

后端会提供一个获取字典数据的接口,如:GET /api/system/dict/simple

返回的数据格式如下:

[{"dictType": "user_status","value": "0","label": "正常"},{"dictType": "user_status","value": "1","label": "禁用"},// 其他字典项
]
  1. 使用 Pinia 进行字典数据的状态管理,Pinia 是 Vue3 推荐的状态管理库,适合管理全局状态,如字典数据
    具体定义的Store:
export const useDictStore = defineStore('dict', {state: () => ({dictMap: new Map<string, any>(),isSetDict: false}),getters: {getDictMap: (state) => state.dictMap,getIsSetDict: (state) => state.isSetDict},actions: {async setDictMap() {// 具体逻辑稍后分析},getDictByType(type: string) {return this.dictMap.get(type) || [];}}
});

后续只需要初始化对应的Store即可:

const dictStore = useDictStore();
dictStore.setDictMap();
  1. 前端缓存可以减少对后端的请求,提高响应速度。可以存储在 sessionStorage 或 localStorage 中

使用自定义缓存钩子:

import { CACHE_KEY } from '@/hooks/web/useCache';const { wsCache } = useCache('sessionStorage');// 存储字典数据
wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 });// 获取字典数据
const cachedDict = wsCache.get(CACHE_KEY.DICT_CACHE);
  1. 字典数据的获取与初始化

在用户登录后,前端需要获取字典数据并存储到 Pinia 和缓存中

逻辑步骤:

检查缓存:首先尝试从缓存中获取字典数据,如果存在且未过期,直接使用
从后端获取:如果缓存不存在或过期,发送请求到后端获取最新数据
存储到 Pinia 和缓存:将获取到的字典数据存储到 Pinia 和 SessionStorage 中
动态生成路由(可选):根据字典数据动态加载菜单和路由,确保用户只能访问权限内的功能

主要的步骤如下:

async function initDictData() {const dictStore = useDictStore();if (dictStore.isSetDict) return;// 从缓存获取const cachedDict = wsCache.get(CACHE_KEY.DICT_CACHE);if (cachedDict) {dictStore.dictMap = cachedDict;dictStore.isSetDict = true;return;}// 从后端获取try {const response = await getSimpleDictDataList();const dictDataMap = new Map<string, any>();response.forEach((dictData: DictDataVO) => {if (!dictDataMap.has(dictData.dictType)) {dictDataMap.set(dictData.dictType, []);}dictDataMap.get(dictData.dictType)?.push({value: dictData.value,label: dictData.label,colorType: dictData.colorType,cssClass: dictData.cssClass});});// 存储到 Pinia 和缓存dictStore.dictMap = dictDataMap;dictStore.isSetDict = true;wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 });} catch (error) {console.error('Failed to fetch dictionary data:', error);}
}
  1. 在组件中使用字典数据

在需要使用字典数据的组件中,可以轻松访问 Pinia 存储的字典数据

<template><div><label>用户状态:</label><select v-model="selectedStatus"><option v-for="(item, index) in dictStatus" :key="index" :value="item.value">{{ item.label }}</option></select></div>
</template><script setup lang="ts">
const dictStore = useDictStore();
const dictStatus = dictStore.getDictByType('user_status');
const selectedStatus = ref('0');
</script>
``6. 字典数据的更新与缓存失效
为确保字典数据的一致性,需要处理缓存的更新和失效```js
async function refreshDict() {const dictStore = useDictStore();// 清除缓存wsCache.delete(CACHE_KEY.DICT_CACHE);// 重新加载字典数据await dictStore.setDictMap();
}

2. Demo

以下主要是围绕第三章的实战中的Demo,提供的思路

前端与后端通信:使用 Vue3 和 Axion 发送 HTTP 请求到 Java 后端,获取字典数据
状态管理:使用 Pinia 管理字典数据,确保全局状态的唯一性和一致性
前端缓存:通过自定义缓存钩子,将字典数据存储在 sessionStorage 中,减少对后端的请求
组件化开发:创建可复用的字典选择组件,提升代码的可维护性和扩展性
动态数据加载:在应用初始化时加载字典数据,支持动态生成路由和菜单

项目结构:

src/
├── api/
│   └── dict.ts         # 后端 API 接口声明
├── hooks/
│   └── web/
│       └── useCache.ts # 缓存钩子
├── store/
│   └── modules/
│       └── dict.ts     # Pinia Store 定义
├── components/
│   └── DictSelect.vue  # 字典选择组件
└── main.ts             # 应用入口

定义Api接口:

// src/api/dict.ts
export interface DictDataVO {dictType: string;value: string;label: string;colorType?: string;cssClass?: string;
}export async function getSimpleDictDataList(): Promise<DictDataVO[]> {return await request({url: '/api/system/dict/simple',method: 'GET'});
}
  1. 创建字典状态管理 Store:
// src/store/modules/dict.ts
import { defineStore } from 'pinia';
import { CACHE_KEY, useCache } from '@/hooks/web/useCache';const { wsCache } = useCache('sessionStorage');
import { getSimpleDictDataList } from '@/api/dict';export interface DictState {dictMap: Map<string, any>;isSetDict: boolean;
}export const useDictStore = defineStore('dict', {state: () => ({dictMap: new Map<string, any>(),isSetDict: false}),getters: {getDictMap: state => state.dictMap,getIsSetDict: state => state.isSetDict},actions: {async setDictMap() {if (this.isSetDict) return;const cachedDict = wsCache.get(CACHE_KEY.DICT_CACHE);if (cachedDict) {this.dictMap = cachedDict;this.isSetDict = true;return;}try {const response = await getSimpleDictDataList();const dictDataMap = new Map<string, any>();response.forEach(dictData => {if (!dictDataMap.has(dictData.dictType)) {dictDataMap.set(dictData.dictType, []);}dictDataMap.get(dictData.dictType)?.push({value: dictData.value,label: dictData.label,colorType: dictData.colorType,cssClass: dictData.cssClass});});this.dictMap = dictDataMap;this.isSetDict = true;wsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 });} catch (error) {console.error('Failed to fetch dictionary data:', error);}},getDictByType(type: string) {return this.dictMap.get(type) || [];}}
});
  1. 创建字典选择组件:
<!-- src/components/DictSelect.vue -->
<template><div class="dict-select"><label>{{ label }}</label><select v-model="selectedValue" @change="handleChange"><option v-for="(item, index) in dictOptions" :key="index" :value="item.value">{{ item.label }}</option></select></div>
</template><script setup lang="ts">
import { useDictStore } from '@/store/modules/dict';interface DictSelectProps {dictType: string;label?: string;modelValue?: string;
}const props = defineProps<DictSelectProps>();
const emit = defineEmits(['update:modelValue']);const dictStore = useDictStore();
const dictOptions = dictStore.getDictByType(props.dictType);
const selectedValue = ref(props.modelValue);const handleChange = (e: Event) => {const value = (e.target as HTMLSelectElement).value;selectedValue.value = value;emit('update:modelValue', value);
};
</script><style scoped>
.dict-select {margin: 10px 0;
}select {padding: 5px;border: 1px solid #ddd;border-radius: 4px;
}
</style>
  1. 在主应用中初始化字典数据:
// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import pinia from './store';
import { useDictStore } from './store/modules/dict';const app = createApp(App).use(router).use(pinia);router.isReady().then(() => {app.mount('#app');// 初始化字典数据const dictStore = useDictStore();dictStore.setDictMap();
});
  1. 使用字典选择组件:
<!-- src/App.vue -->
<template><div id="app"><h1>字典数据管理示例</h1><dict-selectdictType="user_status"label="用户状态"v-model:modelValue="selectedStatus"/></div>
</template><script setup lang="ts">
import DictSelect from './components/DictSelect.vue';const selectedStatus = ref('0');
</script>

3. 实战

以下实战来源:https://gitee.com/zhijiantianya/ruoyi-vue-pro

附上基本的代码注释讲解:

权限管理模块:

import router from './router'
import type { RouteRecordRaw } from 'vue-router'
import { isRelogin } from '@/config/axios/service'
import { getAccessToken } from '@/utils/auth'
import { useTitle } from '@/hooks/web/useTitle'
import { useNProgress } from '@/hooks/web/useNProgress'
import { usePageLoading } from '@/hooks/web/usePageLoading'
import { useDictStoreWithOut } from '@/store/modules/dict'
import { useUserStoreWithOut } from '@/store/modules/user'
import { usePermissionStoreWithOut } from '@/store/modules/permission'// 初始化进度条和页面加载状态
const { start, done } = useNProgress()
const { loadStart, loadDone } = usePageLoading()/*** 解析孔(URL)为路径和参数对象* @param url 输入的完整URL* @returns 包含 basePath 和 paramsObject的对象*/
const parseURL = (url: string | null | undefined
): { basePath: string; paramsObject: { [key: string]: string } } => {// 如果输入为 null 或 undefined,返回空字符串和空对象if (url == null) {return { basePath: '', paramsObject: {} }}// 找到问号的位置,分割基础路径和查询参数const questionMarkIndex = url.indexOf('?')let basePath = urlconst paramsObject: { [key: string]: string } = {}// 如果有查询参数,进行解析if (questionMarkIndex !== -1) {basePath = url.substring(0, questionMarkIndex)const queryString = url.substring(questionMarkIndex + 1)const searchParams = new URLSearchParams(queryString)searchParams.forEach((value, key) => {paramsObject[key] = value})}// 返回解析后的结果return { basePath, paramsObject }
}// 不需要重定向的白名单路径
const whiteList = ['/login','/social-login','/auth-redirect','/bind','/register','/oauthLogin/gitee'
]// 路由加载前的钩子函数
router.beforeEach(async (to, from, next) => {start() // 开始进度条loadStart() // 开始页面加载if (getAccessToken()) { // 检查是否有访问令牌if (to.path === '/login') {// 已经登录的情况下,重定向到主页next({ path: '/' })} else {// 获取字典、用户、权限仓库const dictStore = useDictStoreWithOut()const userStore = useUserStoreWithOut()const permissionStore = usePermissionStoreWithOut()// 检查字典是否加载完成if (!dictStore.getIsSetDict) {await dictStore.setDictMap() // 如果没有加载过,加载字典数据}// 检查用户信息是否加载完成if (!userStore.getIsSetUser) {isRelogin.show = true // 显示重新登录提示await userStore.setUserInfoAction() // 加载用户信息isRelogin.show = false// 加载权限路由await permissionStore.generateRoutes()permissionStore.getAddRouters.forEach((route) => {router.addRoute(route as unknown as RouteRecordRaw) // 动态添加路由})// 处理重定向路径const redirectPath = from.query.redirect || to.pathconst redirect = decodeURIComponent(redirectPath as string)const { basePath, paramsObject: query } = parseURL(redirect)// 根据情况决定是否替换当前路由const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect, query }next(nextData)} else {next() // 用户信息已加载,继续导航}}} else {// 没有登录,检查是否在白名单中if (whiteList.indexOf(to.path) !== -1) {next() // 白名单路径,允许访问} else {// 重定向到登录页,并携带当前路径作为 redirect 参数next(`/login?redirect=${to.fullPath}`)}
})// 路由加载完成后的钩子函数
router.afterEach((to) => {useTitle(to?.meta?.title as string) // 更新页面标题done() // 结束进度条loadDone() // 结束页面加载状态
})

字典管理模块:

import { defineStore } from 'pinia'
import { store } from '../index'
import { DictDataVO } from '@/api/system/dict/types'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache('sessionStorage')
import { getSimpleDictDataList } from '@/api/system/dict/dict.data'/*** 字典值的类型定义*/
export interface DictValueType {value: anylabel: stringcolorType?: stringcssClass?: string
}/*** 字典类型的类型定义*/
export interface DictTypeType {dictType: stringdictValue: DictValueType[]
}/*** 字典状态类型定义*/
export interface DictState {dictMap: Map<string, any>isSetDict: boolean
}/*** 定义字典 Pinia Store*/
export const useDictStore = defineStore('dict', {state: (): DictState => ({dictMap: new Map<string, any>(), // 字典映射表isSetDict: false // 表示字典是否已加载}),getters: {/*** 获取字典映射表,从缓存中读取*/getDictMap(): Recordable {const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)if (dictMap) {this.dictMap = dictMap}return this.dictMap},/*** 检查字典是否已加载*/getIsSetDict(): boolean {return this.isSetDict}},actions: {/*** 设置字典映射表,从缓存或API获取*/async setDictMap() {const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE)if (dictMap) {this.dictMap = dictMapthis.isSetDict = true} else {const res = await getSimpleDictDataList()// 构建字典数据映射const dictDataMap = new Map<string, any>()res.forEach((dictData: DictDataVO) => {// 按照 dictType 分组if (!dictDataMap.has(dictData.dictType)) {dictDataMap.set(dictData.dictType, [])}// 添加字典值dictDataMap.get(dictData.dictType)?.push({value: dictData.value,label: dictData.label,colorType: dictData.colorType,cssClass: dictData.cssClass})})// 更新状态和缓存this.dictMap = dictDataMapthis.isSetDict = truewsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 缓存60秒}},/*** 根据字典类型获取对应的字典值* @param type 字典类型*/getDictByType(type: string) {if (!this.isSetDict) {this.setDictMap() // 如果未加载,先加载字典}return this.dictMap[type]},/*** 重置字典数据,清空缓存并重新加载*/async resetDict() {wsCache.delete(CACHE_KEY.DICT_CACHE) // 清空缓存const res = await getSimpleDictDataList()const dictDataMap = new Map<string, any>()res.forEach((dictData: DictDataVO) => {// 重新构建字典映射if (!dictDataMap.has(dictData.dictType)) {dictDataMap.set(dictData.dictType, [])}dictDataMap.get(dictData.dictType)?.push({value: dictData.value,label: dictData.label,colorType: dictData.colorType,cssClass: dictData.cssClass})})this.dictMap = dictDataMapthis.isSetDict = truewsCache.set(CACHE_KEY.DICT_CACHE, dictDataMap, { exp: 60 }) // 更新缓存}}
})/*** 提供一个不带 store 的字典 Store 实例*/
export const useDictStoreWithOut = () => {return useDictStore(store)
}

相关文章:

vue3 前端路由权限控制与字典数据缓存实践(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 从实战中出发&#xff1a; 1. 基本知识 Vue3 和 Java 通信时如何进行字典数据管理 需要了解字典数据的结构。通常&#x…...

基于javaweb的SpringBoot精美物流管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...

【极光 Orbit·STC8x】05. GPIO库函数驱动LED流动

【极光 OrbitSTC8】05. GPIO库函数驱动LED流动 七律 逐光流转 八灯列阵若星河&#xff0c;状态为舟渡长波。 寄存器中藏玄机&#xff0c;Switch语句定山河。 循环往复如潮涌&#xff0c;步骤变量掌沉浮。 单片机前展锋芒&#xff0c;代码织就光之舞。 摘要 本文基于STC8H8K6…...

DeepSeek进阶应用(二):结合Kimi制作PPT(双AI协作教程)

&#x1f31f;引言&#xff1a; DeepSeek作为国产AI大模型&#xff0c;以强大的逻辑推理和结构化内容生成能力著称&#xff0c;擅长根据用户需求生成PPT大纲或Markdown文本&#xff1b;Kimi的PPT助手则能解析结构化内容并套用模板快速生成美观的PPT&#xff0c;两者结合实现“内…...

【Aioredis实战总结】Aioredis简介

一、Aioredis简介 Aioredis 是一个基于Python asyncio框架的异步Redis客户端库&#xff0c;专为高并发场景设计。它允许开发者在不阻塞主线程的情况下执行Redis操作&#xff0c;显著提升I/O密集型任务&#xff08;如Web应用的缓存、实时消息队列等&#xff09;的性能。自4.2.0…...

SpringBoot——Maven篇

Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的工具。它具有许多特性&#xff0c;其中一些重要的特性包括&#xff1a; 1. 自动配置&#xff1a;Spring Boot 提供了自动配置的机制&#xff0c;可以根据应用程序的依赖和环境自动配置应用程序的各种组件&#xff…...

Python中的多态与Java、C#、C++中的多态的区别有哪些?

Python中的多态与Java、C#、C等静态类型语言的主要区别体现在以下几个方面&#xff1a; 1. 类型系统与多态实现方式 Python&#xff08;动态类型&#xff0c;鸭子类型&#xff09; 多态基于对象的行为&#xff08;方法的存在性&#xff09;&#xff0c;而非继承或接口。只要对…...

卷积神经网络(知识点)

一、为了使特征图变小&#xff1a; 由两种方法&#xff1a;1.增大步长&#xff1a;卷积的时候不是一次一步&#xff0c;而是一次多步&#xff0c;类似一张图片&#xff0c;在原来的像素基础上&#xff0c;每隔一个取一个像素点。 其中S就是步长 注意&#xff1a;扩大步长不经…...

Vision Transformer (ViT):将Transformer带入计算机视觉的革命性尝试(代码实现)

Vision Transformer (ViT)&#xff1a;将Transformer带入计算机视觉的革命性尝试 作为一名深度学习研究者&#xff0c;如果你对自然语言处理&#xff08;NLP&#xff09;领域的Transformer架构了如指掌&#xff0c;那么你一定不会对它在序列建模中的强大能力感到陌生。然而&am…...

特殊 IP 地址

文章目录 特殊IP地址概述受限广播地址&#xff08;Limited Broadcast Address&#xff09;直接广播地址&#xff08;Directed Broadcast Address&#xff09;多播地址&#xff08;Multicast Address&#xff09;环回地址&#xff08;Loopback Address&#xff09;本网络本主机&…...

数学——A. K-divisible Sum + D. Exam in MAC

A. K-divisible Sum 题目&#xff1a; 思路&#xff1a; 以下 “[xxx]” 符号均代表向上取整 我们假设总和是sum&#xff0c;那么就有sum k * cnt 要想最大值最小&#xff0c;肯定是要让sum尽可能小&#xff0c;这样每个元素都能变小 最小情况是 sum 恰好等于 n 时&#…...

30天学习Java第五天——数组 字符串

数组 一维数组 定义 int[] anArray;int anOtherArray[];初始化int anOtherArray[] new int[] {1, 2, 3, 4, 5}; 访问 anArray[0] 10;可变数组&#xff1a;void varargsMethod(String... varargs) {} 该方法可以接收任意数量的字符串参数&#xff0c;可以是 0 个或者 N 个…...

【DeepSeek应用】本地部署deepseek模型后,如何在vscode中调用该模型进行代码撰写,检视和优化?

若已成功在本地部署了 DeepSeek 模型(例如通过 vscode-llm、ollama 或私有 API 服务),在 VS Code 中调用本地模型进行代码撰写、检视和优化的完整流程如下: 1. 准备工作:确认本地模型服务状态 模型服务类型: 若使用 HTTP API 服务(如 FastAPI/Flask 封装),假设服务地址…...

2025年【广东省安全员C证第四批(专职安全生产管理人员)】考试及广东省安全员C证第四批(专职安全生产管理人员)模拟试题

安全生产是各行各业不可忽视的重要环节&#xff0c;特别是在广东省这样的经济大省&#xff0c;安全生产的重要性更是不言而喻。为了确保安全生产管理人员具备足够的专业知识和实际操作能力&#xff0c;广东省定期举办安全员C证考试。本文将详细介绍2025年广东省安全员C证第四批…...

网络编程、URI和URL的区别、TCP/IP协议、IP和端口、URLConnection

DAY12.1 Java核心基础 网络编程 在互联网时代&#xff0c;网络在生活中处处可见&#xff0c;javaWeb占据了很大一部分 那如何实现javaWeb编程呢&#xff1f; Web编程就是运行在同一个网络下面的终端&#xff0c;使得它们之间可以进行数据传输 计算机网络基本知识 计算机网络…...

JAVA面试_进阶部分_Java JVM:垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

在什么时候&#xff1a; 首先需要知道&#xff0c;GC又分为minor GC 和 Full GC&#xff08;major GC&#xff09;。Java堆内存分为新生代和老年代&#xff0c;新生代 中又分为1个eden区和两个Survior区域。 一般情况下&#xff0c;新创建的对象都会被分配到eden区&#xff…...

自探索大语言模型微调(一)

一、数据 1.1、失败案例 Hugging Face&#xff1a; 根据B站上搜索到的资料&#xff0c;datasets这个库可以直接下载丰富的数据集合和与训练模型&#xff0c;调用也非常的简单&#xff0c;唯一的缺点就是&#xff0c;需要外网&#xff08;翻墙&#xff09;&#xff0c;用国内的…...

Unity 和 Python 的连接(通过SocketIO)附源码

在游戏或者项目开发中&#xff0c;Unity 通常用于创建前端&#xff0c;而 Python 则因其强大的数据处理能力常被用作后端。通过 Socket.IO&#xff0c;我们可以轻松地实现 Unity 和 Python 的实时通信。本文将介绍如何通过 Socket.IO 连接 Unity 和 Python&#xff0c;并附上完…...

89.HarmonyOS NEXT 应用安全与隐私保护指南:构建安全可靠的应用

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 应用安全与隐私保护指南&#xff1a;构建安全可靠的应用 文章目录 HarmonyOS NEXT 应用安全与隐私保护指南&#xff1a;构建安全可…...

浏览器对一个资源设置了缓存,如何清除缓存,且后续请求不命中缓存

方式1、浏览器端强制刷新 方式2、修改资源url eg&#xff1a;如下图&#xff0c;添加了查询参数 <link rel"stylesheet" href"style.css?v1.2.1"> <script src"app.js?t20231010"></script> 原理&#xff1a;1、在资源的…...

spring boot 发送邮件验证码

一、前置需求 1、准备邮箱 2、登录授权码 qq邮箱在–>设置–>账号POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 开启服务 二、发送邮件 1、简单邮件 包含邮件标题、邮件正文 2、引入mail启动器 <dependency><groupId>org.springframework.boot</groupI…...

MySQL连接较慢原因分析及解决措施

文章目录 整体说明一、问题现象二、问题分析2.1、DNS反向解析问题2.2、网络问题2.3、SSL/TLS协商问题2.4、自动补全的延迟 三、问题解决 摘要&#xff1a; MySQL连接较慢原因分析及解决措施 关键词&#xff1a; MySQL、连接缓慢、客户端、参数设置 整体说明 在使用MySQL的时候…...

IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T3【传球游戏】题解

目录 一、提问词 二、DeepSeekR1回复 题目描述 解题思路 实现代码 代码说明 三、说明 【IMADeepSeekR1本地知识库】撰写NOIP2008普及组复赛题解系列 1、IMADeepSeekR1本地知识库撰写NOIP2008普及组T1【ISBN 号码】题解-CSDN博客 2、IMADeepSeekR1本地知识库撰写NOIP200…...

【大模型基础_毛玉仁】2.5 基于 Decoder-only 架构的大语言模型 -- GPT和LLaMa模型介绍

更多内容&#xff1a;XiaoJ的知识星球 目录 2.5 基于 Decoder-only 架构的大语言模型2.5.1 Decoder-only 架构2.5.2 GPT 系列语言模型1&#xff09;初出茅庐&#xff1a;GPT-1 模型2&#xff09;小有所成&#xff1a;GPT-2 模型3&#xff09;崭露头角&#xff1a;GPT-3 模型4&a…...

如何解决ChatGPTplus/pro o1/o3模型无法识别图片或者文件,限制次数?

你是否遇到ChatGPTplus无法识别图片、或者无法识别文件&#xff0c;甚至回答很简短&#xff0c;o1不思考&#xff0c;GPT-4o不能联网、分析图片和处理文件&#xff01;感觉非常敷衍。本文教你如何确定自己的账号是否被降智&#xff1b;教你如何降智的原因&#xff1b;教你解决降…...

go的gmp

参考链接&#xff1a;https://www.bilibili.com/video/BV19r4y1w7Nx Golang的GMP调度模型(协程调度器)是其并发编程的核心。GMP代表Goroutine、Machine和Processor三个关键组成部分。Goroutine是Go语言中的轻量级线程&#xff0c;Machine是操作系统的线程&#xff0c;Processor…...

Vue开发者工具(VueDevtools)下载与安装

一、这里采用极简插件 网址&#xff1a;chrome.zzzmh.cn/index#/inde… 输入 vue.js.devtools并访问 点击推荐下载 下载到本地解压缩 然后把这个文件移动到谷歌插件里面,开启开发者模式 点击详情,开启一些权限 写的一个demo&#xff0c;如果有vue代码的话&#xff0c;就会…...

【C++基础十】泛型编程(模板初阶)

【C基础十】泛型编程—模板 1.什么是模板2.函数模板的实例化&#xff1a;2.1隐式实例化2.2显示实例化 3.函数模板参数的匹配规则4.什么是类模板5.类模板的实例化6.声明和定义分离 1.什么是模板 void swap(int& a, int& b) {int tmp 0;tmp a;a b;b tmp; }void swap…...

【Linux】https 协议

目录 一、https 协议 二、加密和解密 &#xff08;一&#xff09;为什么需要加密与解密 &#xff08;二&#xff09;加密和解密的过程 &#xff08;二&#xff09;常见的加密方式 1、对称加密 2、非对称加密 3、数据摘要 4、数字签名 三、https 的加密方式 &#xff…...

新手村:数据预处理-特征缩放

新手村&#xff1a;数据预处理-特征缩放 特征缩放&#xff08;Feature Scaling&#xff09;是数据预处理中的一个重要步骤&#xff0c;特别是在应用某些机器学习算法时。特征缩放可以使不同尺度的特征具有相同的量级&#xff0c;从而提高模型训练的效率和性能。常见的特征缩放方…...