axios的使用
在 Vue 项目中,封装 Axios 并实现加密、重复请求优化、请求取消、页面切换时取消未完成的请求、以及区分上传和下载操作是非常常见的需求。下面将逐一讲解这些需求的实现方式。
1. Axios 的基本封装
首先,我们可以将 Axios 封装到一个服务层中,方便统一管理请求和拦截。
// src/utils/request.js
import axios from 'axios';
import { encryptRequestData, decryptResponseData } from './crypto'; // 假设有加密解密工具
import { ElMessage } from 'element-plus'; // UI 组件库的消息提示// 创建 axios 实例
const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // api base_urltimeout: 5000, // 请求超时时间
});// 请求拦截器
service.interceptors.request.use((config) => {// 请求加密if (config.data) {config.data = encryptRequestData(config.data); // 数据加密}// token 放入 header 以防用户身份验证const token = localStorage.getItem('token');if (token) {config.headers['Authorization'] = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);// 响应拦截器
service.interceptors.response.use((response) => {// 响应解密if (response.data) {response.data = decryptResponseData(response.data); // 数据解密}return response;},(error) => {ElMessage.error('请求失败');return Promise.reject(error);}
);export default service;
2. 前后端加密的使用
前后端的加密一般是基于某种加密算法(例如 AES 或 RSA)。这里假设你有现成的加密和解密工具,可以在请求拦截器中对请求进行加密,在响应拦截器中对响应进行解密。
- 加密:请求数据通过加密函数处理,传输给后端的就是密文。
- 解密:响应数据通过解密函数还原为可读内容。
// utils/crypto.js
import CryptoJS from 'crypto-js';// 加密函数
export function encryptRequestData(data) {const key = CryptoJS.enc.Utf8.parse('16characterskey'); // 密钥const iv = CryptoJS.enc.Utf8.parse('16charactersiv '); // 偏移量const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});return encrypted.toString();
}// 解密函数
export function decryptResponseData(ciphertext) {const key = CryptoJS.enc.Utf8.parse('16characterskey'); // 密钥const iv = CryptoJS.enc.Utf8.parse('16charactersiv '); // 偏移量const bytes = CryptoJS.AES.decrypt(ciphertext, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});const decryptedData = bytes.toString(CryptoJS.enc.Utf8);return JSON.parse(decryptedData);
}
3. 重复请求的优化
为避免同一请求短时间内被多次发送,可以通过 axios 的请求拦截器实现防重复请求的功能。可以使用一个 Map 来存储每个请求的唯一标识,当同一请求发送时进行检查,防止重复发送。
const pendingRequests = new Map();const getRequestKey = (config) => {const { method, url, params, data } = config;return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&');
};// 添加请求拦截器
service.interceptors.request.use((config) => {const requestKey = getRequestKey(config);if (pendingRequests.has(requestKey)) {config.cancelToken = new axios.CancelToken((cancel) => {cancel(`Duplicate request: ${requestKey}`);});} else {pendingRequests.set(requestKey, config);}return config;},(error) => {return Promise.reject(error);}
);// 添加响应拦截器
service.interceptors.response.use((response) => {const requestKey = getRequestKey(response.config);pendingRequests.delete(requestKey); // 移除完成的请求return response;},(error) => {if (axios.isCancel(error)) {console.warn(error.message); // 重复请求被取消} else {// 其他错误处理}return Promise.reject(error);}
);
4. 单个请求的取消控制
对于单个请求,你可以使用 axios.CancelToken 来控制某个请求的取消。
const source = axios.CancelToken.source();// 发起请求时传入取消 token
service({url: '/some-endpoint',method: 'get',cancelToken: source.token
}).then((response) => {console.log('请求成功', response);}).catch((error) => {if (axios.isCancel(error)) {console.log('请求被取消', error.message);}});// 在需要的时候取消请求
source.cancel('取消请求');
5. 页面切换时取消未完成的请求
可以在 Vue 路由的 beforeRouteLeave 钩子中控制页面切换时取消未完成的请求。
export default {data() {return {requestSource: null, // 存储取消 token};},methods: {fetchData() {this.requestSource = axios.CancelToken.source();service.get('/api/data', { cancelToken: this.requestSource.token }).then(response => {console.log('请求成功', response);}).catch(error => {if (axios.isCancel(error)) {console.log('请求被取消');} else {console.error('请求错误', error);}});}},beforeRouteLeave(to, from, next) {if (this.requestSource) {this.requestSource.cancel('页面切换取消请求');}next();}
};
6. 区分上传和下载的使用
- 上传文件:通常通过
FormData来上传文件,并在onUploadProgress中监控上传进度。
let formData = new FormData();
formData.append('file', file);service.post('/upload', formData, {headers: {'Content-Type': 'multipart/form-data'},onUploadProgress: (progressEvent) => {let progress = (progressEvent.loaded / progressEvent.total) * 100;console.log(`上传进度: ${progress}%`);}
});
- 下载文件:下载文件时可以指定
responseType为blob,并处理文件保存。
service.get('/download', {responseType: 'blob',onDownloadProgress: (progressEvent) => {let progress = (progressEvent.loaded / progressEvent.total) * 100;console.log(`下载进度: ${progress}%`);}
}).then(response => {const url = window.URL.createObjectURL(new Blob([response.data]));const link = document.createElement('a');link.href = url;link.setAttribute('download', 'file.pdf'); // 下载文件名document.body.appendChild(link);link.click();
});
总结
Axios的封装统一管理请求和拦截。- 使用加密、解密函数对请求和响应数据进行保护。
- 防止重复请求,通过
requestKey唯一标识每个请求。 - 提供单个请求取消和页面切换时取消未完成请求的机制。
- 针对上传、下载分别进行处理,监听进度。
根据这些实现,你可以根据需求进一步调整封装的细节和功能。
可以结合 vue-router 的导航守卫使用,尤其是在页面切换时取消未完成的请求。通过在 vue-router 的钩子函数(例如 beforeRouteLeave 或 beforeEach)中调用 axios 的取消方法,可以确保在用户切换页面时及时取消正在进行的请求,避免无效请求消耗资源。
实现步骤
-
创建一个全局的取消请求管理工具:使用一个 Map 来存储每个页面的取消请求函数(
CancelToken),当页面切换时从 Map 中找到对应的取消方法并执行。 -
在路由守卫中调用取消方法:在
beforeEach或beforeRouteLeave钩子中调用取消请求的逻辑,确保切换路由时清理未完成的请求。
具体实现方案
1. 取消请求的封装
我们可以在 axios 的封装文件中为每个请求生成一个取消令牌(CancelToken),并将其存储在全局的 cancelMap 中。
// src/utils/request.js
import axios from 'axios';const cancelMap = new Map(); // 全局的取消请求管理工具const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // API 基础路径timeout: 10000, // 超时时间
});// 请求拦截器
service.interceptors.request.use((config) => {const source = axios.CancelToken.source(); // 创建一个取消令牌config.cancelToken = source.token; // 将取消令牌附加到请求中// 使用唯一的标识(例如:URL+请求方式)来存储取消令牌const requestKey = `${config.url}&${config.method}`;cancelMap.set(requestKey, source.cancel); // 存储取消请求函数return config;},(error) => {return Promise.reject(error);}
);// 响应拦截器
service.interceptors.response.use((response) => {// 请求成功后,删除对应的取消函数const requestKey = `${response.config.url}&${response.config.method}`;cancelMap.delete(requestKey);return response;},(error) => {// 如果请求被取消,不做其他处理if (axios.isCancel(error)) {console.log('请求被取消');}return Promise.reject(error);}
);// 取消未完成的请求
export function cancelPendingRequests() {cancelMap.forEach((cancel) => {cancel('路由切换取消请求'); // 执行取消函数});cancelMap.clear(); // 清空取消函数
}export default service;
2. 在 vue-router 中使用取消逻辑
接下来我们在 vue-router 中添加导航守卫,确保在每次路由切换时都调用 cancelPendingRequests 来取消未完成的请求。
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import { cancelPendingRequests } from '@/utils/request'; // 引入取消请求方法
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';const routes = [{path: '/',name: 'Home',component: Home,},{path: '/about',name: 'About',component: About,},
];const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes,
});// 全局路由守卫 - 在每次路由切换前,取消未完成的请求
router.beforeEach((to, from, next) => {cancelPendingRequests(); // 取消未完成的请求next(); // 继续路由切换
});export default router;
3. 在组件中发起请求
在组件中正常发起 axios 请求,不需要额外的处理。每次请求都会通过 axios 封装自动附加 CancelToken,并在路由切换时通过 cancelPendingRequests 自动取消。
// src/views/Home.vue
<template><div><h1>Home</h1><p>{{ data }}</p></div>
</template><script>
import service from '@/utils/request';export default {data() {return {data: null,};},mounted() {this.fetchData();},methods: {async fetchData() {try {const response = await service.get('/api/home');this.data = response.data;} catch (error) {console.error(error);}},},
};
</script>
4. 页面级取消请求
有时我们只需要在页面组件内部取消请求,比如当用户离开页面时取消当前页面的请求,这时可以使用组件的 beforeRouteLeave 钩子。
// src/views/About.vue
<template><div><h1>About</h1><p>{{ data }}</p></div>
</template><script>
import service from '@/utils/request';
import { ref } from 'vue';export default {setup() {const data = ref(null);let requestSource = null;const fetchData = async () => {requestSource = service.CancelToken.source();try {const response = await service.get('/api/about', {cancelToken: requestSource.token,});data.value = response.data;} catch (error) {if (axios.isCancel(error)) {console.log('请求被取消');} else {console.error(error);}}};return { data, fetchData };},mounted() {this.fetchData();},beforeRouteLeave(to, from, next) {if (this.requestSource) {this.requestSource.cancel('页面离开取消请求');}next();},
};
</script>
总结
- 全局取消:通过在
vue-router的beforeEach守卫中调用cancelPendingRequests,每次路由切换时都会取消未完成的请求,避免页面切换后无用的网络请求消耗。 - 局部取消:在页面组件内部使用
beforeRouteLeave钩子取消单个页面的请求,确保当用户离开页面时及时中止未完成的请求。 - 防止重复请求:通过对请求进行唯一标识,并在发起请求前检查是否有相同请求正在进行,可以防止重复发送相同的请求。
通过结合 vue-router 和 axios 的 CancelToken,可以有效地管理请求的生命周期,确保用户体验的流畅性。
在实际开发中,前端项目可能会需要请求不同的服务地址(例如,不同的 API 网关、微服务等),而 Axios 的 baseURL 是请求的默认根路径。如果项目中需要根据具体请求来动态配置不同的 baseURL,有几种方式可以处理:
常见解决方案
1. 在请求时动态指定 baseURL
可以根据不同的业务逻辑或接口,动态为每个请求指定 baseURL。Axios 支持在发起请求时覆盖默认的 baseURL,通过为每个请求单独设置 baseURL 来实现多服务地址请求。
import axios from 'axios';// 默认 axios 实例
const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // 默认的 baseURLtimeout: 10000, // 超时时间
});// 示例:根据业务逻辑或特定条件指定不同的 baseURL
export function fetchDataFromServiceA() {return service({url: '/serviceA/data',baseURL: 'https://api.serviceA.com', // 为这个请求动态设置 baseURLmethod: 'get',});
}export function fetchDataFromServiceB() {return service({url: '/serviceB/data',baseURL: 'https://api.serviceB.com', // 另一个服务的 baseURLmethod: 'get',});
}
2. 创建多个 Axios 实例
如果不同服务的 baseURL 是固定的,并且它们各自有独立的配置,那么可以为每个服务创建一个独立的 Axios 实例。这样可以对不同服务有不同的 baseURL、headers 或其他配置。
import axios from 'axios';// 服务A的 axios 实例
const serviceA = axios.create({baseURL: 'https://api.serviceA.com',timeout: 10000,
});// 服务B的 axios 实例
const serviceB = axios.create({baseURL: 'https://api.serviceB.com',timeout: 10000,
});// 使用 serviceA 发送请求
export function fetchServiceAData() {return serviceA.get('/data');
}// 使用 serviceB 发送请求
export function fetchServiceBData() {return serviceB.get('/data');
}
这种方式使得各个服务的配置更加独立清晰,有助于代码的可维护性。
3. 根据环境动态配置 baseURL
对于一些需要根据不同的环境(如开发、生产等)动态切换服务地址的需求,可以在配置文件中根据 NODE_ENV 来设定不同的 baseURL。
// .env.development
VUE_APP_BASE_API=https://dev.api.com// .env.production
VUE_APP_BASE_API=https://prod.api.com
在 axios 的封装文件中读取环境变量:
import axios from 'axios';const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // 根据环境变量设置 baseURLtimeout: 10000,
});export default service;
4. 通过请求拦截器动态修改 baseURL
如果需要根据请求的特定条件(例如请求的路径、参数等)来动态设置不同的 baseURL,可以在 axios 的请求拦截器中根据条件修改 config.baseURL。
import axios from 'axios';// 默认 axios 实例
const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // 默认的 baseURLtimeout: 10000,
});// 请求拦截器 - 根据特定条件动态设置 baseURL
service.interceptors.request.use((config) => {if (config.url.includes('/serviceA')) {config.baseURL = 'https://api.serviceA.com'; // 动态切换到 serviceA 的 baseURL} else if (config.url.includes('/serviceB')) {config.baseURL = 'https://api.serviceB.com'; // 动态切换到 serviceB 的 baseURL}return config;},(error) => {return Promise.reject(error);}
);export default service;
5. 在组件中指定 baseURL
在组件中直接为特定的请求指定 baseURL,这也是一种灵活的方式,适用于只在特定组件内进行请求的情况。
<template><div><button @click="fetchData">获取数据</button></div>
</template><script>
import axios from 'axios';export default {methods: {fetchData() {axios({url: '/data',baseURL: 'https://api.serviceA.com', // 在组件中指定 baseURLmethod: 'get',}).then((response) => {console.log('数据:', response.data);}).catch((error) => {console.error('请求错误:', error);});},},
};
</script>
6. 根据 API 名称或者模块切换 baseURL
可以将 API 分模块管理,通过模块名自动选择对应的 baseURL。例如,可以根据模块名动态选择不同的 baseURL。
const serviceMap = {serviceA: 'https://api.serviceA.com',serviceB: 'https://api.serviceB.com',
};export function request({ module, url, ...options }) {const service = axios.create({baseURL: serviceMap[module], // 动态选择 baseURLtimeout: 10000,});return service({ url, ...options });
}// 使用
request({module: 'serviceA',url: '/data',method: 'get',
}).then(response => {console.log(response.data);
});
总结
- 动态设置
baseURL:直接在请求中指定baseURL,适用于小范围的不同服务地址请求。 - 多个 Axios 实例:为每个服务创建独立的
Axios实例,适用于多个不同服务地址的项目,清晰明确。 - 环境变量切换:根据开发、生产环境自动配置不同的
baseURL。 - 拦截器动态修改:通过请求拦截器动态修改
baseURL,适合复杂场景的需求。 - 模块化管理:根据模块名或者业务需求选择不同的
baseURL,可读性更高。
根据你的项目规模和需求,可以选择最适合的方式处理多 baseURL 问题。
加密解密方案
在前后端通信中,使用加密方案来保护数据的安全性是非常重要的。常见的加密方式通常有对称加密、非对称加密和哈希算法。以下是一些在 Axios 中常用的加密方案,结合前后端的使用场景以及如何在 Axios 请求中应用这些加密方式。
常见加密方式
1. 对称加密(Symmetric Encryption)
对称加密是指加密和解密使用相同的密钥。常见的对称加密算法有 AES(Advanced Encryption Standard)。在前后端通信中,可以使用对称加密对敏感信息进行加密,后端使用相同的密钥解密。
使用场景:
对称加密通常用于加密敏感数据(如用户密码、银行信息等)在传输中的保护。
在 Axios 中使用 AES 加密:
npm install crypto-js
import axios from 'axios';
import CryptoJS from 'crypto-js';const secretKey = 'your-secret-key'; // 需要和后端保持一致的密钥// 加密函数
function encryptData(data) {const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();return ciphertext;
}// 解密函数(在后端实现,前端不需要)
function decryptData(ciphertext) {const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);const decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));return decryptedData;
}// 使用加密后的数据发送请求
axios.post('/api/encrypt', {data: encryptData({username: 'user1',password: 'mypassword',}),
}).then(response => {console.log('Response:', response.data);
}).catch(error => {console.error('Error:', error);
});
在这种情况下,前端对敏感数据进行 AES 加密,然后通过 Axios 发送给服务器,服务器在收到数据后用相同的密钥进行解密。
2. 非对称加密(Asymmetric Encryption)
非对称加密使用一对密钥:公钥和私钥。常见的非对称加密算法是 RSA。通常,前端使用公钥加密数据,后端使用私钥解密数据。非对称加密适用于加密少量数据,因为它的加密速度较慢。
使用场景:
非对称加密常用于需要高度安全性的数据传输,如敏感的身份验证信息、密钥交换等。
在 Axios 中使用 RSA 加密:
npm install node-forge
import axios from 'axios';
import forge from 'node-forge';// 从后端获取公钥
axios.get('/api/public-key').then(response => {const publicKey = response.data.publicKey;// 使用 RSA 公钥加密const encryptWithRSA = (data, publicKey) => {const rsa = forge.pki.publicKeyFromPem(publicKey);const encrypted = rsa.encrypt(forge.util.encodeUtf8(data));return forge.util.encode64(encrypted);};// 加密数据const encryptedData = encryptWithRSA(JSON.stringify({username: 'user1',password: 'mypassword',}), publicKey);// 发送加密后的数据axios.post('/api/encrypt', {data: encryptedData,}).then(response => {console.log('Response:', response.data);});
});
在这种场景下,前端获取后端的公钥后,用 RSA 加密敏感数据,发送给服务器。后端用私钥解密数据。
3. 哈希算法(Hashing)
哈希算法用于将任意长度的数据映射为固定长度的散列值。常见的哈希算法包括 MD5、SHA-256 等。哈希算法通常用于验证数据的完整性,例如校验文件是否被篡改或传输过程中是否损坏。
使用场景:
哈希函数常用于密码的加盐哈希存储,或通过签名验证请求的完整性(如 HMAC)。
在 Axios 中使用 SHA-256 进行数据签名:
npm install crypto-js
import axios from 'axios';
import CryptoJS from 'crypto-js';// 加盐哈希
function hashData(data, secret) {const hash = CryptoJS.HmacSHA256(data, secret);return hash.toString(CryptoJS.enc.Hex);
}// 创建要发送的数据
const data = JSON.stringify({username: 'user1',password: 'mypassword',
});// 生成签名
const secret = 'your-secret-key';
const signature = hashData(data, secret);// 发送带有签名的请求
axios.post('/api/verify', {data,signature, // 传递签名以验证完整性
}).then(response => {console.log('Response:', response.data);
});
这种方式确保请求在传输过程中没有被篡改,后端可以使用相同的密钥对接收到的数据进行哈希计算,并验证签名是否匹配。
4. 混合加密
混合加密是对称加密和非对称加密的结合,通常用于提高安全性和效率。在实际应用中,通常会使用 RSA 非对称加密来加密 AES 对称加密的密钥,而数据则使用 AES 加密,这样可以兼顾效率和安全性。
使用场景:
混合加密常用于需要传输大量数据但仍需要高度安全性的场景,特别是前端生成随机的对称密钥,用 RSA 加密这个密钥后传递给后端。
实现混合加密:
import axios from 'axios';
import CryptoJS from 'crypto-js';
import forge from 'node-forge';// 使用 AES 生成随机密钥
function generateAESKey() {return CryptoJS.lib.WordArray.random(16).toString();
}// AES 加密数据
function encryptData(data, aesKey) {return CryptoJS.AES.encrypt(data, aesKey).toString();
}// RSA 公钥加密 AES 密钥
function encryptAESKeyWithRSA(aesKey, publicKey) {const rsa = forge.pki.publicKeyFromPem(publicKey);const encrypted = rsa.encrypt(forge.util.encodeUtf8(aesKey));return forge.util.encode64(encrypted);
}// 混合加密过程
axios.get('/api/public-key').then(response => {const publicKey = response.data.publicKey;const aesKey = generateAESKey();const encryptedData = encryptData(JSON.stringify({username: 'user1',password: 'mypassword',}), aesKey);const encryptedAESKey = encryptAESKeyWithRSA(aesKey, publicKey);// 发送加密的数据和加密的 AES 密钥axios.post('/api/encrypt', {encryptedData,encryptedAESKey,}).then(response => {console.log('Response:', response.data);});
});
在这种情况下,前端使用 AES 加密实际数据,并使用 RSA 加密 AES 密钥。后端接收到加密的密钥和数据后,先用 RSA 私钥解密 AES 密钥,再用 AES 密钥解密数据。
重复请求的优化和请求取消
-
防止重复请求:
通过使用请求的唯一标识(例如url + method)来管理请求,防止用户短时间内重复发送相同请求。可以在发送请求前检查是否有相同的请求正在进行,如果有则不发送新的请求。 -
取消请求:
可以结合axios的CancelToken,在用户离开页面或切换操作时取消未完成的请求,避免浪费资源。
总结
- 对称加密:如 AES,适用于加密传输的敏感数据。
- 非对称加密:如 RSA,适用于密钥交换和少量敏感数据的加密。
- 哈希算法:如 SHA-256,常用于数据完整性验证。
- 混合加密:结合 AES 和 RSA,兼顾性能和安全性,常用于大数据加密。
通过这些加密方案,能够有效地保护前后端通信中的数据安全。
相关文章:
axios的使用
在 Vue 项目中,封装 Axios 并实现加密、重复请求优化、请求取消、页面切换时取消未完成的请求、以及区分上传和下载操作是非常常见的需求。下面将逐一讲解这些需求的实现方式。 1. Axios 的基本封装 首先,我们可以将 Axios 封装到一个服务层中…...
Ubuntu 使用命令克隆和恢复SD卡
因为平常我需要做很多张开发板的出货卡,测试卡,那么我需要将备份下来文件,方便后续管理,这里时候需要用到Ubuntu上面的命令来克隆镜像和恢复镜像到SD卡上 先查询自己的SD卡是在sdx,以我的为例子,为sdb 备…...
Java 小游戏《超级马里奥》
文章目录 一、效果展示二、代码编写1. 素材准备2. 创建窗口类3. 创建常量类4. 创建动作类5. 创建关卡类6. 创建障碍物类7. 创建马里奥类8. 编写程序入口 一、效果展示 二、代码编写 1. 素材准备 首先创建一个基本的 java 项目,并将本游戏需要用到的图片素材 image…...
go语言defer详解
什么是defer?为什么需要defer?怎样合理使用defer?defer进阶 defer的底层原理是什么?利用defer原理defer命令的拆解defer语句的参数闭包是什么?defer配合recover后记参考资料 什么是defer? defer是Go语言提供的一种用…...
【C语言】循环中断break
在循环使用过程中,可能遇到某些情况需要终止循环。比如按座位查找一位学生,循环查找,找到时可以直接停止。后续的循环将不再执行。 break;只跳出一层循环 例子中的素数判断,查找到根号n停止:一个合数等于两个数的乘积…...
centos ping能通但是wget超时-解决
问题截图: 域名解析地址为IPV6地址,建议您调整IPV4优先级之后,再尝试访问,请参考Linux系统IPv4/IPv6双栈接入优先使用IPv4设置:移动云帮助中心 实操截图:...
SDIO - DWC MSHC 电压切换和频率切换
背景 我们的sdio访问sd card过去一直跑在低频上,HS50M。前段时间给eMMc添加了HS200模式,eMMc的总线模式定义是这样的: 可以看到1.8V的IO 电压可以支持所有模式,我们过去的芯片,由硬件部门放到evb上,其IO …...
EI-CLIP 深度理解 PPT
系列文章目录 文章目录 系列文章目录 在电子商务产品的跨模态检索中,电子商务图像和电子商务语言都有许多独特的特点。如图所示,一个电子商务产品图片通常只包含一个简单的场景,有一个或两个前景物体和一个普通的背景。同时,电子商…...
leetcode力扣刷题系列——【最小元素和最大元素的最小平均值】
题目 你有一个初始为空的浮点数数组 averages。另给你一个包含 n 个整数的数组 nums,其中 n 为偶数。 你需要重复以下步骤 n / 2 次: 从 nums 中移除 最小 的元素 minElement 和 最大 的元素 maxElement。 将 (minElement maxElement) / 2 加入到 aver…...
【线性回归分析】:基于实验数据的模型构建与可视化
目录 线性回归分析:基于实验数据的模型构建与可视化 1. 数据准备 2. 构建线性回归模型 3. 可视化 数据分析的核心 构建预测模型 应用场景 预测模型中的挑战 结论 线性回归分析:基于实验数据的模型构建与可视化 在数据分析领域,线性…...
CountUp.js 实现数字增长动画 Vue
效果: 官网介绍 1. 安装 npm install --save countup.js2. 基本使用 // template <span ref"number1Ref"></span>// script const number1Ref ref<HTMLElement>() onMounted(() > {new CountUp(number1Ref.value!, 9999999).sta…...
设计模式大全
1. 策略模式 什么是策略模式? 策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互换。策略模式使得算法可以独立于使用它的客户端而变化。通过使用策略…...
redis IO多路复用机制
目录 一、五种 I/O 模型 1.阻塞IO(Blocking IO) 2.非阻塞IO(Nonblocking IO) 3.IO多路复用(IO Multiplexing) 通知的方式 select模式 poll模式 epoll模式 4.信号驱动IO(Signal Driven …...
Oracle漏洞修复 19.3 补丁包 升级为19.22
1.场景描述 上周末2024-10-12日,服务器扫出漏洞,希望及时修复。其中,oracle的漏洞清单如下,总结了下,基本都是 Oracle Database Server 的 19.3 版本到 19.20 版本和 21.3 版本到 21.11 版本存在安全漏洞,即版本问题。如: Oracle Database Server 安全漏洞(CVE-2023-22…...
Q2=10 and Q2=1--PLB(Fig.4)
(个人学习笔记,仅供参考) import numpy as np from scipy.special import kv, erfc from scipy.integrate import dblquad import matplotlib.pyplot as plt import scipy.integrate as spi# Constants w 0.6198 g0_sq 21.5989 rho 0.782…...
sd卡挂载返回FR_NOT_READY等错误
前言 本文章主要是例举文件系统挂载sd卡时出现的一下问题总结。本人用的芯片是GDF103系列,最近项目要使用sd进行读取文件,因此查阅了资料进行开发。一开始是使用了SPI方式连接,例程是原子哥的stm32进行改的,但多次调试都是卡死在发…...
推荐一款超级实用的浏览器扩展程序!实时翻译网页,支持多种语言(带私活源码)
今天给大家分享的一款浏览器插件。 一、背景 在如今的信息时代,互联网已经成为了人们获取信息、交流和娱乐的重要平台,而随着全球化的不断深入和交流的加强,越来越多的人开始关注各国的文化、政治和经济,因此需要浏览不同语言的…...
manjaro kde 24 应该如何设置才能上网(2024-10-13亲测)
要在 Manjaro KDE 24 上设置网络连接,可以按照以下步骤进行设置,确保你能够连接到互联网: 是的,你可以尝试使用一个简单的自动修复脚本来解决 Manjaro KDE 中的网络连接问题。这个脚本将检查网络服务、重新启动 NetworkManager、…...
2024软件测试面试大全(答案+文档)
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、软件测试基础面试题 1、阐述软件生命周期都有哪些阶段? 常见的软件生命周期模型有哪些? 软件生命周期是指一个计算机软件从功能确定设计,到…...
unity动态批处理
unity动态批处理 动态批处理要求和兼容性渲染管线兼容性 使用动态批处理网格的动态批处理限制动态生成几何体的动态批处理 动态批处理 动态批处理是一种绘制调用批处理方法,用于批处理移动的 GameObjects 以减少绘制调用。动态批处理在处理网格和 Unity 在运行时动…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
