1. 程式人生 > >springsession原始碼分析二之RedisHttpSessionConfiguration

springsession原始碼分析二之RedisHttpSessionConfiguration

SpringHttpSessionConfiguration

  1. SpringHttpSessionConfiguration是RedisHttpSessionConfiguration的父類
  2. 程式碼

    @Configuration
    public class SpringHttpSessionConfiguration {
    
        private CookieHttpSessionStrategy defaultHttpSessionStrategy = new CookieHttpSessionStrategy();
    
        private HttpSessionStrategy httpSessionStrategy = this
    .defaultHttpSessionStrategy; private List<HttpSessionListener> httpSessionListeners = new ArrayList<HttpSessionListener>(); private ServletContext servletContext; @Bean public SessionEventHttpSessionListenerAdapter sessionEventHttpSessionListenerAdapter() { return
    new SessionEventHttpSessionListenerAdapter(this.httpSessionListeners); } /*** SessionRepositoryFilter的Bean是在這裡被注入的 **/ @Bean public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter( SessionRepository<S> sessionRepository) { SessionRepositoryFilter<S> sessionRepositoryFilter = new
    SessionRepositoryFilter<S>( sessionRepository); sessionRepositoryFilter.setServletContext(this.servletContext); if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) { sessionRepositoryFilter.setHttpSessionStrategy( (MultiHttpSessionStrategy) this.httpSessionStrategy); } else { sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy); } return sessionRepositoryFilter; } @Autowired(required = false) public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } @Autowired(required = false) public void setCookieSerializer(CookieSerializer cookieSerializer) { this.defaultHttpSessionStrategy.setCookieSerializer(cookieSerializer); } @Autowired(required = false) public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) { this.httpSessionStrategy = httpSessionStrategy; } @Autowired(required = false) public void setHttpSessionListeners(List<HttpSessionListener> listeners) { this.httpSessionListeners = listeners; } }

