




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
若依框架(ruoyi)Vue3+ElementPlus移除Redis緩存方案(完整步驟)目錄一、 背景介紹 2二、 部署問(wèn)題 2三、 需要解決的問(wèn)題 3四、 實(shí)施步驟 31. 更改ruoyi-admin目錄下application.yml文件 32. 更改ruoyi-framework下的RedisConfig文件 33. 修改RedisCache類 64. 登錄校驗(yàn)時(shí)刪除過(guò)期緩存,防止占用內(nèi)存 85. 處理用戶信息垃圾緩存問(wèn)題 96. 處理在線用戶列表 97. 處理緩存讀取問(wèn)題 108. 更改SysConfigServiceImpl文件 129. 去掉redisCache.setCacheObject方法后兩個(gè)參數(shù) 1310. 處理異常問(wèn)題 13五、 項(xiàng)目啟動(dòng)效果圖 14六、 系統(tǒng)擴(kuò)展集成了MybatisPlus 14背景介紹公司運(yùn)維的某些項(xiàng)目需要進(jìn)行“國(guó)產(chǎn)化”改造,經(jīng)過(guò)反復(fù)技術(shù)選型,終合考慮了技術(shù)的先進(jìn)性、可維護(hù)性,并著重考慮后期能更好地進(jìn)行二次開(kāi)發(fā),最終選擇了若依(RuoYI)這個(gè)開(kāi)源框架,這個(gè)框架的Vue3版本,核心使用了Vue3、ElementPlus、Vite構(gòu)建工具等相對(duì)較新的技術(shù),無(wú)關(guān)的功能相對(duì)較少,通過(guò)對(duì)其改造,在此基礎(chǔ)上進(jìn)行二次開(kāi)發(fā)后,有助于掌握當(dāng)前主流的開(kāi)發(fā)技術(shù)和構(gòu)建模式,能夠?yàn)楣镜钠渌?xiàng)目后續(xù)改造儲(chǔ)備相關(guān)技術(shù)。部署問(wèn)題項(xiàng)目部署過(guò)程依據(jù)官方文檔還算順利,但編譯和啟動(dòng)過(guò)程中,總是提示在6379端口的服務(wù)啟動(dòng)失敗,后來(lái)知道是redis緩存服務(wù)的原因,因?yàn)榇蟛糠猪?xiàng)目比較小,沒(méi)有并發(fā)問(wèn)題需要考慮,如果再部署Redis服務(wù)器的話,無(wú)疑增加了額外的運(yùn)維成本和不穩(wěn)定性,于是決定采用ConcurrentHashMap對(duì)其進(jìn)行替換,但在實(shí)際操作過(guò)程中遇到了不少問(wèn)題,網(wǎng)上查的的解決方案沒(méi)有一個(gè)是完整可用的,所以在成功解決這個(gè)問(wèn)題后,就此形成一個(gè)完整的記錄文檔,供有此需求的人參考。需要解決的問(wèn)題用ConcurrentHashMap替換后,項(xiàng)目運(yùn)行不能有任何報(bào)錯(cuò)系統(tǒng)緩存模塊和在線用戶模塊能正常顯示數(shù)據(jù)解決ConcurrentHashMap非正常退出所產(chǎn)生的冗余緩存等一系列不合理問(wèn)題實(shí)施步驟更改ruoyi-admin目錄下application.yml文件注釋掉文件內(nèi)的redis配置,如下圖更改ruoyi-framework下的RedisConfig文件注釋掉@Bean、@Configuration和@EnableCaching注解在ruoyi-common的core/redis下新建MyCache類packagemon.core.redis;
importorg.springframework.cache.Cache;
importorg.springframework.cache.support.SimpleValueWrapper;
importorg.springframework.stereotype.Component;
importjava.util.Collection;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Objects;
importjava.util.concurrent.Callable;
importjava.util.concurrent.ConcurrentHashMap;
@Component
publicclassMyCacheimplementsCache{
privateMap<String,Object>storage=newConcurrentHashMap<>();
/**
*每個(gè)緩存生效時(shí)間12小時(shí)
*/
//publicstaticfinallongCACHE_HOLD_TIME_12H=12*60*60*1000L;
@Override
publicStringgetName(){
returnnull;
}
@Override
publicObjectgetNativeCache(){
returnnull;
}
@Override
public<T>Tget(Objectkey,Class<T>type){
returnnull;
}
@Override
public<T>Tget(Objectkey,Callable<T>valueLoader){
returnnull;
}
@Override
publicvoidclear(){
}
publicbooleanhasKey(Stringkey){
returnstorage.containsKey(key);
}
@Override
publicValueWrapperget(Objectkey){
Stringk=key.toString();
Objectvalue=storage.get(k);
//注意返回的數(shù)據(jù),要和存放時(shí)接收到數(shù)據(jù)保持一致,要將數(shù)據(jù)反序列化回來(lái)。
returnObjects.isNull(value)?null:newSimpleValueWrapper(value);
}
@Override
publicvoidput(Objectkey,Objectvalue){
if(Objects.isNull(value)){
return;
}
storage.put(key.toString(),value);
}
@Override
publicvoidevict(Objectkey){
storage.remove(key.toString());
}
//刪除集合
publicbooleandeleteObject(Collection<String>collection){
collection.forEach(item->{
storage.remove(item);
});
returntrue;
}
//獲取所有的keys
publicCollection<String>keys(finalStringpattern){
//editbywjl鍵值查詢
StringpatternStr=pattern.replace(":","");
Map<String,Object>myMap=newHashMap<>();
Collection<String>keys=storage.keySet();
for(Stringkey:keys){
if(key.contains(patternStr)){
myMap.put(key,storage.get(key));
}
}
returnmyMap.keySet();
}
}修改RedisCache類整個(gè)文件,使用下面代碼段覆蓋packagemon.core.redis;
importjava.util.Collection;
importjava.util.concurrent.TimeUnit;
importorg.springframework.cache.Cache;
importorg.springframework.stereotype.Component;
importjavax.annotation.Resource;
/**
*springredis工具類
*
*@authorruoyi
**/
@SuppressWarnings(value={"unchecked","rawtypes"})
@Component
publicclassRedisCache
{
@Resource
publicMyCachemyCache;
/**
*緩存基本的對(duì)象,Integer、String、實(shí)體類等
*
*@paramkey緩存的鍵值
*@paramvalue緩存的值
*/
public<T>voidsetCacheObject(finalStringkey,finalTvalue)
{
myCache.put(key,value);
}
/**
*判斷key是否存在
*
*@paramkey鍵
*@returntrue存在false不存在
*/
publicBooleanhasKey(Stringkey)
{
returnmyCache.hasKey(key);
}
/**
*獲得緩存的基本對(duì)象。
*
*@paramkey緩存鍵值
*@return緩存鍵值對(duì)應(yīng)的數(shù)據(jù)
*/
public<T>TgetCacheObject(finalStringkey)
{
Cache.ValueWrappervalueWrapper=myCache.get(key);
if(valueWrapper==null){
returnnull;
}else{
return(T)valueWrapper.get();
}
}
/**
*刪除單個(gè)對(duì)象
*
*@paramkey
*/
publicbooleandeleteObject(finalStringkey)
{
myCache.evict(key);
returntrue;
}
/**
*刪除集合對(duì)象
*
*@paramcollection多個(gè)對(duì)象
*@return
*/
publicbooleandeleteObject(finalCollectioncollection)
{
returnmyCache.deleteObject(collection);
}
/**
*獲得緩存的基本對(duì)象列表
*
*@parampattern字符串前綴
*@return對(duì)象列表
*/
publicCollection<String>keys(finalStringpattern)
{
returnmyCache.keys(pattern);
}
}登錄校驗(yàn)時(shí)刪除過(guò)期緩存,防止占用內(nèi)存更改ruoyi-framework目錄下web/service/TokenService文件,使用下面方法替換原有方法/**
*驗(yàn)證令牌有效期,相差不足20分鐘,自動(dòng)刷新緩存
*
*@paramloginUser
*@return令牌
*/
publicvoidverifyToken(LoginUserloginUser)
{
longexpireTime=loginUser.getExpireTime();
longcurrentTime=System.currentTimeMillis();
if(expireTime-currentTime<0){
//editbywjl過(guò)期刪除token
StringuserKey=getTokenKey(loginUser.getToken());
redisCache.deleteObject(userKey);
thrownewServiceException("登錄超時(shí)",HttpStatus.UNAUTHORIZED);
}
elseif(expireTime-currentTime<=MILLIS_MINUTE_TEN)
{
refreshToken(loginUser);
}
}處理用戶信息垃圾緩存問(wèn)題繼續(xù)更改上一條修改過(guò)的TokenService文件,修改文件當(dāng)中的createToken(LoginUserloginUser)方法保證每個(gè)用戶只緩存一個(gè)鍵值對(duì),防止反復(fù)登錄或直接關(guān)閉瀏覽器產(chǎn)生垃圾緩存//Stringtoken=IdUtils.fastUUID();
Stringtoken="WF"+String.format("%08d",loginUser.getUserId());處理在線用戶列表更改ruoyi-admin目錄下\src\main\java\com\ruoyi\web\controller\monitor\SysUserOnlineController.java文件,找到下面方法,可直接替換publicTableDataInfolist(Stringipaddr,StringuserName)
{
Collection<String>keys=redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY);
List<SysUserOnline>userOnlineList=newArrayList<SysUserOnline>();
for(Stringkey:keys)
{
//editbywjl在線用戶
if(key.indexOf(CacheConstants.LOGIN_TOKEN_KEY)>-1){
LoginUseruser=redisCache.getCacheObject(key);
if(StringUtils.isNotEmpty(ipaddr)&&StringUtils.isNotEmpty(userName))
{
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr,userName,user));
}
elseif(StringUtils.isNotEmpty(ipaddr))
{
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr,user));
}
elseif(StringUtils.isNotEmpty(userName)&&StringUtils.isNotNull(user.getUser()))
{
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName,user));
}
else
{
userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
}
}
}
Collections.reverse(userOnlineList);
userOnlineList.removeAll(Collections.singleton(null));
returngetDataTable(userOnlineList);
}處理緩存讀取問(wèn)題更改ruoyi-admin目錄下com\ruoyi\web\controller\monitor\CacheController.java由于更改太多,直接使用下面整個(gè)類替換packagecom.ruoyi.web.controller.monitor;
importjava.util.ArrayList;
importjava.util.Collection;
importjava.util.List;
importcom.alibaba.fastjson2.JSON;
importmon.core.redis.RedisCache;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.security.access.prepost.PreAuthorize;
importorg.springframework.web.bind.annotation.DeleteMapping;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.PathVariable;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
importmon.constant.CacheConstants;
importmon.core.domain.AjaxResult;
importcom.ruoyi.system.domain.SysCache;
/**
*緩存監(jiān)控
*
*@authorruoyi
*/
@RestController
@RequestMapping("/monitor/cache")
publicclassCacheController
{
@Autowired
privateRedisCacheredisCache;
privatefinalstaticList<SysCache>caches=newArrayList<SysCache>();
{
caches.add(newSysCache(CacheConstants.LOGIN_TOKEN_KEY,"用戶信息"));
caches.add(newSysCache(CacheConstants.SYS_CONFIG_KEY,"配置信息"));
caches.add(newSysCache(CacheConstants.SYS_DICT_KEY,"數(shù)據(jù)字典"));
caches.add(newSysCache(CacheConstants.CAPTCHA_CODE_KEY,"驗(yàn)證碼"));
caches.add(newSysCache(CacheConstants.REPEAT_SUBMIT_KEY,"防重提交"));
caches.add(newSysCache(CacheConstants.RATE_LIMIT_KEY,"限流處理"));
caches.add(newSysCache(CacheConstants.PWD_ERR_CNT_KEY,"密碼錯(cuò)誤次數(shù)"));
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getNames")
publicAjaxResultcache()
{
returnAjaxResult.success(caches);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getKeys/{cacheName}")
publicAjaxResultgetCacheKeys(@PathVariableStringcacheName)
{
//editbywjl緩存列表
Collection<String>keys=redisCache.keys(cacheName);
returnAjaxResult.success(keys);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getValue/{cacheName}/{cacheKey}")
publicAjaxResultgetCacheValue(@PathVariableStringcacheName,@PathVariableStringcacheKey)
{
//editbywjl通過(guò)鍵值獲取緩存
ObjectcacheValue=redisCache.getCacheObject(cacheKey);
SysCachesysCache=newSysCache(cacheName,cacheKey,JSON.toJSONString(cacheValue));
returnAjaxResult.success(sysCache);
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheName/{cacheName}")
publicAjaxResultclearCacheName(@PathVariableStringcacheName)
{
Collection<String>cacheKeys=redisCache.keys(cacheName+"*");
redisCache.deleteObject(cacheKeys);
returnAjaxResult.success();
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheKey/{cacheKey}")
publicAjaxResultclearCacheKey(@PathVariableStringcacheKey)
{
redisCache.deleteObject(cacheKey);
returnAjaxResult.success();
}
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@DeleteMapping("/clearCacheAll")
publicAjaxResultclearCacheAll()
{
Collection<String>cacheKeys=redisCache.keys("*");
redisCache.deleteObject(cacheKeys);
returnAjaxResult.success();
}
}更改SysConfigServiceImpl文件在ruoyi-system目錄下@Override
publicStringselectConfigByKey(StringconfigKey)
{
//StringconfigValue=Convert.toStr(redisCache.getCacheObject(getCacheKey(configK
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 影像科CT技師上崗證真題與答案
- 游客行為分析優(yōu)化旅游服務(wù)
- 企業(yè)培訓(xùn)課件價(jià)值觀
- 企業(yè)培訓(xùn)技巧課件
- 英語(yǔ)全能閱讀強(qiáng)化練(十五)
- 優(yōu)化外資利用結(jié)構(gòu)改進(jìn)措施
- 企業(yè)培訓(xùn)車輛無(wú)償借用及管理合同
- 美容養(yǎng)生連鎖店按摩技師團(tuán)隊(duì)承包合同
- 高效采購(gòu)合同談判策略與標(biāo)的物協(xié)議
- 彩票站與彩票代銷商代理合作協(xié)議
- 2025明光事業(yè)單位筆試真題
- 2025房縣事業(yè)單位筆試真題
- DBJ50T-195-2025 混凝土抗壓強(qiáng)度檢測(cè)技術(shù)標(biāo)準(zhǔn)
- 《南昌市海綿城市建設(shè)規(guī)劃設(shè)計(jì)導(dǎo)則》
- 牙齒漂白治療技術(shù)操作指南
- 道路施工工藝培訓(xùn)
- 2025-2030全球及中國(guó)乙酰檸檬酸三丁酯(ATBC)行業(yè)市場(chǎng)現(xiàn)狀供需分析及市場(chǎng)深度研究發(fā)展前景及規(guī)劃可行性分析研究報(bào)告
- 克羅恩病診斷與治療課件
- 2025濟(jì)寧市泗水縣泗河街道社區(qū)工作者考試真題
- 初二化學(xué)全套試題及答案
- 核心素養(yǎng)教學(xué)落地四大關(guān)鍵策略
評(píng)論
0/150
提交評(píng)論