一. 需求.

    我们公司要对自己的各个网站进行数据采集,想了解一个用户在我们网站的整个浏览轨迹,但是我们每个二级域名都对应自己的项目,也就是说对应自己的jsessionid,我们无法把这些数据关联起来,所以想到让所有的二级域名都公用一个jsessionid,这样用户的整个浏览数据我们就都能得到了。

二. 开发。

    需要对tomcat(jboss-web)的源码进行修改,修改的地方有两处。

    1.org.apache.catalina.connector.Request的configureSessionCookie方法

 /**     * Configures the given JSESSIONID cookie.     *     * @param cookie The JSESSIONID cookie to be configured     */    protected void configureSessionCookie(TomcatCookie cookie) {        cookie.setMaxAge(-1);        if (context.getSessionCookie().getPath() != null) {            cookie.setPath(context.getSessionCookie().getPath());        } else {            String contextPath = context.getEncodedPath();            if ("".equals(contextPath)) {                contextPath = "/";            }            cookie.setPath(contextPath);        }        if (context.getSessionCookie().getComment() != null) {            cookie.setComment(context.getSessionCookie().getComment());        }        if (context.getSessionCookie().getDomain() != null) {            cookie.setDomain(context.getSessionCookie().getDomain());        }        if (context.getSessionCookie().isHttpOnly()) {            cookie.setHttpOnly(true);        }                cookie.setPath("/");        cookie.setDomain(System.getProperty("cookieDomain"));                 if (context.getSessionCookie().isSecure()) {            cookie.setSecure(true);        } else if (isSecure()) {            cookie.setSecure(true);        }    }

添加的代码是  

cookie.setPath("/");cookie.setDomain(System.getProperty("cookieDomain"));

      2.在编译好的tomcat中修改conf下的catalina.properties

添加cookieDomain变量 cookieDomain=.cdeledu.com

三.原理

    tomcat如何读取客户端的jsessionid

        向tomcat请求过程中,需要访问org.apache.catalina.connector.CoyoteAdapter的sevice方法,里面调用了postParseRequest方法,这个方法就是主要解析客户端的jsessionid,其中parseSessionId主要是分析url里的jessionID,parseSessionCookiesId这个是分析cookie中的jsessionid

代码如下:

从url获得jsesionid

    /**     * Parse session id in URL.     */    protected void parseSessionId(org.apache.coyote.Request req, Request request) {        ByteChunk uriBC = req.requestURI().getByteChunk();        //math的值为:";jsessionid=" ,判断url中是否有这个字符串        int semicolon = uriBC.indexOf(match, 0, match.length(), 0);        //如果有解析,并赋值给request(org.apache.catalina.connector.Request)        if (semicolon > 0) {            // Parse session ID, and extract it from the decoded request URI            int start = uriBC.getStart();            int end = uriBC.getEnd();            int sessionIdStart = semicolon + match.length();            int semicolon2 = uriBC.indexOf(';', sessionIdStart);            if (semicolon2 >= 0) {                request.setRequestedSessionId                    (new String(uriBC.getBuffer(), start + sessionIdStart,                             semicolon2 - sessionIdStart));                // Extract session ID from request URI                byte[] buf = uriBC.getBuffer();                for (int i = 0; i < end - start - semicolon2; i++) {                    buf[start + semicolon + i]                         = buf[start + i + semicolon2];                }                uriBC.setBytes(buf, start, end - start - semicolon2 + semicolon);            } else {                request.setRequestedSessionId                    (new String(uriBC.getBuffer(), start + sessionIdStart,                             (end - start) - sessionIdStart));                uriBC.setEnd(start + semicolon);            }            request.setRequestedSessionURL(true);        } else {            request.setRequestedSessionId(null);            request.setRequestedSessionURL(false);        }    }

从cookie中获取

    /**     * Parse session id in URL.     */    protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) {        // Parse session id from cookies 获取request中的cookie        Cookies serverCookies = req.getCookies();        int count = serverCookies.getCookieCount();        if (count <= 0)            return;        for (int i = 0; i < count; i++) {            ServerCookie scookie = serverCookies.getCookie(i);            //判断cookie中有name为jsessionid的,            //有就赋值给request(org.apache.catalina.connector.Request)            if (scookie.getName().equals(Globals.SESSION_COOKIE_NAME)) {                // Override anything requested in the URL                if (!request.isRequestedSessionIdFromCookie()) {                    // Accept only the first session id cookie                    convertMB(scookie.getValue());                    request.setRequestedSessionId                        (scookie.getValue().toString());                    request.setRequestedSessionCookie(true);                    request.setRequestedSessionURL(false);                    if (log.isDebugEnabled())                        log.debug(" Requested cookie session id is " +                            request.getRequestedSessionId());                } else {                    if (!request.isRequestedSessionIdValid()) {                        // Replace the session id until one is valid                        convertMB(scookie.getValue());                        request.setRequestedSessionId                            (scookie.getValue().toString());                    }                }            }        }    }

由于咱们写到的是主域下,所以在tomcat中能获得这个cookie(tomcat中能获得的cookie的范围为自己域名下和主域下的)。