RedisHttpSessionConfiguration

  1. 程式碼

            /**
            0.RedisHttpSessionConfiguration 是一個程式設計式註解
            1. @Configuration相當於xml中的<beans>標籤,使用AnnotationConfigApplicationContext讀取配置
            而xml使用ClassPathXmlApplicationContext讀取
            2. @EnableScheduling使用該註解讓Spring可以進行任務排程,功能類似於Spring的xml名稱空間<task:*>
            */
            @Configuration
            @EnableScheduling
            public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
                    implements ImportAware {
                //redis鍵的超時時間,即session,key的超時時間 
                private Integer maxInactiveIntervalInSeconds = 1800;
                /***
                *在Redis 2.8.0版本起,加入了“Keyspace notifications”(即“鍵空間通知”)的功能
                鍵空間通知,允許Redis客戶端從“釋出/訂閱”通道中建立訂閱關係,以便客戶端能夠在Redis中的資料因某種方式受到影響時收到相應事件
                在官方文件中,keyevent通道的格式永遠是這樣的:
            [email protected]<db>__:prefix
            對於資料過期事件,我們在繫結訂閱時通配模板也可以精確地寫成:
            [email protected]*__:expired
                **/
                private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction();
                //redis key的名稱空間 spring:session:<redisNamespace>
                private String redisNamespace = "";
                /**
                *ON_SAVE  當呼叫SessionRepository.save時候才被呼叫,web環境下就是響應提交的時候(預設)
                IMMEDIATE 當建立SessionRepository.createSession() 的時候或者給session設定屬性的時候立即存入redis
                *ON_SAVE Only writes to Redis when SessionRepository.save(org.springframework.session.Session) is invoked. In a web environment this is typically done as soon as the HTTP response is committed.
                IMMEDIATE Writes to Redis as soon as possible. For example SessionRepository.createSession() will write the session to Redis. Another example is that setting an attribute on the session will also write to Redis immediately.
                **/
                private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
                //序列化方式
                private RedisSerializer<Object> defaultRedisSerializer;
    
                private Executor redisTaskExecutor;
    
                private Executor redisSubscriptionExecutor;
    
                /**
                RedisMessageListenerContainer 表示訊息監聽容器
                **/
                @Bean
                public RedisMessageListenerContainer redisMessageListenerContainer(
                        RedisConnectionFactory connectionFactory,
                        RedisOperationsSessionRepository messageListener) {
    
                    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
                    container.setConnectionFactory(connectionFactory);
                    if (this.redisTaskExecutor != null) {
                        container.setTaskExecutor(this.redisTaskExecutor);
                    }
                    if (this.redisSubscriptionExecutor != null) {
                        container.setSubscriptionExecutor(this.redisSubscriptionExecutor);
                    }
                    /***
                    設定監聽器與釋出主題,主題名稱為 [email protected]*:del  [email protected]*:expired
                    ***/
                    container.addMessageListener(messageListener,
                            Arrays.asList(new PatternTopic("[email protected]*:del"),
                                    new PatternTopic("[email protected]*:expired")));
                    /***
                    * this.keyPrefix + "event:created:"+ "*";
                    **/
                    container.addMessageListener(messageListener, Arrays.asList(new PatternTopic(
                            messageListener.getSessionCreatedChannelPrefix() + "*")));
                    return container;
                }
    
                @Bean
                public RedisTemplate<Object, Object> sessionRedisTemplate(
                        RedisConnectionFactory connectionFactory) {
                    RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
                    template.setKeySerializer(new StringRedisSerializer());
                    template.setHashKeySerializer(new StringRedisSerializer());
                    if (this.defaultRedisSerializer != null) {
                        template.setDefaultSerializer(this.defaultRedisSerializer);
                    }
                    template.setConnectionFactory(connectionFactory);
                    return template;
                }
    
                @Bean
                public RedisOperationsSessionRepository sessionRepository(
                        @Qualifier("sessionRedisTemplate") RedisOperations<Object, Object> sessionRedisTemplate,
                        ApplicationEventPublisher applicationEventPublisher) {
                    RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
                            sessionRedisTemplate);
                    sessionRepository.setApplicationEventPublisher(applicationEventPublisher);
                    sessionRepository
                            .setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
                    if (this.defaultRedisSerializer != null) {
                        sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
                    }
    
                    String redisNamespace = getRedisNamespace();
                    if (StringUtils.hasText(redisNamespace)) {
                        sessionRepository.setRedisKeyNamespace(redisNamespace);
                    }
    
                    sessionRepository.setRedisFlushMode(this.redisFlushMode);
                    return sessionRepository;
                }
    
                public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
                    this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
                }
    
                public void setRedisNamespace(String namespace) {
                    this.redisNamespace = namespace;
                }
    
                public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
                    Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
                    this.redisFlushMode = redisFlushMode;
                }
    
                private String getRedisNamespace() {
                    if (StringUtils.hasText(this.redisNamespace)) {
                        return this.redisNamespace;
                    }
                    return System.getProperty("spring.session.redis.namespace", "");
                }
    
                public void setImportMetadata(AnnotationMetadata importMetadata) {
    
                    Map<String, Object> enableAttrMap = importMetadata
                            .getAnnotationAttributes(EnableRedisHttpSession.class.getName());
                    AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap);
                    this.maxInactiveIntervalInSeconds = enableAttrs
                            .getNumber("maxInactiveIntervalInSeconds");
                    this.redisNamespace = enableAttrs.getString("redisNamespace");
                    this.redisFlushMode = enableAttrs.getEnum("redisFlushMode");
                }
    
                @Bean
                public InitializingBean enableRedisKeyspaceNotificationsInitializer(
                        RedisConnectionFactory connectionFactory) {
                    return new EnableRedisKeyspaceNotificationsInitializer(connectionFactory,
                            this.configureRedisAction);
                }
    
                /**
                 * Sets the action to perform for configuring Redis.
                 *
                 * @param configureRedisAction the configureRedis to set. The default is
                 * {@link ConfigureNotifyKeyspaceEventsAction}.
                 */
                @Autowired(required = false)
                public void setConfigureRedisAction(ConfigureRedisAction configureRedisAction) {
                    this.configureRedisAction = configureRedisAction;
                }
                /**
                *如果需要覆蓋預設的Redis序列化實現類,在spring中將自己的實現類id設定為  springSessionDefaultRedisSerializer
                **/
                @Autowired(required = false)
                @Qualifier("springSessionDefaultRedisSerializer")
                public void setDefaultRedisSerializer(
                        RedisSerializer<Object> defaultRedisSerializer) {
                    this.defaultRedisSerializer = defaultRedisSerializer;
                }
            /**
                *如果需要覆蓋預設Redis任務多執行緒Executor,在spring中將自己的實現類id設定為springSessionRedisTaskExecutor
                **/
                @Autowired(required = false)
                @Qualifier("springSessionRedisTaskExecutor")
                public void setRedisTaskExecutor(Executor redisTaskExecutor) {
                    this.redisTaskExecutor = redisTaskExecutor;
                }
                /**
                *如果需要覆蓋預設訂閱任務多執行緒Executor,在spring中將自己的實現類id設定為   springSessionRedisSubscriptionExecutor
                **/
                @Autowired(required = false)
                @Qualifier("springSessionRedisSubscriptionExecutor")
                public void setRedisSubscriptionExecutor(Executor redisSubscriptionExecutor) {
                    this.redisSubscriptionExecutor = redisSubscriptionExecutor;
                }
    
                /**
                 * Ensures that Redis is configured to send keyspace notifications. This is important
                 * to ensure that expiration and deletion of sessions trigger SessionDestroyedEvents.
                 * Without the SessionDestroyedEvent resources may not get cleaned up properly. For
                 * example, the mapping of the Session to WebSocket connections may not get cleaned
                 * up.
                 */
                static class EnableRedisKeyspaceNotificationsInitializer implements InitializingBean {
                    private final RedisConnectionFactory connectionFactory;
    
                    private ConfigureRedisAction configure;
    
                    EnableRedisKeyspaceNotificationsInitializer(
                            RedisConnectionFactory connectionFactory,
                            ConfigureRedisAction configure) {
                        this.connectionFactory = connectionFactory;
                        this.configure = configure;
                    }
    
                    public void afterPropertiesSet() throws Exception {
                        RedisConnection connection = this.connectionFactory.getConnection();
                        this.configure.configure(connection);
                    }
                }
  2. 配置

            <bean id="redisHttpSessionConfiguration"
                class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
                <property name="maxInactiveIntervalInSeconds" value="${redis.session.time}" />
                <property name="redisNamespace" value="${redis.session.namespace}"/>
                <property name="cookieSerializer" ref="cookieSerializer" />
            </bean>
    
            <bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
                <property name="domainName" value="${cookie.domain}" />
                <property name="cookiePath" value="/" />
                <property name="cookieName" value="${cookie.cookieName}" />
            </bean>

