ホームページ  >  記事  >  Java  >  SpringBootのセッションタイムアウト問題の原因を詳しく解説

SpringBootのセッションタイムアウト問題の原因を詳しく解説

巴扎黑
巴扎黑オリジナル
2018-05-10 13:49:595472ブラウズ

この記事では、SpringBoot のセッション タイムアウト原理の詳細な説明を主に紹介します。編集者が非常に優れていると考えたので、参考として共有します。編集者をフォローして一緒に見てみましょう

1: はじめに:

一定期間決済バックエンドにログインした後に操作がない場合は、操作を行う前に必ず再度ログインする必要があります。この問題の原因は、セッションがタイムアウトしたためです。コードをデバッグしたところ、セッション タイムアウトが 1800 秒であることがわかりました。つまり、1800 秒以内に操作がない場合、セッションはタイムアウトになります。では、このタイムアウトはどのように設定されるのでしょうか?では、このタイムアウトをリセットするにはどうすればよいでしょうか?セッションがタイムアウトしたとき、システムはどのように判断するのでしょうか?それでは、一つずつお答えしていきます。

2: システムセッションタイムアウトはデフォルトでどのように設定されますか?

説明: セッションタイムアウトを取得するメソッドは「request.getSession().getMaxInactiveInterval()」ですが、Tomcatのタイムアウトを設定するパラメータは「sessionTimeout」なので、どのように接続されているのでしょうか?

ステップ 1: 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」インターフェースを継承します。カスタマイズ メソッドを書き換えて、このメソッドを「プッシュ」して「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.「Container.addInitializers(new SessionCconfiguringInitializer(this.session))」のステップ 2 を実行して、すべての設定をロードします。パラメーター 。

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;
 }

ステップ 2: 上記のタイムアウト期間を「MaxInactiveInterval」パラメータに割り当てます。

注: 上記の Tomcat に必要なパラメータはすべてロードされているため、次に Tomcat が実行されます。ここでは詳細には触れず、Tomcat の起動とパラメータのロードの説明に直接進みます。 「TomcatEmbeddedServletContainerFactory」クラスのメソッド呼び出し処理は

getEmbeddedServletContainer--》prepareContext--》configureContext--》configureSession--》getSessionTimeoutInMinutesとなります。

1. configureSession を呼び出して、tomcat

//以下代码
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 に割り当てます。ようやくセッションタイムアウトの設定が完了しました。

//以下代码
@Override
public void setContext(Context context) {
 //省略其余设置代码,直接重新设置Session超时时间,此时又将上面的分钟单位转为秒。此时终于给Sesseion设置了默认超时时间。
 if (this.context != null) {
  setMaxInactiveInterval(this.context.getSessionTimeout() * 60);
  this.context.addPropertyChangeListener(this);
 }
}

3: タイムアウトがカスタマイズされている場合はどうなりますか?

実際、上記のプロセスから、「org.springframework.boot.autoconfigure.web.ServerProperties」クラスで対応するセッションパラメータを見つけて初期化し、実行するだけでよいことがわかります。ロードすると設定が完了します。

/**
 * 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();
}

なので、アプリケーション内で「server.session.timeout」を設定するだけです。パラメータの型はlong型で、単位は「秒」です。

4: 実行中のプログラムはセッションのタイムアウトをどのように決定しますか?

これは実際には非常に簡単です。毎回同じセッションリクエストの時間を前回のリクエスト時間と比較し、2 つの値の差が 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;
}

説明:

したがって、セッションタイムアウトを確実に長くするには、アプリケーション構成ファイルで「server.session.timeout」パラメータを設定できます。パラメータの単位は「秒」です。 60 の整数倍ではありません。60 の整数倍に変換されます (2: システムによるタイムアウトの設定方法と、ステップ 2 の「1」のアルゴリズムを参照)。 1分未満の場合は60秒に換算されます。

拡張:

実際、割り当てのために EmbeddedServletContainerCustomizer のカスタマイズ メソッドを直接オーバーライドすることもできます。

りー

以上がSpringBootのセッションタイムアウト問題の原因を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。