国家商标查询官方网站,北京网站建设价,企业推广网站,wordpress 菜单 图片此文章带你实现前端缓存#xff0c;利用时间戳封装一个类似于Redis可以添加过期时间的缓存工具 不仅可以实现对缓存数据设置过期时间#xff0c;还可以自定义是否需要对缓存数据进行加密处理
工具介绍说明
对缓存数据进行非对称加密处理 对必要数据进行缓存#xff0c;并…此文章带你实现前端缓存利用时间戳封装一个类似于Redis可以添加过期时间的缓存工具 不仅可以实现对缓存数据设置过期时间还可以自定义是否需要对缓存数据进行加密处理
工具介绍说明
对缓存数据进行非对称加密处理 对必要数据进行缓存并设置过期时间并设置是否需要对缓存数据进行加密处理 其他工具 1、过期时间封装好的工具可以添加数据的缓存时长过期时间 2、是否加密可以根据需求是否需要对缓存的数据进行加密处理 3、加密解密只需要简单配置就可以实现缓存数据的加密解密功能 4、长期有效对于不需要过期的数据只要不手动清理可以长期有效 5、扩展性强可以根据自己的需求直接进行代码的调整简单易懂易扩展 本地缓存 1、Vue、Html5 的数据缓存可以存放到localStorage 、cookie 或者 sessionStorage 中 2、uniApp、和 微信小程序 的数据缓存可以使用自带的API uni.setStorageSync 缓存的缺点 1、无论localStorage、cookie、sessionStorage 还是 uni.setStorageSync 都没有过期时间的限制 2、不能对数据进行实时的加解密处理或者加解密扩展性差 3、对于大量旧的缓存数据还要手动处理不能实时的去除旧数据 简单封装 代码以uniApp 为例先实现可以添加过期时间的功能 缓存工具类cacheUtil.js
const expiration 1000 * 60 * 60 * 24 * 7; // 默认有效期7天
const keyPrefix KEY_; // 缓存key的统一前缀
import { isEmpty, isNumberStr, trimAllBlank } from ./utils.js;/*** 添加缓存* param {String} key 缓存的key* param {Object} val 缓存的val* param {Number} expire 过期时间单位秒* returns {Boolean} 成功 | 失败*/
export const setCache (key, val, expire) {if (isEmpty(key)) return false;expire expire isNumberStr(expire) ? Number(trimAllBlank(expire)) : 0;expire Date.now() (expire 0 ? expiration : (expire * 1000));let param JSON.stringify({data: val, // 缓存的数据expire: expire // 过期时间});key keyPrefix key; // 缓存的keyuni.setStorageSync(key, param); // 同步缓存return true;
}/*** 获取缓存的数据* param {String} key 缓存key* returns {Object}*/
export const getCache (key) {if (isEmpty(key)) return {};key keyPrefix key;let value uni.getStorageSync(key) || ;if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire value.expire || ;if (isEmpty(expire) || !isNumberStr(expire)) {return value.data || ;}expire Number(expire) || 0;if (expire Date.now()) {removeKeys(key);return {};}}return value.data;
}/*** 获取缓存有效时长单位秒* param {String} key 缓存的key* param {Number} unit 0毫秒1秒2分钟默认毫秒值* returns {Number} 有效时长*/
export const getExpire (key, unit) {if (isEmpty(key)) return 0;key keyPrefix key;let value uni.getStorageSync(key) || ;if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire Number(value.expire || 0);if (unit 1) return expire / 1000;if (unit 2) return expire / 1000 / 60;return expire;}return 0;
}/*** 给缓存设置过期时间* param {String} key 缓存数据的key* param {Number} expire 过期时长单位秒*/
export const setExpire (key, expire) {let value getCache(key) || {};setCache(key, value, expire);
}/*** 删除缓存数据* param keys 删除缓存多个key之间使用,隔开* returns {Number} 删除条数*/
export const removeKeys (...keys) {if (isEmpty(keys)) return 0;keys.forEach((key, index) {key keyPrefix key;uni.removeStorageSync(key); // 同步删除});return keys.length;
}/*** 清空所有缓存*/
export const clearAll () {uni.clearStorageSync(); // 同步清除
}数据加解密 我这里使用的使用非对称加密根据个人项目需求可进行调整 加解密工具类jsencryptUtil.js
import JSEncrypt from jsencrypt/bin/jsencrypt.min;
const encryptor new JSEncrypt();
const publicKey -----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALg
CXvS1JPTluyIqr3eie4mqkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQ
-----END PUBLIC KEY-----;
const privateKey -----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALgCXvS1JPTluyIqr3eie4m
qkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQJABNYdbvX2nbC8vxoYBLal
wO9kTFfhLHO9k6Hiop2k5wjbl7FlOBUr7iEeFxdYeuT0JcNyLVeGphKZAS9HlR
0QIhALWpLQaV/UFD/E3lTtkCd890Hn6noLKCOxMRcwtx22oxAiEA2ublehWoGwA5
FGL9s7B9AgMOwzX0Z43F4fzCfAwCF8CIGYhR6QVPT2tKDLvAWY14f/q654PReQ2
HVo6DDDaAR5xAiEAgyFMGD07aXNjcO8D4Y944yqnvkLk/NNydmbO6oJ2sCIAzn
bQCPl4yK81yVTdUA0fMKWRZn3vJ2C11AaemSs42C
-----END RSA PRIVATE KEY-----;/*** 使用公钥进行加密处理* param {string} txt 明文字符串*/
export function encrypt(txt) {// 设置公钥encryptor.setPublicKey(publicKey); // 对数据进行加密return encryptor.encrypt(txt);
}/*** 使用私钥进行解密处理* param {string} enc 密文字符串*/
export function decrypt(enc) {// 设置私钥encryptor.setPrivateKey(privateKey);// 对数据进行解密return encryptor.decrypt(enc);
}完善缓存工具
const expiration 1000 * 60 * 60 * 24 * 7; // 默认有效期7天
const keyPrefix KEY_; // 缓存key的统一前缀
import { isEmpty, isNumberStr, trimAllBlank } from ./utils.js;
import { encrypt, decrypt } from ./jsencryptUtil.js;/*** 添加缓存* param {String} key 缓存的key* param {Object} val 缓存的val* param {Number} expire 过期时间单位秒* param {Boolean} enc 是否需要加密处理true | false* returns {Boolean} 成功 | 失败*/
export const setCache (key, val, expire, enc) {if (isEmpty(key)) return false;expire expire isNumberStr(expire) ? Number(trimAllBlank(expire)) : 0;expire Date.now() (expire 0 ? expiration : (expire * 1000));let param JSON.stringify({data: val, // 缓存的数据expire: expire // 过期时间});if (enc true) param encrypt(param );key keyPrefix key; // 缓存的keyuni.setStorageSync(key, param); // 同步缓存return true;
}/*** 获取缓存的数据* param {String} key 缓存key* param {Boolean} dec 是否需要解密处理true | false* returns {Object}*/
export const getCache (key, dec) {if (isEmpty(key)) return {};key keyPrefix key;let value uni.getStorageSync(key) || ;if (dec true) value decrypt(value);if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire value.expire || ;if (isEmpty(expire) || !isNumberStr(expire)) {return value.data || ;}expire Number(expire) || 0;if (expire Date.now()) {removeKeys(key);return {};}}return value.data;
}/*** 删除缓存数据* param keys 删除缓存多个key之间使用,隔开* returns {Number} 删除条数*/
export const removeKeys (...keys) {if (isEmpty(keys)) return 0;keys.forEach((key, index) {key keyPrefix key;uni.removeStorageSync(key); // 同步删除});return keys.length;
}/*** 清空所有缓存*/
export const clearAll () {uni.clearStorageSync(); // 同步清除
}这样就可以对缓存的数据进行加密处理了 每次都要传入一个参数来确定是否需要加密或者解密处理太繁琐了 能不能不需要我来传是否需要解密呢根据加密参数进行判断答案时可以的 接下来我们先处理一下加解密工具对于很长很长的明文数据进行加密时加密工具会报错 下面对加密工具进行改造改造完成之后再来进一步完善缓存工具不用每次都传入解密标志
加密太长报错 使用 JSEncrypt 加密数据时对于比较长的字符串加密时会出现异常报错并提示数据太大 解决方法需要对加密工具进行一次改造处理
修改加密工具
import JSEncrypt from jsencrypt/bin/jsencrypt.min;
const encryptor new JSEncrypt();
const publicKey -----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALg
CXvS1JPTluyIqr3eie4mqkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQ
-----END PUBLIC KEY-----;
const privateKey -----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALgCXvS1JPTluyIqr3eie4m
qkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQJABNYdbvX2nbC8vxoYBLal
wO9kTFfhLHO9k6Hiop2k5wjbl7FlOBUr7iEeFxdYeuT0JcNyLVeGphKZAS9HlR
0QIhALWpLQaV/UFD/E3lTtkCd890Hn6noLKCOxMRcwtx22oxAiEA2ublehWoGwA5
FGL9s7B9AgMOwzX0Z43F4fzCfAwCF8CIGYhR6QVPT2tKDLvAWY14f/q654PReQ2
HVo6DDDaAR5xAiEAgyFMGD07aXNjcO8D4Y944yqnvkLk/NNydmbO6oJ2sCIAzn
bQCPl4yK81yVTdUA0fMKWRZn3vJ2C11AaemSs42C
-----END RSA PRIVATE KEY-----;/*** 使用公钥进行加密处理* param {string} txt 明文字符串*/
export function encrypt(txt) {encryptor.setPublicKey(publicKey); // 设置公钥if (txt.length 100) {let result ;while (txt txt.length 0) {let dl txt.slice(0, 100);txt txt.slice(100);if (!result) {result result encryptor.encrypt(dl);} else {result result ~ encryptor.encrypt(dl);}}return result;}return encryptor.encrypt(txt); // 对数据进行加密
}/*** 使用私钥进行解密处理* param {string} enc 密文字符串*/
export function decrypt(enc) {// 设置私钥encryptor.setPrivateKey(privateKey);if (enc.includes(~)) {let result ;let arr enc.split(~);for (let i 0; i arr.length; i) {if (arr[i] arr[i].length 0) {result result encryptor.decrypt(arr[i]);}}return result;}return encryptor.decrypt(enc);
}改造缓存工具
const expiration 1000 * 60 * 60 * 24 * 7; // 默认有效期7天
const keyPrefix KEY_; // 缓存key的统一前缀
import { isEmpty, isNumberStr, trimAllBlank } from ./util.js;
import { encrypt, decrypt } from ./jsencryptUtil.js;/*** 添加缓存* param {String} key 缓存的key* param {Object} val 缓存的val* param {Number} expire 过期时间单位秒* param {Boolean} enc 是否需要加密处理true | false* returns {Boolean} 成功 | 失败*/
export const setCache (key, val, expire, enc) {if (isEmpty(key)) return false;expire expire isNumberStr(expire) ? Number(trimAllBlank(expire)) : 0;expire Date.now() (expire 0 ? expiration : (expire * 1000));enc enc true;let param JSON.stringify({data: (enc ? encrypt(val) : val), // 缓存的数据encrypt: enc, // 数据加密标志expire: expire // 过期时间});key keyPrefix key; // 缓存的keyuni.setStorageSync(key, param); // 同步缓存return true;
}/*** 获取缓存的数据* param {String} key 缓存key* returns {Object}*/
export const getCache (key) {if (isEmpty(key)) return {};key keyPrefix key;let value uni.getStorageSync(key) || ;if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire value.expire || ;let dec value.encrypt true;if (dec) value.data decrypt(value.data);if (isEmpty(expire) || !isNumberStr(expire)) {return value.data || ;}expire Number(expire) || 0;if (expire Date.now()) {removeKeys(key);return {};}}return value;
}/*** 删除缓存数据* param keys 删除缓存多个key之间使用,隔开* returns {Number} 删除条数*/
export const removeKeys (...keys) {if (isEmpty(keys)) return 0;keys.forEach((key, index) {key keyPrefix key;uni.removeStorageSync(key); // 同步删除});return keys.length;
}/*** 清空所有缓存*/
export const clearAll () {uni.clearStorageSync(); // 同步清除
}到此缓存工具就完成了只要在缓存时传入是否需要加密的参数就可以了解密时只需要传入key就可以了不需要再额外传入解密参数
最终完整代码
util工具
util.js
/*** 判断数据是否为空* param {*} input 原数据* return {Boolean}*/
export const isEmpty (input) {if (Object.prototype.toString.call(input) [object Object]) {let vals Object.values(input) || [];let num 0;for (let val of vals) {val (!val ? : JSON.stringify(val)).trim().replace(/\s*/g, );num !val ? num 1 : num;}return vals.length num;}if (typeof input ! string) input (!input ? : JSON.stringify(input)).trim().replace(/\s*/g, );return !input || input.length 0 || ([[], {}, NaN, null, undefined].includes(input));
}/*** 去除特殊字符包括但不限于空格、制表符\t、换行符\r、回车符\n* param {string} input 原数据* return {string}*/
export const trimAllBlank (input) {input typeof input string ? input.trim() : JSON.stringify(input);return (input || ).replace(/\s*/g, );
}/*** 是否数字* param {string} str 字符串* returns {boolean}*/
export const isNumberStr (str) {str isEmpty(str) ? : str;return /^[-]?(0|([1-9]\d*))(\.\d)?$/g.test(str);
}加密工具
jsencryptUtil.js
import JSEncrypt from jsencrypt/bin/jsencrypt.min;
const publicKey -----BEGIN PUBLIC KEY-----
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALg
CXvS1JPTluyIqr3eie4mqkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQ
-----END PUBLIC KEY-----;
const privateKey -----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBAJtV6S0G6O9LpOVx/riiZzNk1gAl1ALgCXvS1JPTluyIqr3eie4m
qkVdFROjNpCxvtXkRtisB9PlmU9YOPTt8C8CAwEAAQJABNYdbvX2nbC8vxoYBLal
wO9kTFfhLHO9k6Hiop2k5wjbl7FlOBUr7iEeFxdYeuT0JcNyLVeGphKZAS9HlR
0QIhALWpLQaV/UFD/E3lTtkCd890Hn6noLKCOxMRcwtx22oxAiEA2ublehWoGwA5
FGL9s7B9AgMOwzX0Z43F4fzCfAwCF8CIGYhR6QVPT2tKDLvAWY14f/q654PReQ2
HVo6DDDaAR5xAiEAgyFMGD07aXNjcO8D4Y944yqnvkLk/NNydmbO6oJ2sCIAzn
bQCPl4yK81yVTdUA0fMKWRZn3vJ2C11AaemSs42C
-----END RSA PRIVATE KEY-----;/*** 使用公钥进行加密处理* param {string} txt 明文字符串*/
export function encrypt(txt) {const encryptor new JSEncrypt();encryptor.setPublicKey(publicKey); // 设置公钥if (txt.length 100) {let result ;while (txt txt.length 0) {let dl txt.slice(0, 100);txt txt.slice(100);if (!result) {result result encryptor.encrypt(dl);} else {result result ~ encryptor.encrypt(dl);}}return result;}return encryptor.encrypt(txt); // 对数据进行加密
}/*** 使用私钥进行解密处理* param {string} enc 密文字符串*/
export function decrypt(enc) {const encryptor new JSEncrypt();encryptor.setPrivateKey(privateKey);if (enc.includes(~)) {let result ;let arr enc.split(~);for (let i 0; i arr.length; i) {if (arr[i] arr[i].length 0) {result result encryptor.decrypt(arr[i]);}}return result;}return encryptor.decrypt(enc);
}缓存工具
cacheUtil.js
const expiration 1000 * 60 * 60 * 24 * 7; // 默认有效期7天
const keyPrefix KEY_; // 缓存key的统一前缀
import { isEmpty, isNumberStr, trimAllBlank } from ./util.js;
import { encrypt, decrypt } from ./jsencryptUtil.js;/*** 添加缓存* param {String} key 缓存的key* param {Object} val 缓存的val* param {Number} expire 过期时间单位秒* param {Boolean} enc 是否需要加密处理true | false* returns {Boolean} 成功 | 失败*/
export const setCache (key, val, expire, enc) {if (isEmpty(key)) return false;expire expire isNumberStr(expire) ? Number(trimAllBlank(expire)) : 0;expire Date.now() (expire 0 ? expiration : (expire * 1000));enc enc true;let param JSON.stringify({data: (enc ? encrypt(val) : val), // 缓存的数据encrypt: enc, // 数据加密标志expire: expire // 过期时间});key keyPrefix key; // 缓存的keyuni.setStorageSync(key, param); // 同步缓存return true;
}/*** 获取缓存的数据* param {String} key 缓存key* returns {Object}*/
export const getCache (key) {if (isEmpty(key)) return {};key keyPrefix key;let value uni.getStorageSync(key) || ;if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire value.expire || ;let dec value.encrypt true;if (dec) value.data decrypt(value.data);if (isEmpty(expire) || !isNumberStr(expire)) {return value.data || ;}expire Number(expire) || 0;if (expire Date.now()) {removeKeys(key);return {};}}return value;
}/*** 获取缓存有效时长单位秒* param {String} key 缓存的key* param {Number} unit ms毫秒s秒m分钟默认毫秒值* returns {Number} 有效时长*/
export const getExpire (key, unit) {if (isEmpty(key)) return 0;key keyPrefix key;let value uni.getStorageSync(key) || ;if (value.includes(data) value.includes(expire)) {value JSON.parse(value) || {};let expire Number(value.expire || 0);unit unit.toLowerCase();if (unit s) return expire / 1000;if (unit m) return expire / 1000 / 60;return expire;}return 0;
}/*** 给缓存设置过期时间* param {String} key 缓存数据的key* param {Number} expire 过期时长单位秒*/
export const setExpire (key, expire) {let value getCache(key) || {};setCache(key, value, expire);
}/*** 删除缓存数据* param keys 删除缓存多个key之间使用,隔开* returns {Number} 删除条数*/
export const removeKeys (...keys) {if (isEmpty(keys)) return 0;keys.forEach((key, index) {key keyPrefix key;uni.removeStorageSync(key); // 同步删除});return keys.length;
}/*** 清空所有缓存*/
export const clearAll () {uni.clearStorageSync(); // 同步清除
}其他语言改造 vuevue中使用时需要将 uni.xxxStorage(...) 替换为localStorage 或者 sessionStorage html5和 vue 一样需要将 uni.xxxStorage(...) 替换为localStorage 或者 sessionStorage 微信小程序需要将 uni.xxxStorage(...) 替换为 wx.xxxStorage(...) localStorage和sessionStorage的区别 sessionStorage只在本次会话有效关闭浏览器数据将被删除 localStorage如果不手动删除则长期有效关闭浏览器数据也不会被清除