相關推薦

springsession原始碼分析RedisHttpSessionConfiguration

SpringHttpSessionConfiguration SpringHttpSessionConfiguration是RedisHttpSessionConfiguration的父類 程式碼 @Configuration public cl

RxJava2原始碼分析just、fromArray、fromIterable

     Observable.just:接收1個以上,10個以下的引數,然後逐個發射。         Observable.fromArray:接收一個數組,從陣列中一個一個取出來發射。  

Redux原始碼分析()combineReducers

Redux原始碼分析(combineReducers) 上一篇我們看完了createStore這個自認為最為核心的檔案之後,我們再來看下combineReducers.js這個檔案,其他它最主要的作用就是合併多個reducer,因為在createStore中的第

OKHttp原始碼分析()RequestBody

一,概述 在上篇blog中以get請求為例分析了OKHttp框架的表層原始碼,具體參見:OKHttp原始碼分析(一) 在post請求中用到的API很大部分與get請求中用到的API相同,最大的不同就是Request.Builder類的post方法,這個方法的

springsession原始碼分析RedisOperationsSessionRepository

RedisOperationsSessionRepository uml 圖 MessageListener是redis訊息訂閱的監聽介面,SessionMessageListener 是過時的,已經被 RedisOperationsSes

原始碼分析String原始碼分析

    前面已經分析過String原始碼為什麼是不可變的,同時通過我們常用的String的相關的類StringBuffer和StringBuilder,我們可以發現String類中欄位名被定義為了final型別,這樣的話將只能被賦值一次。接下來,繼續看String原始碼實現的

