我无法获得ZK会话超时,因为我们的应用程序每隔几分钟轮询一次服务器以获取信息。触发此轮询的代码是Javascript,它单击隐藏按钮,将onClick事件发送到服务器。
你知道有什么办法告诉ZK这个轮询是自动的,不应该影响会话超时计时器吗?
非常感谢。
-Ian
答案 0 :(得分:3)
简短回答是否定的。
答案很长,首先没有“ZK会议”。它只是由Servlet规范定义的HttpSession。其次,会话管理由servlet Web容器完成,因此在请求传递给ZK进行处理之前很久就完成了会话超时计数器重置。
答案 1 :(得分:3)
解决方法是编写一个过滤器来检测请求是否是该轮询请求,并在过滤器中记录“真实”请求的时间,如果长时间没有实际请求,则会使会话无效。
样品:
<强> 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() {}
}