一:前言:
10多年的撫順網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營銷網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整撫順建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“撫順網(wǎng)站設(shè)計(jì)”,“撫順網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
最近支付后臺登錄一段時(shí)間后如果沒有任何操作,總是需要重新登錄才可以繼續(xù)訪問頁面,出現(xiàn)這個(gè)問題的原因就是session超時(shí),debug代碼后發(fā)現(xiàn)session的超時(shí)時(shí)間是1800s。也就是說當(dāng)1800秒內(nèi)沒有任何操作,session就會出現(xiàn)超時(shí)現(xiàn)象。那這個(gè)超時(shí)時(shí)間是如何設(shè)置的呢?然后該如何重新設(shè)置此超時(shí)時(shí)間呢?系統(tǒng)又如何判斷session超時(shí)的呢?接下來就一一進(jìn)行解答。
二:系統(tǒng)session超時(shí)時(shí)間如何默認(rèn)的?
說明:獲取session超時(shí)時(shí)間的方法為”request.getSession().getMaxInactiveInterval()",但是tomcat中設(shè)置超時(shí)時(shí)間的參數(shù)為“sessionTimeout”,那么他們是怎么聯(lián)系起來的呢?
第一步:加載sessionTimeout參數(shù)。
1、項(xiàng)目運(yùn)行初始化通過“@ConfigurationProperties”注解加載“org.springframework.boot.autoconfigure.web.ServerProperties”類。
//springBoot中默認(rèn)的配置文件為"application.yml"或者"application.perties"文件,也就是說server是其中的一個(gè)配置參數(shù)。 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public class ServerProperties implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered { //代碼 }
2、上面類中“ServerProperties”繼承自“EmbeddedServletContainerCustomizer”接口。重寫customize方法,之后在此方法中“向上推”,即可找到“AbstractConfigurableEmbeddedServletContainer ”類。
@Override public void customize(ConfigurableEmbeddedServletContainer container) { //多個(gè)參數(shù)判斷,如果在application中沒配置的情況下都是null if (getPort() != null) { container.setPort(getPort()); } ...//n多個(gè)參數(shù)判斷, //以下的代碼就是重點(diǎn),因?yàn)槭莟omcat容器,所以以下條件為“真”,經(jīng)過一系列的查找父類或者實(shí)現(xiàn)接口即可找到抽象類“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); } //以上代碼執(zhí)行完成之后,實(shí)際上已經(jīng)有對應(yīng)的session所有的默認(rèn)參數(shù),之后通過下面方法,將所有參數(shù)放入對應(yīng)的容器中。第3、4步就是設(shè)置過程 container.addInitializers(new SessionConfiguringInitializer(this.session)); }
3、在“AbstractConfigurableEmbeddedServletContainer”類中終于可以找到“超時(shí)時(shí)間”的相關(guān)設(shè)置
//重要代碼 //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、執(zhí)行第2步的”Container.addInitializers(new SessionConfiguringInitializer(this.session))“加載所有的配置參數(shù)。
public static class Session { /** * Session timeout in seconds. */ private Integer timeout; public Integer getTimeout() { return this.timeout; } //將session超時(shí)時(shí)間設(shè)置進(jìn)來 public void setTimeout(Integer sessionTimeout) { this.timeout = sessionTimeout; }
第二步:將上面的超時(shí)時(shí)間賦值給“MaxInactiveInterval”參數(shù)。
說明:既然上面tomcat需要的參數(shù)都已經(jīng)加載完成,那么接下來就會運(yùn)行tomcat,此處不做細(xì)講,直接進(jìn)入tomcat啟動和加載參數(shù)說明。在“TomcatEmbeddedServletContainerFactory”類中的方法調(diào)用流程如下:
getEmbeddedServletContainer--》prepareContext--》configureContext--》configureSession--》getSessionTimeoutInMinutes。
1、調(diào)用configureSession設(shè)置tomcat的Session配置參數(shù)。
//以下代碼 private void configureSession(Context context) { long sessionTimeout = getSessionTimeoutInMinutes(); context.setSessionTimeout((int) sessionTimeout); Manager manager = context.getManager(); if (manager == null) { manager = new StandardManager(); //此處即為設(shè)置相應(yīng)的參數(shù)的位置。之后會調(diào)用StandardContext類的setManger(Manager)方法,在setManger中會調(diào)用"manager.setContext(this)" context.setManager(manager); } } //計(jì)算超時(shí)時(shí)間為分鐘(注意:此處會將之前的1800秒,轉(zhuǎn)換為30分鐘)。可以看出最終的時(shí)間結(jié)果是個(gè)整數(shù)的分鐘類型,也就是說如果設(shè)置的超時(shí)時(shí)間(單位為秒)不是60的倍數(shù),也會最終轉(zhuǎn)換為60的倍數(shù),并且最小超時(shí)時(shí)間設(shè)置的是60秒。 private long getSessionTimeoutInMinutes() { long sessionTimeout = getSessionTimeout(); if (sessionTimeout > 0) { sessionTimeout = Math.max(TimeUnit.SECONDS.toMinutes(sessionTimeout), 1L); } return sessionTimeout; }
2、最終將SessionTimeout賦值給MaxInactiveInterval。終于完成session超時(shí)時(shí)間設(shè)置。
//以下代碼 @Override public void setContext(Context context) { //省略其余設(shè)置代碼,直接重新設(shè)置Session超時(shí)時(shí)間,此時(shí)又將上面的分鐘單位轉(zhuǎn)為秒。此時(shí)終于給Sesseion設(shè)置了默認(rèn)超時(shí)時(shí)間。 if (this.context != null) { setMaxInactiveInterval(this.context.getSessionTimeout() * 60); this.context.addPropertyChangeListener(this); } }
三:如果自定義超時(shí)時(shí)間呢?
其實(shí)從上面的流程,已經(jīng)不難看出,只需要在“org.springframework.boot.autoconfigure.web.ServerProperties”類中找到對應(yīng)的Session參數(shù),初始化讓其加載上來即可完成設(shè)置。
/** * 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“即可,參數(shù)類型為long類型,單位為”秒“。
四:運(yùn)行程序是如何判斷session超時(shí)的?
其實(shí)很簡單:只需要在每次本次同一個(gè)sessionequest請求的時(shí)間,和之前的請求時(shí)間進(jìn)行比較,發(fā)現(xiàn)兩個(gè)值的差已經(jīng)大于MaxInactiveInterval的值即可。
//判斷是否超時(shí) @Override public boolean isValid() { //省略多個(gè)條件判斷 if (maxInactiveInterval > 0) { //判斷此session空閑時(shí)間是否比maxInactiveInterval大,如果大的情況下,session就超時(shí) int timeIdle = (int) (getIdleTimeInternal() / 1000L); if (timeIdle >= maxInactiveInterval) { expire(true); } } return this.isValid; } //將上次訪問時(shí)間和當(dāng)前時(shí)間比較,拿到空閑時(shí)間值 @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超時(shí)時(shí)間長點(diǎn),可以在application配置文件中配置“server.session.timeout”參數(shù)即可,參數(shù)單位為“秒”,如果參數(shù)不是60的整數(shù)倍,會轉(zhuǎn)換成60的整數(shù)倍(見二:系統(tǒng)如何設(shè)置超時(shí)時(shí)間、步驟二中的“1”中算法)。如不滿一分鐘,會轉(zhuǎn)換為60秒。
擴(kuò)展:
實(shí)際上也可以直接重寫EmbeddedServletContainerCustomizer的customize方法進(jìn)行賦值。
@Bean public EmbeddedServletContainerCustomizer containerCustomizer(){ return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setSessionTimeout(600);//單位為S } }; }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
當(dāng)前題目:詳解SpringBoot中Session超時(shí)原理說明
標(biāo)題來源:http://bm7419.com/article16/jciidg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、動態(tài)網(wǎng)站、網(wǎng)站排名、響應(yīng)式網(wǎng)站、網(wǎng)頁設(shè)計(jì)公司、移動網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)