解決shiro redis 重寫sessiondao多次查詢Redis問題
doReadSession
doCreate
update
doReadSession
update
doReadSession
doReadSession
update
常常還出現這個異常
Caused by: org.apache.shiro.session.UnknownSessionException: There is no session with id [517a249d-f921-43c4-8c07-c9c6e4cfba73]
解決方式:
這個是shiro 設計上的問題, 主要是因為shiro 框架獲取 session裡面的屬性時,每次都去拿取session,一次請求中會有很多次 獲取 session 裡面的屬性。
我的解決思路是首先獲取Spring啟動後獲取可請求的地址,然後放到快取中,Shiro框架是基於過濾器實現的,我在進入Shiro的過濾器前先判定當前請求是否合法,如果合法的話,進入下一個過濾器,不合法的話返回提示,然後也不去Redis中進行查詢。
以下基於Spring Boot框架
1.建立一個監聽獲取Spring啟動後可訪問的地址
然後在SpringBoot啟動時註冊監聽package com.abroad.common.listener; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import com.abroad.common.cache.LocalCache; /** * 當容器啟動時獲取當前容器的可請求地址,並把它放到快取中 * * @ClassName: RequestURLListener * @Description: TODO() * @author: mengxr * @date 2017年3月29日 下午6:25:36 */ public class RequestUrlListener implements ApplicationListener<ContextRefreshedEvent> { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (event.getApplicationContext().getParent() == null) {// root application context 沒有parent,他就是老大. try { ApplicationContext applicationContext = event .getApplicationContext(); RequestMappingHandlerMapping bean = applicationContext .getBean(RequestMappingHandlerMapping.class); Set<String> result = new HashSet<String>(); Map<RequestMappingInfo, HandlerMethod> handlerMethods = bean .getHandlerMethods(); for (RequestMappingInfo rmi : handlerMethods.keySet()) { PatternsRequestCondition pc = rmi.getPatternsCondition(); Set<String> pSet = pc.getPatterns(); result.addAll(pSet); } LocalCache.ACCESS_URL.addAll(result); logger.info("-----------初始化RequestUrlListener成功 "); } catch (Exception e) { logger.error("-----------獲取RequestUrlListener失敗 ",e); } } } }
2.獲取到可訪問的URL地址後建立一個過濾器Filterpackage com.abroad; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.abroad.common.listener.RequestUrlListener; /** * @ClassName: SecurityApplication * @Description: TODO(許可權管理框架) * @author: mengxr * @date 2017年3月23日 上午10:52:13 */ @SpringBootApplication public class SecurityApplication { public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(SecurityApplication.class); springApplication.addListeners(new RequestUrlListener()); //新增一個啟動後監聽 springApplication.run(args); } }
package com.abroad.common.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abroad.common.cache.LocalCache;
import com.abroad.common.comn.ResponseJson;
import com.abroad.common.comn.StatusCode;
import com.abroad.common.comn.web.ServletTools;
/**
* @ClassName: AccessFilter
* @Description: TODO(訪問過濾器)
* @author: mengxr
* @date 2017年3月29日 下午6:08:54
*/
public class AccessFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String url = ServletTools.getContextPath((HttpServletRequest)request);
boolean flag = LocalCache.ACCESS_URL.contains(url);
if(flag){ //如果還有的話繼續走下一個過濾器
chain.doFilter(request, response);
}else{
//沒有找到相應的資源
ServletTools.sendResponse((HttpServletResponse) response, new ResponseJson(StatusCode.NOT_FOUND, false));
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("訪問過濾器AccessFilter註冊成功----");
}
@Override
public void destroy() {
logger.info("訪問過濾器AccessFilter摧毀成功-----");
}
}
SpringBoot註冊過濾器
package com.abroad.common.config;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import com.abroad.common.filter.AccessFilter;
/**
*
* @ClassName: AccessConfigue
* @Description: TODO(訪問控制)
* @author: mengxr
* @date 2017年3月29日 下午5:58:39
*/
@Configuration
public class AccessConfigue {
/**
* 由於shrio框架在每次請求的時候都要向快取查詢當前的Session效率十分低,並且shrio框架是基於過濾器實現的,
* 所以在進入shrioFilter前先對訪問的資料進行過濾,如果不存在的換直接跳轉到404狀態
* @Title: accessFilterRegistration
* @Description: TODO(這裡用一句話描述這個方法的作用)
* @param @return 設定檔案
* @return FilterRegistrationBean 返回型別
* @author: mengxr
* @date 2017年3月29日 下午6:03:17
* @throws
*/
@Bean
@Order(Integer.MAX_VALUE) //攔截器優先順序最高
public FilterRegistrationBean accessFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
AccessFilter accessFilter = new AccessFilter();
registration.setFilter(accessFilter);
registration.addUrlPatterns("/*");
registration.addInitParameter("paramName", "paramValue");
registration.setName("accessFilter");
return registration;
}
}
PS: 此處 @Order是攔截器的優先順序 要優於Shrio的攔截器先
3.啟動服務 發現AcceeFilter要由於shiroFilter先執行
4.測試結果 再次訪問URL後發現已不再進行Redis查詢
相關推薦
解決shiro redis 重寫sessiondao多次查詢Redis問題
發現 一直呼叫 sessiondao 的 doReadSession 方法 doReadSession doCreate update doReadSession update doReadSession doReadSession update 常常還
解決 springboot整合shiro,redis快取session 多次從redis獲取session問題
spring boot整合shiro redis快取session的教程很多,我這裡就不多說了,看了好多教程沒有解決快取session 多次從redis獲取session的問題,所以發表此部落格,希望對大家有所幫助。本人也是小白一個,如果有什麼問題還請各位大神多多指教
在同一事務中,mybatis多次查詢返回相同結果解決方法
一、問題描述: 使用spring @Transaction事務時,在for迴圈中需要多次執行同一查詢語句,第一次查詢出物件後,對物件進行修改後,結果再進行第二次查詢的時候,查詢返回的資料是自己第一次修改後的資料。因為業務需要每次查詢都需要取更改資料庫,以後的查詢都會根據上一次迴圈修改後的值進行操
優化 shiro 多次呼叫 redis 的問題
我們常使用 Shiro + redis 的組合解決叢集下的 Session 共享問題,這裡就不展開如何整合的問題了。 在進行日常優化的過程中,我通過日誌發現這麼一段日誌: 2017-09-17 15:16:07.723 -DEBUG [nio-8080-exec-6] o
解決Javascript中$(window).resize()多次執行(轉)
https://www.cnblogs.com/shuilangyizu/p/6816756.html 有些時候,我們需要在瀏覽器視窗發生變化的時候,動態的執行一些操作,比如做自適應頁面時的適配。這個時候,我們需要在視窗拖動的時候去執行程式碼。但是有些時候,執行的操作比較複雜,我們只希望在視窗拖動完畢之後,
【codeforces 617E XOR and Favorite Number】【莫隊分塊】【多次查詢求區間[l,r]中區間異或等於k的子區間個數】
【連結】 【題意】 給定一個數組,多次查詢,問區間l,r中有多少個子區間滿足區間異或為k 【思路】 查詢很大,意味著每次回答的時間複雜度不能太大。對於本題,我們可以維護一個字首異或,sum[i],區間[a,b]異或為k等價於sum[a-1]^sum[b]=k,假如
關聯查詢和多次查詢的點 以及 MySQL慢查詢優化 EXPLAIN詳解
對於欄位比較多的表,如果有些欄位的使用頻率很低,可以將這些欄位分離出來形成新表。因為當一個表的資料量很大時,會由於使用頻率低的欄位的存在而變慢。2. 增加中間表 對於需要經常聯合查詢的表,可以建立中間表以提高查詢效率。通過建立中間表,把需要經常聯合查詢的資料插入到中間表中,然後將
【微信小程式】下拉載入多次請求的解決方案,避免使用者多次發起請求降低業務處理。
方案一:小程式前端:做好請求判斷,請求前:設定常量變為0 ,觸發網路請求介面 常量變為 1,回撥成功常量設定 0 ,每次請求前判斷常量是否為 1,為1 即意味著上次請求回撥沒有接收到。防止多次請求。但是
徹底解決listview,gridview的getview多次呼叫問題
listview,gridview,有時候getview會呼叫多次,特別是把listview放在viewpager中,很容易卡頓 網上的方法往往只是說,把listview的height固定住或者fill_parent,其實這樣簡單的listview是有效的,但是item如
iOS解決按鈕短時間內多次點選只觸發一次事件方法(開始寫部落格)
在上家公司做專案的時候,做了個60秒獲取驗證碼的功能,當時做了個定時器,按鈕觸發定時器,邏輯來講都是沒問題的,但是實際操作的時候,惡意的在短時間內多次點選那個獲取驗證碼按鈕,按鈕的點選事件被呼叫了多次,定時器從而也呼叫多次,本來一秒減一的事件變成了一秒減多,並且減到0
iOS解決按鈕短時間內多次點擊只觸發一次事件方法
end bind nbsp per dos cancel span 內多 perf - (void)unisversalButtonAcrion:(UIButton *)sender { [[self class] cancelPreviousPerformReq
多次查詢一段區間內有多少個子區間滿足其中一個端點為區間最大值。
預處理 如果 哪些 class 每一個 祖先 href 貢獻 http 考慮維護出每一個點左邊第一個比它大的位置,右邊同理,這樣有一個合法區間。 然後對詢問離線,由於要求只包含區間內的貢獻,掃描線+線段樹解決。 T1 http://codeforces.com/proble
EntityFramework Core 3多次Include導致查詢效能低之解決方案
前言 上述我們簡單講解了幾個小問題,這節我們再來看看如標題EF Core中多次Include導致出現效能的問題,廢話少說,直接開門見山。 EntityFramework Core 3多次Include查詢問題 不要嫌棄我囉嗦,我們凡事從頭開始講解起,首先依然給出我們上一節的示例類: pub
使用fdmemTable來代替clientDataset,解決MySQL5.6(含)以上版本用cds多次更新時的錯誤
提交 sage string fdm pos final .text .post 1.5 //讀取mysql保存到fdMemTable中 procedure TForm3.btnOpen1Click(Sender: TObject);var stream, stream2
ubuntu 使用sudo apt-get update 出現 被配置多次導致無法升級錯誤解決方法
code 開發機 goup 使用 lin logs 配置 周末 ubun 這個周六周末在考慮升級自己GPU開發機,在琢磨使用docker來按轉tensorflow環境,在升級軟件的時候爆出了如下錯誤 在 /etc/apt/sources.list.d/sogoupin
android-繼承BaseAdapter--自己定義適配器,getView運行多次的解決方法
能夠 popu con data ssa baseadapt tracking you idt 定義的getView運行多次的ListView布局: <ListView android:id="@+id/lv_messages"
解決ASP.NET中ServiceStack.Redis每小時6000次訪問請求的問題
asp log style ack div net pre 小時 使用 1.可以使用3.0的版本: Install-Package ServiceStack.Redis -Version 3.0 2.使用ServiceStack.Redis.Complete: Ins
jq:mouseover和mouseout多次觸發解決辦法
mouseover ren div clas 結構 tro 需要 als ldr 區別: mouseover與mouseenter 不論鼠標指針穿過被選元素或其子元素,都會觸發 mouseover 事件。 只有在鼠標指針穿過被選元素時,才會觸發 mouseenter
C#中WebBrowser.DocumentCompleted事件多次調用問題解決方法
post lin ont display err 框架 center 一個 blank 關於DocumentCompleted事件,MSDN給出的解釋是在文檔加載完畢後執行,但是在我的程序中DocumentCompleted卻被多次調用,查了一下資料,大概出現了以下幾種情
解決一個特定的負載均衡下定時任務執行多次的問題
nginx負載均衡 項目 post 緩存 日期 多少 size edi 開始 項目每天晚上有個定時任務,把redis緩存數據重新連接數據庫刷新一遍,耗時大約40分鐘。但問題是項目是nginx負載均衡,這個定時任務會執行多次。經過一些思考之後,用以下辦法解決: redis裏加