在不影响ZK会话超时的情况下触发事件

时间:2013-01-02 20:53:33

标签: session-timeout zk

我无法获得ZK会话超时,因为我们的应用程序每隔几分钟轮询一次服务器以获取信息。触发此轮询的代码是Javascript,它单击隐藏按钮,将onClick事件发送到服务器。

你知道有什么办法告诉ZK这个轮询是自动的,不应该影响会话超时计时器吗?

非常感谢。

-Ian

2 个答案:

答案 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() {}
}