javascript
SpringBoot中Session超时原理说明
一:前言:
最近支付后臺登錄一段時間后如果沒有任何操作,總是需要重新登錄才可以繼續訪問頁面,出現這個問題的原因就是session超時,debug代碼后發現session的超時時間是1800s。也就是說當1800秒內沒有任何操作,session就會出現超時現象。那這個超時時間是如何設置的呢?然后該如何重新設置此超時時間呢?系統又如何判斷session超時的呢?接下來就一一進行解答。
二:系統session超時時間如何默認的?
說明:獲取session超時時間的方法為”request.getSession().getMaxInactiveInterval()",但是tomcat中設置超時時間的參數為“sessionTimeout”,那么他們是怎么聯系起來的呢?
第一步:加載sessionTimeout參數。
? 1、項目運行初始化通過“@ConfigurationProperties”注解加載“org.springframework.boot.autoconfigure.web.ServerProperties”類。
| //springBoot中默認的配置文件為"application.yml"或者"application.perties"文件,也就是說server是其中的一個配置參數。 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerPropertiesimplements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered { //代碼 } |
2、上面類中“ServerProperties”繼承自“EmbeddedServletContainerCustomizer”接口。重寫customize方法,之后在此方法中“向上推”,即可找到“AbstractConfigurableEmbeddedServletContainer ?”類。
| @Override public void customize(ConfigurableEmbeddedServletContainer container) {//多個參數判斷,如果在application中沒配置的情況下都是nullif (getPort() != null) {container.setPort(getPort());}...//n多個參數判斷,//以下的代碼就是重點,因為是tomcat容器,所以以下條件為“真”,經過一系列的查找父類或者實現接口即可找到抽象類“AbstractConfigurableEmbeddedServletContainer”//public class TomcatEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware//public abstract class AbstractEmbeddedServletContainerFactory extends AbstractConfigurableEmbeddedServletContainer implements EmbeddedServletContainerFactory if (container instanceof TomcatEmbeddedServletContainerFactory) {getTomcat().customizeTomcat(this,(TomcatEmbeddedServletContainerFactory) container);} //以上代碼執行完成之后,實際上已經有對應的session所有的默認參數,之后通過下面方法,將所有參數放入對應的容器中。第3、4步就是設置過程container.addInitializers(new SessionConfiguringInitializer(this.session)); } |
3、在“AbstractConfigurableEmbeddedServletContainer”類中終于可以找到“超時時間”的相關設置
| //重要代碼 //45行 private static final int DEFAULT_SESSION_TIMEOUT = (int) TimeUnit.MINUTES.toSeconds(30); //66行 private int sessionTimeout = DEFAULT_SESSION_TIMEOUT;@Override public void setSessionTimeout(int sessionTimeout) {this.sessionTimeout = sessionTimeout; } //171-188行 @Override public void setSessionTimeout(int sessionTimeout, TimeUnit timeUnit) {Assert.notNull(timeUnit, "TimeUnit must not be null");this.sessionTimeout = (int) timeUnit.toSeconds(sessionTimeout); }/*** Return the session timeout in seconds.* @return the timeout in seconds*/ public int getSessionTimeout() {return this.sessionTimeout; } |
4、執行第2步的”container.addInitializers(new SessionConfiguringInitializer(this.session))“加載所有的配置參數。
| public static class Session {/*** Session timeout in seconds.*/private Integer timeout;public Integer getTimeout() {return this.timeout;} //將session超時時間設置進來public void setTimeout(Integer sessionTimeout) {this.timeout = sessionTimeout;} |
第二步:將上面的超時時間賦值給“MaxInactiveInterval”參數。
說明:既然上面tomcat需要的參數都已經加載完成,那么接下來就會運行tomcat,此處不做細講,直接進入tomcat啟動和加載參數說明。在“TomcatEmbeddedServletContainerFactory”類中的方法調用流程如下:
getEmbeddedServletContainer--》prepareContext--》configureContext--》configureSession--》getSessionTimeoutInMinutes。
1、調用configureSession設置tomcat的Session配置參數。
| //以下代碼 private void configureSession(Context context) {long sessionTimeout = getSessionTimeoutInMinutes();context.setSessionTimeout((int) sessionTimeout);Manager manager = context.getManager();if (manager == null) {manager = new StandardManager();//此處即為設置相應的參數的位置。之后會調用StandardContext類的setManger(Manager)方法,在setManger中會調用"manager.setContext(this)"context.setManager(manager);} } //計算超時時間為分鐘(注意:此處會將之前的1800秒,轉換為30分鐘)。可以看出最終的時間結果是個整數的分鐘類型,也就是說如果設置的超時時間(單位為秒)不是60的倍數,也會最終轉換為60的倍數,并且最小超時時間設置的是60秒。 private long getSessionTimeoutInMinutes() {long sessionTimeout = getSessionTimeout();if (sessionTimeout > 0) {sessionTimeout = Math.max(TimeUnit.SECONDS.toMinutes(sessionTimeout), 1L);}return sessionTimeout; } |
2、最終將SessionTimeout賦值給MaxInactiveInterval。終于完成session超時時間設置。
| //以下代碼 @Override public void setContext(Context context) {//省略其余設置代碼,直接重新設置Session超時時間,此時又將上面的分鐘單位轉為秒。此時終于給Sesseion設置了默認超時時間。if (this.context != null) {setMaxInactiveInterval(this.context.getSessionTimeout() * 60);this.context.addPropertyChangeListener(this);} } |
三:如果自定義超時時間呢?
其實從上面的流程,已經不難看出,只需要在“org.springframework.boot.autoconfigure.web.ServerProperties”類中找到對應的Session參數,初始化讓其加載上來即可完成設置。
| /*** Get the session timeout.* @return the session timeout* @deprecated since 1.3.0 in favor of {@code session.timeout}.*/ @Deprecated @DeprecatedConfigurationProperty(replacement = "server.session.timeout") public Integer getSessionTimeout() {return this.session.getTimeout(); } |
所以在application中配置“server.session.timeout“即可,參數類型為long類型,單位為”秒“。
四:運行程序是如何判斷session超時的?
其實很簡單:只需要在每次本次同一個sessionequest請求的時間,和之前的請求時間進行比較,發現兩個值的差已經大于MaxInactiveInterval的值即可。
| //判斷是否超時 @Override public boolean isValid() {//省略多個條件判斷if (maxInactiveInterval > 0) {//判斷此session空閑時間是否比maxInactiveInterval大,如果大的情況下,session就超時int timeIdle = (int) (getIdleTimeInternal() / 1000L);if (timeIdle >= maxInactiveInterval) {expire(true);}}return this.isValid; } //將上次訪問時間和當前時間比較,拿到空閑時間值 @Override public long getIdleTimeInternal() {long timeNow = System.currentTimeMillis();long timeIdle;if (LAST_ACCESS_AT_START) {timeIdle = timeNow - lastAccessedTime;} else {timeIdle = timeNow - thisAccessedTime;}return timeIdle; } |
說明:
所以為了保證session超時時間長點,可以在application配置文件中配置“server.session.timeout”參數即可,參數單位為“秒”,如果參數不是60的整數倍,會轉換成60的整數倍(見二:系統如何設置超時時間、步驟二中的“1”中算法)。如不滿一分鐘,會轉換為60秒。
擴展:
實際上也可以直接重寫EmbeddedServletContainerCustomizer的customize方法進行賦值。
| @Beanpublic EmbeddedServletContainerCustomizer containerCustomizer(){return new EmbeddedServletContainerCustomizer() {@Overridepublic void customize(ConfigurableEmbeddedServletContainer container) {container.setSessionTimeout(600);//單位為S}};} |
總結
以上是生活随笔為你收集整理的SpringBoot中Session超时原理说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第三十二期:MySQL常见的图形化工具
- 下一篇: Java线程之多线程与多进程(3)——J