日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jeesite缓存问题

發布時間:2023/11/30 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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、前端

  • JS框架:jQuery 1.9。

  • CSS框架:Twitter Bootstrap 2.3.1。

  • 客戶端驗證:JQuery Validation Plugin 1.11。

  • 富文本:CKEcitor

  • 文件管理:CKFinder

  • 動態頁簽:Jerichotab

  • 手機端框架:Jingle

  • 數據表格:jqGrid

  • 對話框:jQuery jBox

  • 下拉選擇框:jQuery Select2

  • 樹結構控件:jQuery zTree

  • 日期控件: My97DatePicker



這里對于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)?{??
  • ??
  • ??????????
  • ????????//判斷是否有權限修改用戶信息??
  • ??????????
  • ????????//先清緩存:因為框架原因,只要更新了該用戶,則會同步更新該用戶緩存,從而無法獲得真正的該用戶信息,所以需要清除掉該緩存,這里先注釋掉,看問題??
  • ????????//UserUtils.clearCache(user);??
  • ????????User?oldUser?=?systemService.getUser(user.getId());??
  • ????????List<String>roleIdListOld?=?oldUser.getRoleIdList();??
  • ????????User?operator?=?UserUtils.getUser();??
  • ????????List<String>roleIdListOperator?=?operator.getRoleIdList();??
  • ????????//自己不能修改自己的權限??
  • //??????if(user.getId().equals(operator.getId())){??
  • //??????????addMessage(model,?"修改用戶信息失敗,?不能修改自己的權限");??
  • //??????????UserUtils.clearCache();??
  • //??????????return?form(oldUser,?model);??
  • //??????????}??
  • ????????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();??
  • ????????????//UserUtils.getCacheMap().clear();??
  • ????????}??
  • ????????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)?{??
  • ??????????
  • ????????//先清除該user的緩存,防止干擾到其他地方的引用。其實還是會有并發問題,會在清除之前被引用到??
  • ????????UserUtils.clearCache(user);??
  • ????????????????//從db中獲取user,注意這個userSave?是修改前的,與user的值不一樣,注意一點:如果直接從getUser(user.getId());中獲取,同時并沒有清緩存的前提下??
  • ????????????????//UserUtils.clearCache(user);則會導致拿到的user并非DB里的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
  • /**?
  • ?*?根據ID獲取用戶——通過DB?
  • ?*?@param?id?
  • ?*?@return?取不到返回null?
  • ?*/??
  • public?static?User?getUserFromDB(String?id){??
  • ??
  • ????User?user?=?userDao.get(id);??
  • ????user.setRoleList(roleDao.findList(new?Role(user)));??
  • ????return?user;??
  • }??


  • 因此特別需要注意緩存的使用,不是任何地方都適合使用緩存。

    0

    總結

    以上是生活随笔為你收集整理的jeesite缓存问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。