JAVA语言之详解SpringBoot中Session超时原理说明
龚超 2018-07-24 来源 : 阅读 1010 评论 0

摘要:本文主要向大家介绍了JAVA语言的SpringBoot中Session超时原理说明,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言的SpringBoot中Session超时原理说明,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

一:前言:

最近支付后台登录一段时间后如果没有任何操作,总是需要重新登录才可以继续访问页面,出现这个问题的原因就是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 ServerProperties

implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {

//代码

}

复制代码

2、上面类中“ServerProperties”继承自“EmbeddedServletContainerCustomizer”接口。重写customize方法,之后在此方法中“向上推”,即可找到“AbstractConfigurableEmbeddedServletContainer ”类。


@Override

public void customize(ConfigurableEmbeddedServletContainer container) {

//多个参数判断,如果在application中没配置的情况下都是null

if (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 {[url=home.php?mod=space&uid=24691]@code[/url] 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方法进行赋值。


@Bean

public EmbeddedServletContainerCustomizer containerCustomizer(){

return new EmbeddedServletContainerCustomizer() {

@Override

public void customize(ConfigurableEmbeddedServletContainer container) {

container.setSessionTimeout(600);//单位为S

}

};

}

希望对JAVA有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言JAVA频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长针对企业软件开发的产品设计及开发的细节与流程设计课程内容。座右铭:大道至简!

  • 370
    文章
  • 23119
    人气
  • 87%
    受欢迎度

已有23人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
WEB前端必须会的基本知识题目
经验技巧 93% 的用户喜欢
Java语言中四种遍历List的方法总结(推荐)
经验技巧 91% 的用户喜欢
Java语言之SHA-256加密的两种实现方法详解
经验技巧 75% 的用户喜欢
java语言实现把两个有序数组合并到一个数组的实例
经验技巧 75% 的用户喜欢
通过Java语言代码来创建view的方法
经验技巧 80% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
周鸣君
周鸣君 联系TA
擅长Hadoop/Spark大数据技术
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程