UNIX v6原始碼分析除錯:單步除錯系統程式碼 main函式 kinit1

    環境搭建完成,該學習Main.c的main函數了。先貼上main函式的實現。int main(void) { kinit1(end, P2V(4*1024*1024)); // phys page allocator kvmalloc(); // k

Spring5原始碼深度分析()理解@Conditional,@Import註解

 程式碼地址:https://github.com/showkawa/spring-annotation/tree/master/src/main/java/com/brian 1.原始碼分析二主要分析的內容 1.使用@Condition多條件註冊bean物件2.@Import註解快速注入第三方

Qt update重新整理原始碼分析()

大家好,我是IT文藝男,來自一線大廠的一執行緒序員 上次視訊給大家從原始碼層面剖析了Qt update重新整理機制的非同步事件投遞過程,這次視訊主要從原始碼層面剖析Qt重新整理事件(QEvent::UpdateRequest)的處理過程 我們追蹤QEvent::UpdateRequest事件處理,進入訊息

NSQ原始碼分析()—— Topic

Topic是NSQ非常重要的概念,本次主要講述Topic的獲取、新建、Topic中訊息的輪詢、Topic中訊息的來源、Topic的刪除和退出以及Topic的暫停和取消暫停 topic的相關操作主要在nsq/nsqd/topic.go中 首先看下Topic結構體 type Topic st

Django rest framework 許可權操作(原始碼分析)

知識回顧  這一篇是基於上一篇寫的,上一篇謝了認證的具體流程,看懂了上一篇這一篇才能看懂, 當用戶訪問是 首先執行dispatch函式,當執行當第二部時: #2.處理版本資訊 處理認證資訊 處理許可權資訊 對使用者的訪問頻率進行限制 self

Dubbo 原始碼分析系列三 —— 架構原理

1 核心功能 首先要了解Dubbo提供的三大核心功能: Remoting:遠端通訊 提供對多種NIO框架抽象封裝,包括“同步轉非同步”和“請求-響應”模式的資訊交換方式。 Cluster: 服務框架 提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及

Elastic-Job原始碼解析()定時核心實現quartz

Elastic-Job是一個分散式定時任務框架,其內部的定時主要是利用quartz來實現,而Elastic-Job核心是對quartz進行了封裝,並提供了分散式任務的功能。具體是怎麼實現呢? 怎麼實現分散式呢? 主要是通過Zookeeper通訊,獲取任務伺服器ip地址,並通

Java程式設計師從笨鳥到菜鳥(八十一)細談Spring(十)深入原始碼分析SpringHibernateTemplate

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

spring原始碼分析():外部配置檔案的載入

@PropertySource 和@Profile 簡介: @PropertySource:用在類上,載入一個(*.properties)的配置檔案 @Profile:用在類或者方法上,指定元件在哪個環境的情況下才能被註冊到容器中,不指定,任何環境下都能註冊這個元件 使用案例1-

spring原始碼分析():bean元件賦值

文章目錄 常用註解 @Value和@PropertySource 介紹 使用案例 @AutoWired、@Qulifer 、@Primary 介紹 使用總結

Tomcat 原始碼分析系列環境搭建

Tomcat 原始碼環境搭建 tomcat 9 和 idea 環境搭建 環境準備 JDK 1.10 git idea tomcat 原始碼 maven ant 國內的maven 倉庫映象 安裝Intellij Idea 新

原始碼分析手寫springvc

1.先建立maven的web專案,結構如下 2.在web.xml新增如下配置 <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>com.mayik

jQuery2.0.3原始碼分析系列(29) 視窗尺寸

.width() 基礎回顧 一般的,在獲取瀏覽器視窗的大小和位置時,有以下幾個屬性可以使用: 在不同的瀏覽器中,以下12個屬性所代表的意義也是不一樣的 特別需要注意的是,當使用或者不使用<!DOCTYPE>宣告顯示一個文件的時候,以上12個屬性的意義也會發生變化。 特在IE 9中

最新版ffmpeg原始碼分析:transcode()函式

還是先看一下主函式吧:(省略了很多無關大雅的程式碼) int main(int argc, char **argv) { OptionsContext o = { 0 }; int64_t ti; //與命令列分析有關