本文主要介绍下spring boot中对session timeout参数值的设置过程。

ServerProperties

spring-boot-autoconfigure-1.5.8.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/web/ServerProperties.java

@Overridepublic void customize(ConfigurableEmbeddedServletContainer container) {if (getPort() != null) {container.setPort(getPort());}if (getAddress() != null) {container.setAddress(getAddress());}if (getContextPath() != null) {container.setContextPath(getContextPath());}if (getDisplayName() != null) {container.setDisplayName(getDisplayName());}if (getSession().getTimeout() != null) {container.setSessionTimeout(getSession().getTimeout());}//......}

对应的配置如下

server.session.timeout=120

需要注意单位是秒

TomcatEmbeddedServletContainerFactory

spring-boot-1.5.8.RELEASE-sources.jar!/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java

protected void configureContext(Context context,ServletContextInitializer[] initializers) {TomcatStarter starter = new TomcatStarter(initializers);if (context instanceof TomcatEmbeddedContext) {// Should be true((TomcatEmbeddedContext) context).setStarter(starter);}context.addServletContainerInitializer(starter, NO_CLASSES);for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {context.addLifecycleListener(lifecycleListener);}for (Valve valve : this.contextValves) {context.getPipeline().addValve(valve);}for (ErrorPage errorPage : getErrorPages()) {new TomcatErrorPage(errorPage).addToContext(context);}for (MimeMappings.Mapping mapping : getMimeMappings()) {context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());}configureSession(context);for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {customizer.customize(context);}}
private void configureSession(Context context) {long sessionTimeout = getSessionTimeoutInMinutes();context.setSessionTimeout((int) sessionTimeout);if (isPersistSession()) {Manager manager = context.getManager();if (manager == null) {manager = new StandardManager();context.setManager(manager);}configurePersistSession(manager);}else {context.addLifecycleListener(new DisablePersistSessionListener());}}
private long getSessionTimeoutInMinutes() {long sessionTimeout = getSessionTimeout();if (sessionTimeout > 0) {sessionTimeout = Math.max(TimeUnit.SECONDS.toMinutes(sessionTimeout), 1L);}return sessionTimeout;}

这里要注意一下,它内部转成分钟,然后设置给tomcat原生的StandardContext

可以从源码看到,如果设置小于60秒的话,则会默认取1分钟

StandardContext

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/core/StandardContext.java

@Overridepublic void setSessionTimeout(int timeout) {int oldSessionTimeout = this.sessionTimeout;/** SRV.13.4 ("Deployment Descriptor"):* If the timeout is 0 or less, the container ensures the default* behaviour of sessions is never to time out.*/this.sessionTimeout = (timeout == 0) ? -1 : timeout;support.firePropertyChange("sessionTimeout",oldSessionTimeout,this.sessionTimeout);}

这一步就是设置给原生的tomcat的StandardContext

session失效的计算

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/session/StandardSession.java

/*** Return the <code>isValid</code> flag for this session.*/@Overridepublic boolean isValid() {if (!this.isValid) {return false;}if (this.expiring) {return true;}if (ACTIVITY_CHECK && accessCount.get() > 0) {return true;}if (maxInactiveInterval > 0) {int timeIdle = (int) (getIdleTimeInternal() / 1000L);if (timeIdle >= maxInactiveInterval) {expire(true);}}return this.isValid;}

这里会去计算timeIdle,然后通过timeIdle的值跟设定的session timeout比较,超出则设置session失效

getIdleTimeInternal

   /*** Return the idle time from last client access time without invalidation check* @see #getIdleTime()*/@Overridepublic long getIdleTimeInternal() {long timeNow = System.currentTimeMillis();long timeIdle;if (LAST_ACCESS_AT_START) {timeIdle = timeNow - lastAccessedTime;} else {timeIdle = timeNow - thisAccessedTime;}return timeIdle;}

维护了两个变量,一个是lastAccessedTime,一个是thisAccessedTime

这个是在这个方法中更新

   /*** End the access.*/@Overridepublic void endAccess() {isNew = false;/*** The servlet spec mandates to ignore request handling time* in lastAccessedTime.*/if (LAST_ACCESS_AT_START) {this.lastAccessedTime = this.thisAccessedTime;this.thisAccessedTime = System.currentTimeMillis();} else {this.thisAccessedTime = System.currentTimeMillis();this.lastAccessedTime = this.thisAccessedTime;}if (ACTIVITY_CHECK) {accessCount.decrementAndGet();}}

正常请求更新

Http11Processor

tomcat-embed-core-8.5.23-sources.jar!/org/apache/coyote/http11/Http11Processor.java

    @Overridepublic SocketState service(SocketWrapperBase<?> socketWrapper)throws IOException {//......while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&sendfileState == SendfileState.DONE && !endpoint.isPaused()) {// ......// Process the request in the adapterif (!getErrorState().isError()) {try {rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);getAdapter().service(request, response);// Handle when the response was committed before a serious// error occurred.  Throwing a ServletException should both// set the status to 500 and set the errorException.// If we fail here, then the response is likely already// committed, so we can't try and set headers.if(keepAlive && !getErrorState().isError() && !isAsync() &&statusDropsConnection(response.getStatus())) {setErrorState(ErrorState.CLOSE_CLEAN, null);}} catch (InterruptedIOException e) {setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);} catch (HeadersTooLargeException e) {log.error(sm.getString("http11processor.request.process"), e);// The response should not have been committed but check it// anyway to be safeif (response.isCommitted()) {setErrorState(ErrorState.CLOSE_NOW, e);} else {response.reset();response.setStatus(500);setErrorState(ErrorState.CLOSE_CLEAN, e);response.setHeader("Connection", "close"); // TODO: Remove}} catch (Throwable t) {ExceptionUtils.handleThrowable(t);log.error(sm.getString("http11processor.request.process"), t);// 500 - Internal Server Errorresponse.setStatus(500);setErrorState(ErrorState.CLOSE_CLEAN, t);getAdapter().log(request, response, 0);}}// Finish the handling of the requestrp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);if (!isAsync()) {// If this is an async request then the request ends when it has// been completed. The AsyncContext is responsible for calling// endRequest() in that case.endRequest();}//......}//......}

这里的service方法在getErrorState().isError()为false的时候,会调用adapter的service方法

CoyoteAdapter

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/connector/CoyoteAdapter.java

    @Overridepublic void service(org.apache.coyote.Request req, org.apache.coyote.Response res)throws Exception {Request request = (Request) req.getNote(ADAPTER_NOTES);Response response = (Response) res.getNote(ADAPTER_NOTES);//...try {// Parse and set Catalina and configuration specific// request parameterspostParseSuccess = postParseRequest(req, request, res, response);if (postParseSuccess) {//check valves if we support asyncrequest.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());// Calling the containerconnector.getService().getContainer().getPipeline().getFirst().invoke(request, response);}if (request.isAsync()) {async = true;ReadListener readListener = req.getReadListener();if (readListener != null && request.isFinished()) {// Possible the all data may have been read during service()// method so this needs to be checked hereClassLoader oldCL = null;try {oldCL = request.getContext().bind(false, null);if (req.sendAllDataReadEvent()) {req.getReadListener().onAllDataRead();}} finally {request.getContext().unbind(false, oldCL);}}Throwable throwable =(Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);// If an async request was started, is not going to end once// this container thread finishes and an error occurred, trigger// the async error processif (!request.isAsyncCompleting() && throwable != null) {request.getAsyncContextInternal().setErrorState(throwable, true);}} else {request.finishRequest();response.finishResponse();}} catch (IOException e) {// Ignore} finally {//......// Recycle the wrapper request and responseif (!async) {request.recycle();response.recycle();}}}

会在finally里头调用request.recycle()

Request#recycle

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/connector/Request.java 里头的方法会调用recycleSessionInfo

protected void recycleSessionInfo() {if (session != null) {try {session.endAccess();} catch (Throwable t) {ExceptionUtils.handleThrowable(t);log.warn(sm.getString("coyoteRequest.sessionEndAccessFail"), t);}}session = null;requestedSessionCookie = false;requestedSessionId = null;requestedSessionURL = false;requestedSessionSSL = false;}

这里就更新了两个事件

forward中更新

适合处理error直接forward的情况,比如鉴权不通过,直接forward的,这个时候还没进入到servlet的service方法

ApplicationDispatcher#recycleRequestWrapper

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/core/ApplicationDispatcher.java

private void invoke(ServletRequest request, ServletResponse response,State state) throws IOException, ServletException {//......// Get the FilterChain HereApplicationFilterChain filterChain =ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);// Call the service() method for the allocated servlet instancetry {// for includes/forwardsif ((servlet != null) && (filterChain != null)) {filterChain.doFilter(request, response);}// Servlet Service Method is called by the FilterChain} catch (ClientAbortException e) {ioException = e;} catch (IOException e) {wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",wrapper.getName()), e);ioException = e;} catch (UnavailableException e) {wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",wrapper.getName()), e);servletException = e;wrapper.unavailable(e);} catch (ServletException e) {Throwable rootCause = StandardWrapper.getRootCause(e);if (!(rootCause instanceof ClientAbortException)) {wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",wrapper.getName()), rootCause);}servletException = e;} catch (RuntimeException e) {wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException",wrapper.getName()), e);runtimeException = e;}// Release the filter chain (if any) for this requesttry {if (filterChain != null)filterChain.release();} catch (Throwable e) {ExceptionUtils.handleThrowable(e);wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters",wrapper.getName()), e);// FIXME: Exception handling needs to be similar to what is in the StandardWrapperValue}// Deallocate the allocated servlet instancetry {if (servlet != null) {wrapper.deallocate(servlet);}} catch (ServletException e) {wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",wrapper.getName()), e);servletException = e;} catch (Throwable e) {ExceptionUtils.handleThrowable(e);wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException",wrapper.getName()), e);servletException = new ServletException(sm.getString("applicationDispatcher.deallocateException",wrapper.getName()), e);}// Reset the old context class loadercontext.unbind(false, oldCCL);// Unwrap request/response if needed// See Bugzilla 30949unwrapRequest(state);unwrapResponse(state);// Recycle request if necessary (also BZ 30949)recycleRequestWrapper(state);// ......}

执行完servlet之后(不管成功还是失败),会调用recycleRequestWrapper

private void recycleRequestWrapper(State state) {if (state.wrapRequest instanceof ApplicationHttpRequest) {((ApplicationHttpRequest) state.wrapRequest).recycle();        }}

tomcat-embed-core-8.5.23-sources.jar!/org/apache/catalina/core/ApplicationHttpRequest.java

    /*** Recycle this request*/public void recycle() {if (session != null) {session.endAccess();}}

这里会调用endAccess,更新两个时间

小结

  • 每次的请求,都会跟新session的lastAccessedTime和thisAccessedTime,只有没有访问超过设定时间才会失效
  • server.session.timeout设定的单位是秒,但是小于60的话,会被重置为60,内部转为分钟单位来算,默认1800是30分钟

聊聊springboot session timeout参数设置相关推荐

  1. java forward 修改请求参数_聊聊springboot session timeout参数设置

    序 本文主要介绍下spring boot中对session timeout参数值的设置过程. ServerProperties spring-boot-autoconfigure-1.5.8.RELE ...

  2. kafka 中参数:session.timeout.ms 和 heartbeat.interval.ms的区别

    文章目录 1.heartbeat.interval.ms 2.heartbeat.interval.ms 与 session.timeout.ms 的对比 3.session.timeout.ms 和 ...

  3. PHP的各种参数设置ini_set:内存 错误等级 session

    @ ini_set('memory_limit', '64M'); menory_limit:设定一个脚本所能够申请到的最大内存字节数,这有利于写的不好的脚本消耗服务器上的可 用内存.@符号代表不输出 ...

  4. 【SpringBoot】SpringBoot最精简的设置

    比较精简的SpringBoot2 设置,包含能力:提供RestFul.JDBC.Log4j2 POM文件设置: <parent><groupId>org.springframe ...

  5. springboot全局配置文件可设置的属性

    # =================================================================== #COMPON SPRING BOOT PROPERTIES ...

  6. mysql设置参数不生效_关于mysql的wait_timeout参数 设置不生效的问题【转】

    关于wait_timeout 有一次去online set wait_timeout 的时候发现改了不生效,如下: mysql> show variables like 'wait_timeou ...

  7. 关于mysql的wait_timeout参数 设置不生效的问题【转】

    关于wait_timeout 有一次去online set wait_timeout 的时候发现改了不生效,如下: mysql> show variables like 'wait_timeou ...

  8. SpringBoot 如何进行参数校验,老鸟们都这么玩的!

    大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...

  9. BIRT参数设置详解

    http://www.blogjava.net/huangzhanhu/archive/2010/02/03/311777.html 在使用birt报表的时候感觉页面的 BIRT Report Vie ...

  10. Birt 报表参数设置

    一.web.xml 1 <!-- 2 Default locale setting. 3 设置默认的Locale信息. 4 --> 5 <context-param> 6 &l ...

最新文章

  1. 2022入坑图像分割,我该从哪儿入手?
  2. centos 安装php5.6
  3. 第8章3节《MonkeyRunner源码剖析》 5
  4. Applese 的毒气炸弹
  5. 使用 ABAP 代码解析一个 class 的所有方法
  6. Idea新建modules后无法自动导入pom.xml
  7. C++描述杭电OJ 2009.求数列的和 ||
  8. [物理学与PDEs]第3章第3节 电导率 $\sigma$ 为无穷时的磁流体力学方程组 3.3 磁场线``冻结''原理...
  9. FPGA常用总线IIC 与SPI选择策略
  10. liunx安装Lamp
  11. MATLAB规划和LINGO规划,[数学建模]线性规划与matlab,lingo解法
  12. 三星note8android 9.0,三星S9/S9+计划明天推送安卓9.0正式版、S8/S8+、Note8下周推测试版...
  13. js移动端文字提示框
  14. Hubstudio指纹浏览器和MaxProxy代理的配置教程
  15. LeetCode #1056. Confusing Number
  16. 输出二叉树中从每个叶子结点到根结点的路径
  17. Cstyle的UEFI导读: UEFI的N种实现及差别
  18. foot元素一直浮在底层
  19. 微信小程序快递取件及上门服务
  20. 音乐发烧友私藏!这里有一份端午浓情大礼包!

热门文章

  1. android uid变化,在Android中安装期间确定应用的UID如何?
  2. php get安全过滤,php 有效安全过滤get,posd,cookie_PHP教程
  3. linux用户开放权限,linux权限设置(开放某个文件夹给指定用户)(示例代码)
  4. mysql会话杀不掉_SQL Server会话KILL不掉,一直处于KILLED /ROLLBACK状态情形浅析
  5. vue 图片服务器不显示,vue 打包放服务器,css样式不显示-Go语言中文社区
  6. wps分析工具库如何加载_怎么在wps表格里面加入“数据分析”工具啊?
  7. 用计算机探索奥秘规律例题,计算器指法练习题.doc
  8. 2017云栖大会门票转让_2018云栖大会门票价格及购买流程!附赠购买代金券
  9. java中bean的作用域有哪些_深入了解Spring中Bean的作用域和生命周期
  10. 液晶指定位置显示 c语言,大家看看该怎么改才能让12864液晶显示屏显示21个字符啊?...