【问题标题】:Fire event without impacting ZK session timeout在不影响 ZK 会话超时的情况下触发事件
【发布时间】:2013-01-02 20:53:32
【问题描述】:

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

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

非常感谢。

-伊恩

【问题讨论】:

    标签: session-timeout zk


    【解决方案1】:

    一种解决方法是编写一个过滤器来检测请求是否是轮询请求,并在过滤器中记录“真实”请求的时间,如果长时间没有真实请求,则使会话无效。

    样本:

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

    【讨论】:

      【解决方案2】:

      简短的回答是否定的。

      长答案是,首先没有“ZK Session”。它只是 Servlet 规范定义的 HttpSession。其次,会话管理由 servlet web 容器完成,因此会话超时计数器重置在请求传递给 ZK 进行处理之前很久就完成了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-10
        • 2014-07-02
        • 2023-03-30
        • 2020-04-07
        • 1970-01-01
        • 2018-08-03
        • 1970-01-01
        • 2018-02-02
        相关资源
        最近更新 更多