アプリケーションが数分ごとにサーバーに情報をポーリングするため、ZK セッションのタイムアウトが発生しません。このポーリングをトリガーするコードは、非表示のボタンをクリックして onClick イベントをサーバーに送信する Javascript です。
このポーリングが自動化されており、セッション タイムアウト タイマーに影響を与えるべきではないことを ZK に伝える方法を知っていますか?
どうもありがとう。
-イアン
アプリケーションが数分ごとにサーバーに情報をポーリングするため、ZK セッションのタイムアウトが発生しません。このポーリングをトリガーするコードは、非表示のボタンをクリックして onClick イベントをサーバーに送信する Javascript です。
このポーリングが自動化されており、セッション タイムアウト タイマーに影響を与えるべきではないことを ZK に伝える方法を知っていますか?
どうもありがとう。
-イアン
簡単な答えはノーです。
長い答えは、まず第一に「ZK セッション」がないということです。これは、サーブレット仕様で定義されている単なる HttpSession です。次に、セッション管理はサーブレット Web コンテナによって行われるため、リクエストが処理のために ZK に渡されるずっと前に、セッション タイムアウト カウンタのリセットが行われます。
回避策は、リクエストがそのポーリング リクエストであるかどうかを検出するフィルタを作成し、「実際の」リクエストの時間をフィルタに記録してから、長時間実際のリクエストがない場合はセッションを無効にすることです。
サンプル:
test.zul
<zk>
<intbox id="ibx" value="1" />
<timer delay="1000" id="pooltimer" repeats="true">
<attribute name="onTimer"><![CDATA[
ibx.setValue(ibx.getValue() + 1);
]]></attribute>
</timer>
<button label="click or invalidated in 20 seconds">
<attribute name="onClick"><![CDATA[
long lastRealRequest = (Long)Sessions.getCurrent().getAttribute("LAST_REAL_REQUEST");
alert("only pooling request in "
+ ((System.currentTimeMillis() - lastRealRequest) / 1000)
+ " second(s)");
]]></attribute>
</button>
</zk>
zk.xml
<zk>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
</zk>
web.xml のフィルタ
<filter>
<filter-name>requestFilter</filter-name>
<filter-class>test.RequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
RequestFilter.java
package test;
import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class RequestFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
Map param = req.getParameterMap();
HttpSession sess = req.getSession();
boolean isRealRequest = true;
// here detect whether it is the poll request
// initiate the LAST_REAL_REQUEST if the poll request is
// the first request
//
// invalidate session if no real request within session timeout range
for (Object key : param.keySet()) {
if (key.toString().startsWith("cmd")
&& "onTimer".equals(((String[])param.get(key))[0])) {
// not real request
isRealRequest = false;
// try get last real request time
Long lastRealRequest = (Long)sess.getAttribute("LAST_REAL_REQUEST");
if (lastRealRequest == null) {
System.out.println("init");
// init if no previous real request
lastRealRequest = System.currentTimeMillis();
sess.setAttribute("LAST_REAL_REQUEST", lastRealRequest);
} else if ((System.currentTimeMillis() - lastRealRequest) > 20000) {
System.out.println("invalidate");
// invalidate session if only poll request for a long time
sess.invalidate();
}
}
}
// process request
chain.doFilter(request, response);
// update LAST_REAL_REQUEST if this is a real request
if (isRealRequest) {
// record last real request time
sess.setAttribute("LAST_REAL_REQUEST", System.currentTimeMillis());
}
}
@Override
public void destroy() {}
}