生活随笔
收集整理的這篇文章主要介紹了
jeesite缓存问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?jeesite,其框架主要為:
后端
-
核心框架:Spring Framework 4.0
-
安全框架:Apache Shiro 1.2
-
視圖框架:Spring MVC 4.0
-
服務端驗證:Hibernate Validator 5.1
-
布局框架:SiteMesh 2.4
-
工作流引擎:Activiti 5.15、FoxBPM 6
-
任務調度:Spring Task 4.0
-
持久層框架:MyBatis 3.2
-
數據庫連接池:Alibaba Druid 1.0
-
緩存框架:Ehcache 2.6、Redis
-
日志管理:SLF4J 1.7、Log4j
-
工具類:Apache Commons、Jackson 2.2、Xstream 1.4、Dozer 5.3、POI 3.9
2、前端
這里對于jeesite,感覺其功能還是挺強大的,但是有一點致命缺點,就是其緩存機制,本來緩存是為了提速,但是,當這里的緩存加上了MVC,并且在前端進行請求后,不適時宜地將請求的相關類對象進行緩存,這就導致了單例化和偽持久化。怎么說來?就是說,當前端修改Person對象實例,并提交到服務端試圖保存時,由于某些原因,如權限不足導致保存失敗,這本來應該是很正常的,但是,偏偏由于在這之前,緩存將Person對象實例更新了,從而緩存中的該實例是修改后的,這樣,后來再次獲取該對象,由于緩存存在,優先取緩存而不是從DB里獲取,導致,后來獲取的對象的數據都是錯誤的(修改但保存失敗的),這就變相單例化,而且是無法獲得正確數據了。
例如如下的接口
[java]?view plain
?copy @RequiresPermissions("sys:user:edit")?? ????@RequestMapping(value?=?"save")?? ????public?String?save(User?user,?HttpServletRequest?request,?Model?model,?RedirectAttributes?redirectAttributes)?{?? ?? ?????????? ?????????? ?????????? ?????????? ?????????? ????????User?oldUser?=?systemService.getUser(user.getId());?? ????????List<String>roleIdListOld?=?oldUser.getRoleIdList();?? ????????User?operator?=?UserUtils.getUser();?? ????????List<String>roleIdListOperator?=?operator.getRoleIdList();?? ?????????? ?? ?? ?? ?? ?? ????????if(!roleIdListOperator.containsAll(roleIdListOld)){?? ????????????addMessage(model,?"修改用戶信息失敗,?您的權限不足");?? ????????????UserUtils.clearCache();?? ????????????return?form(oldUser,?model);?? ????????}?? ????????user.setRoleList(roleList);?? ?????????? ????????systemService.saveUser(user);?? ?????????? ????????if?(user.getPhone().equals(UserUtils.getUser().getPhone())){?? ????????????UserUtils.clearCache();?? ?????????????? ????????}?? ????????addMessage(redirectAttributes,?"保存用戶'"?+?user.getPhone()?+?"'成功");?? ????????return?"redirect:"?+?adminPath?+?"/sys/user/list?repage";?? ????}?? 再看下getUser:
[java]?view plain
?copy public?static?User?getUser(String?id){?? ????User?user?=?(User)CacheUtils.get(USER_CACHE,?USER_CACHE_ID_?+?id);?? ????if?(user?==??null){?? ????????user?=?userDao.get(id);?? ????????if?(user?==?null){?? ????????????return?null;?? ????????}?? ????????user.setRoleList(roleDao.findList(new?Role(user)));?? ????????CacheUtils.put(USER_CACHE,?USER_CACHE_ID_?+?user.getId(),?user);?? ????????CacheUtils.put(USER_CACHE,?USER_CACHE_LOGIN_NAME_?+?user.getPhone(),?user);?? ????}?? ????return?user;?? }?? 這里的
[java]?view plain
?copy systemService.getUser(user.getId());?? 會一直拿到該對象實例的緩存值,而該值,在修改提交到服務端時,框架已經更新了,再進到controller中。
所以,即使在
[java]?view plain
?copy if(!roleIdListOperator.containsAll(roleIdListOld)){?? ????????????addMessage(model,?"修改用戶信息失敗,?您的權限不足");?? ????????????UserUtils.clearCache();?? ????????????return?form(oldUser,?model);?? ????????}?? 這里返回了,其他地方獲取該user的值
[java]?view plain
?copy getUser(user.getId());?? 還是會是緩存的值。
也相當于單例的、全局的實例值
解決方法:
在關系到修改等的地方,每次都需要對該實例進行緩存的清空。同時,在修改時,修改對象最好就是拿出db的該記錄,逐個參數進行修改替換:
[java]?view plain
?copy @RequiresPermissions("user:list:edit")?? ????@RequestMapping(value?=?"editUserInfoSave")?? ????public?String?editUserInfoSave(User?user,Model?model,?RedirectAttributes?redirectAttributes)?{?? ?????????? ?????????? ????????UserUtils.clearCache(user);?? ?????????????????? ?????????????????? ????????????????User?userSave?=?systemService.getUserFromDB(user.getId());?? ????????? ? ?? ????????userSave.setName(user.getName());?? ????????userSave.setFirstnameStr(user.getFirstnameStr());?? ????????userSave.setLastnameStr(user.getLastnameStr());?? ????????userSave.setIdStr(user.getIdStr());?? ????????userSave.setUsername(user.getUsername());?? ????????userSave.setBirthdateStr(user.getBirthdateStr());?? ????????userSave.setEmail(user.getEmail());?? ????????userSave.setUserType(user.getUserType());?? ????????userSave.setGenderStr(user.getGenderStr());?? ?????????? ????????systemService.saveUser(userSave);?? ????????addMessage(redirectAttributes,?"保存用戶'"?+?user.getPhone()?+?"'成功");?? ????????return?"redirect:"?+?adminPath?+?"/user/user/list?repage";?? ????}?? 這里的getUserFromDB:
[java]?view plain
?copy ? ? ? ? ?? public?static?User?getUserFromDB(String?id){?? ?? ????User?user?=?userDao.get(id);?? ????user.setRoleList(roleDao.findList(new?Role(user)));?? ????return?user;?? }?? 因此特別需要注意緩存的使用,不是任何地方都適合使用緩存。
頂
0 踩
總結
以上是生活随笔為你收集整理的jeesite缓存问题的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。