spring-session-data-redis自動配置原理

1. 導(dǎo)入庫文件

implementation 'org.springframework.session:spring-session-data-redis
于是org.springframework.boot.autoconfigure.session.SessionAutoConfiguration就生效了崭闲,

2 SessionAutoConfiguration分析

里面有這個一段

        @Configuration(proxyBeanMethods = false)
        @ConditionalOnMissingBean(SessionRepository.class)
        @Import({ ServletSessionRepositoryImplementationValidator.class,
                ServletSessionConfigurationImportSelector.class })
        static class ServletSessionRepositoryConfiguration {

        }

通過@import引入了ServletSessionConfigurationImportSelector泽艘,這個類繼承SessionConfigurationImportSelector

    static class ServletSessionConfigurationImportSelector extends SessionConfigurationImportSelector {

        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return super.selectImports(WebApplicationType.SERVLET);
        }

    }

最終執(zhí)行完后参滴,會在SessionStoreMappingsMAPPINGS中找到RedisSessionConfiguration并倒入到容器中

    static {
        Map<StoreType, Configurations> mappings = new EnumMap<>(StoreType.class);
        mappings.put(StoreType.REDIS,
                new Configurations(RedisSessionConfiguration.class, RedisReactiveSessionConfiguration.class));
        mappings.put(StoreType.MONGODB,
                new Configurations(MongoSessionConfiguration.class, MongoReactiveSessionConfiguration.class));
        mappings.put(StoreType.JDBC, new Configurations(JdbcSessionConfiguration.class, null));
        mappings.put(StoreType.HAZELCAST, new Configurations(HazelcastSessionConfiguration.class, null));
        mappings.put(StoreType.NONE,
                new Configurations(NoOpSessionConfiguration.class, NoOpReactiveSessionConfiguration.class));
        MAPPINGS = Collections.unmodifiableMap(mappings);
    }

3. RedisSessionConfiguration作用分析

RedisSessionConfiguration中有一個靜態(tài)內(nèi)部類SpringBootRedisHttpSessionConfiguration繼承自RedisHttpSessionConfiguration,RedisHttpSessionConfiguration又繼承了SpringHttpSessionConfiguration類饼煞,
兩個父類中注冊了很多組建域那,關(guān)鍵就是RedisIndexedSessionRepositorySessionRepositoryFilter類剥险。

    @Configuration(proxyBeanMethods = false)
    public static class SpringBootRedisHttpSessionConfiguration extends RedisHttpSessionConfiguration {

        @Autowired
        public void customize(SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties,
                ServerProperties serverProperties) {
            Duration timeout = sessionProperties
                    .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout());
            if (timeout != null) {
                setMaxInactiveIntervalInSeconds((int) timeout.getSeconds());
            }
            setRedisNamespace(redisSessionProperties.getNamespace());
            setFlushMode(redisSessionProperties.getFlushMode());
            setSaveMode(redisSessionProperties.getSaveMode());
            setCleanupCron(redisSessionProperties.getCleanupCron());
        }

    }

RedisHttpSessionConfiguration中注冊RedisIndexedSessionRepository組件

    @Bean
    public RedisIndexedSessionRepository sessionRepository() {
        RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
        RedisIndexedSessionRepository sessionRepository = new RedisIndexedSessionRepository(redisTemplate);
        sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
        if (this.indexResolver != null) {
            sessionRepository.setIndexResolver(this.indexResolver);
        }
        if (this.defaultRedisSerializer != null) {
            sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
        }
        sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
        if (StringUtils.hasText(this.redisNamespace)) {
            sessionRepository.setRedisKeyNamespace(this.redisNamespace);
        }
        sessionRepository.setFlushMode(this.flushMode);
        sessionRepository.setSaveMode(this.saveMode);
        int database = resolveDatabase();
        sessionRepository.setDatabase(database);
        this.sessionRepositoryCustomizers
                .forEach((sessionRepositoryCustomizer) -> sessionRepositoryCustomizer.customize(sessionRepository));
        return sessionRepository;
    }

RedisIndexedSessionRepository用來生成桦锄、保存session睬棚。
SpringHttpSessionConfiguration中注冊SessionRepositoryFilter
SpringHttpSessionConfiguration中注冊SessionRepositoryFilter組件

    @Bean
    public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(
            SessionRepository<S> sessionRepository) {
        SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);
        sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
        return sessionRepositoryFilter;
    }

SessionRepositoryFilterConfiguration類中,有這樣一段代碼

    @Bean
    FilterRegistrationBean<SessionRepositoryFilter<?>> sessionRepositoryFilterRegistration(
            SessionProperties sessionProperties, SessionRepositoryFilter<?> filter) {
        FilterRegistrationBean<SessionRepositoryFilter<?>> registration = new FilterRegistrationBean<>(filter);
        registration.setDispatcherTypes(getDispatcherTypes(sessionProperties));
        registration.setOrder(sessionProperties.getServlet().getFilterOrder());
        return registration;
    }

最終將SessionRepositoryFilter注冊到servlet容器杜秸。這個SessionRepositoryFilter類很關(guān)鍵放仗,它將HttpServletRequest包裝成SessionRepositoryRequestWrapper,HttpServletResponse包裝成SessionRepositoryResponseWrapper,SessionRepositoryRequestWrapperpublic HttpSessionWrapper getSession(boolean create),以后調(diào)用getSession等方法亩歹,就被攔截了匙监,就會去RedisIndexedSessionRepository中保存、生成session小作。

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);

        SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);
        SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,
                response);

        try {
            filterChain.doFilter(wrappedRequest, wrappedResponse);
        }
        finally {
            wrappedRequest.commitSession();
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亭姥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子顾稀,更是在濱河造成了極大的恐慌达罗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件静秆,死亡現(xiàn)場離奇詭異粮揉,居然都是意外死亡,警方通過查閱死者的電腦和手機抚笔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門扶认,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人殊橙,你說我怎么就攤上這事辐宾。” “怎么了膨蛮?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵叠纹,是天一觀的道長。 經(jīng)常有香客問我敞葛,道長誉察,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任惹谐,我火速辦了婚禮持偏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘豺鼻。我一直安慰自己综液,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布儒飒。 她就那樣靜靜地躺著谬莹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上附帽,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天埠戳,我揣著相機與錄音,去河邊找鬼蕉扮。 笑死整胃,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的喳钟。 我是一名探鬼主播屁使,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奔则!你這毒婦竟也來了蛮寂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤易茬,失蹤者是張志新(化名)和其女友劉穎酬蹋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抽莱,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡范抓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了食铐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匕垫。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虐呻,靈堂內(nèi)的尸體忽然破棺而出年缎,到底是詐尸還是另有隱情,我是刑警寧澤铃慷,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蜕该,受9級特大地震影響犁柜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堂淡,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一馋缅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绢淀,春花似錦萤悴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春硝全,著一層夾襖步出監(jiān)牢的瞬間栖雾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工伟众, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留析藕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓凳厢,卻偏偏與公主長得像账胧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子先紫,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容