tomcat 二级域名 session共享

字体大小: 中小 标准 ->行高大小: 标准

Tomcat下,不同的二级域名之间或根域与子域之间,Session默认是不共享的,因为Cookie名称为JSESSIONIDCookie根域是默认是没设置的,访问不同的二级域名,其Cookie就重新生成,而session就是根据这个Cookie来生成的,所以在不同的二级域名下生成的Session也 不一样。找到了其原因,就可根据这个原因对Tomcat在生成Session时进行相应的修改(注:本文针对Tomcat 6.0.18)

 

修改tomcat源代码
包:catalina.jar
类:org.apache.catalina.connector.Request

protected void configureSessionCookie(Cookie cookie) {
        cookie.setMaxAge(-1);

         String contextPath = null;

         if (!connector.getEmptySessionPath() &&(getContext() != null)) {

                  contextPath = getContext().getEncodedPath();

         }

         if ((contextPath != null) &&(contextPath.length() > 0)) {

                  cookie.setPath(contextPath);

         }else{

                  cookie.setPath("/");

         }

         String value =System.getProperty("webDomain");

         if ((null !=value) &&(value.length()>0) && (value.indexOf(".") != -1)) {

                  cookie.setDomain((value.startsWith("."))?value:"."+value);

         }

         if (isSecure()) {

                  cookie.setSecure(true);

         }

}

重新编译Tomcat编译tomcat

修改配置:tomcat\conf\catalina.properties,在最后添加一行

webDomain=***.com

java中的Cookie Session

 

   最近实现网页访问量及在线人数的统计,看到一篇好文章。转之...

引用部分:

   当浏览器得到这个sessionid会将它放在自己的进程内存里这里不同的浏览器会有所不同,IE进程间不能共享这个sessionid,也就是新开一个IE将不能共享 这个sessionid;Firefox进程间可以共享.然后你继续发请求给这个网站的时候浏览器就会把这个sessionid放在请求头里发送给该 服务器了这样服务器得到sessionid后再和自己内存里存放的sessionid对比锁定客户端从而区分不同客户端,完成会话

 

   可以看出如果用这种方式,当用户在会话的过程中关闭浏览器结束进程,则这个sessionid将消失,如果用户又打开浏览器想继续这次会话的时候,就会因 为发送的请求中没有这个sessionid而使服务器无法辨别该把那个session信息给他,注意(这个时候服务器端的sessionid和 sessionid所指向的session都还存在,只是没有正确的sessionid和它匹配而占用服务器内存,只有session过期或服务器重启才 释放内存)。 

 

   上面这种方式叫会话cookie,cookie放在浏览器内存里,只能在这个浏览器的内存范围里完成会话,是一种不长久的方式,为了能长久会话,就出现了持久化cookie,把cookie固化在用户的计算机上,现在的cookie不单单能存放sessionid,还能放用户信息,样式表信息等。
   
如果用户禁止了所有cookie的使用,那么会话cookie和持久化cookie都不能用了,有个方案也可以解决问题,就是URL重写,这里要说下的就是URL重写只能实现会话cookie的效果,持久会话实现不了。 


   刚开始理解时,我也认为会有持久和会话这两种COOKIE。我认为,会话COOKIE就是用来存放SESSIONID的,并且只存在于浏览器内存,浏览器关闭后会话COOKIE就被删除;持久COOKIE就是用来存放其它信息,并且是在我们的本地硬盘里能看到的那种COOKIE


然后我写了个SERVLET试了一下。 

Java代码:

public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { 

        Cookie cookie = null;

        PrintWriter out = response.getWriter();

        out.println("<html><body>");

        Cookie[] cookies = request.getCookies();

        // 如果没有COOKIE,新建一个COOKIE

        if (cookies == null) {

               out.println("<b>cookies is null.</b></br>");

               cookie = new Cookie("new", "1");

               response.addCookie(cookie);

        } else {

                out.println("<b>cookies is not null.</b></br>");

                for (int i = 0; i < cookies.length; i++) {

                        cookie = cookies[i];

                        out.println("cookie" + i + " name: " + cookie.getName() + "</br>");

                 }

        }

        HttpSession session = request.getSession();

        if (session == null) {

                out.println("<b>session is null.</b></br>");

        } else {

                out.println("<b>session is not null.</b></br>");

                out.println("session id: " + session.getId() + "</br>");

        }

        out.println("</body></html>");

}

第一次访问这个SERVLET,页面显示,引用:

cookies is null.
session is not null.
session id: 0D0AABB6F911362FEE87BEEB2953C33F

第二次访问,页面显示,引用

cookiesis not null.
cookie0 name: new 
cookie1 name: JSESSIONID 
session is not null.

session id: 0D0AABB6F911362FEE87BEEB2953C33F


    第二次访问时从客户端来了两个COOKIE,名为“new”COOKIE是我创建的,名为“JSESSIONID”COOKIE应该是服务器TOMCAT创建的,但这时,在本地硬盘里找不到这两个COOKIE的文件。

    改一下SERVLET,在创建名为“new”COOKIE时,加一句 

Java代码:

cookie = new Cookie("new", "1");

cookie.setMaxAge(1000);

然后本地硬盘里就有“new”这个COOKIE了。

这下就有疑问了,在没有设置COOKIE存活期时,自己创建的SESSION不会存到本地硬盘,会不会TOMCAT创建的所谓的会话COOKIE也是没有设置存活期呢?

然后根据zddava的博客(http://zddava.javaeye.com/blog/311053),找到了TOMCAT里创建会话COOKIE的代码。

Java代码:

protected void configureSessionCookie(Cookie cookie) {

        cookie.setMaxAge(-1);

        String contextPath = null;

        if (!connector.getEmptySessionPath() && (getContext() != null)) { 
                contextPath = getContext().getEncodedPath();

        }

        if ((contextPath != null) && (contextPath.length() > 0)) {

                cookie.setPath(contextPath);

        } else {

                cookie.setPath("/");

        }

        if (isSecure()) { 

                cookie.setSecure(true);

        }

}

cookie.setMaxAge(-1);使COOKIE在浏览器被关闭时删除。而且这里的cookie和上面SERVLET里的cookie都是javax.servlet.http.Cookie

由 此得出结论,可能最开始是我理解错了,COOKIE并没有会话COOKIE和持久COOKIE之分。我们本地创建的持久COOKIE” WEB容器创建的会话COOKIE”都是一种COOKIE,就是javax.servlet.http.Cookie。只是WEB容器把存活期设置成了关闭浏览器时删除而已(TOMCAT)。

首先谈一下session对象在web开发中的创建以及sessionId生成并返回客户端的运行机制。

session对象当客户端首次访问时,创建一个新的session对象。并同时生成一个sessionId,并在此次响应中将sessionId 以响应报文的方式返回客户端浏览器内存或以重写url方式送回客户端,来保持整个会话,只要sever端的这个session对象没有销毁,以后再调用 request.getSession()时就直接根据客户端的sessionId来检索server端生成的session对象并返回,不会再次去新 建,除非根据此sessionId没有检索到session对象。

下面是在IE下测试,因为IE6.0的一个BUG就是IE的隐私设置。即使是阻止所有cookie时,也还是会以会话cookie来保存sessionId。所以下面都是以会话cookie来讨论的。

(1)server没有关闭,并在session对象销毁时间内,当客户端再次来请求 server端的servletjsp时,将会将在第一次请求时生成的sessionId并附带在请求信息头中并向server端发送,server端 收到sessionId后根据此sessionId会去搜索 (此过程是透明的)server对应的session对象并直接返回这个session对象,此时不会重新去建立一个新的session对象。

(2)server关闭(之前产生的session对象也就消亡了),或session对 象过了其销毁时间后,浏览器窗口不关,并在本浏览器窗口再次去请求sever端的servletjsp时,此时同样会将sessionId(server关闭或session销毁时生成的 sessionId)发送到server端,server根据sessionId去找其对应的session对象,但此时session对象已经不存在, 此时会重新生成一个新的session对象,并生成新的sessionId并同样将这个新生成的sessionId以响应报文的形式送到浏览器内存中。

(3)server没有关闭,并session对象在其销毁时间内,当请求一个jsp页面 回客户端后,关闭此浏览器窗口,此时其内存中的 sessionId也就随之销毁,在重新去请求sever端的servletjsp时,会重新生成一个sessionId给客户端浏览器,并存在浏览内 存中。

上面的理论在servlet中测试都是成立的,下面谈一下在struts框架下进行上面的测试时的不同的地方。

先简要说下测试程序的流程:

客户端请求index.do--->进入server端的IndexAction--->转向login.jsp页面----->请求login.do----->进入server端的LoginAction

首先说明:IndexAction中没有去产生session对象,login.jsp中设置。

sevlet+jsp测试跟踪时,在index.do进入IndexAction后转向 login.jsp时,此时浏览器内存中是没有会话 cookie的,那么在login.jsp上请求login.do进入LoginAction后,用request.getCookies()测试时,其值是为null!结果是吻合的,因为从始至终没有产生过session

(2)环境struts+jsp

struts+jsp测试跟踪时,跟上面的流程一样,开始想结果也应该是一样的,但经过调 试后发现结果却不是所想的那样。在login.do进入 LoginActoin后用,用request.getCookies()测试时,发现其值不为null,即使有namevalue,开始很不理解,因 为根本就没有创建过session对象,哪来的会话cookie值呢!但是结果有,那么想着此时浏览器内存中也就应该有会话cookie,问题就在这里从哪里来的?

后来经过仔细考虑后,想到struts中的特点,我们自己写的Action类是继承strutsAction 的,而且之前是经过struts的中央控制器ActionServlet来控制转向的,所以我想肯定是在程序进入我自己写的IndexAction之 前,struts框架中的代码肯定已经创建了session对象并已经生成了sessionId。于是就找到相关书籍查看了ActionServlet工 作流程以及调用哪些类,看了之后果然在其中看到了HttpSessionsession = request.getSession();这样一句话!于是答案也就明白了。

大家知道strutsActionServlet类中在接收到我们客户端的请求(*.do)(之前会做一系列初始化工作),并不是直接去处理我们的请求并调用相应的Action(我们写的如IndexAction),而是将处理工作交给RequestProcessor类,其process方法中会调用一系列的方法来完成相应的请求处理和转向操作。其中有一个方法引起了我的关注,就是processLocale()方法。

Struts框架:RequestProcess类中的processLocale()方法,原型如下:

Java代码

protected void processLocale(HttpServletRequest request,HttpServletResponse response) {

        // Are we configured to select the Locale automatically?

        if (!moduleConfig.getControllerConfig().getLocale())

                // Has a Locale already been selected?

                HttpSession session = request.getSession();

        if (session.getAttribute(Globals.LOCALE_KEY) != null)

                // Use the Locale returned by the servlet container (if any)

                Locale locale = request.getLocale();

        if (locale != null) {

                 if (log.isDebugEnabled()) {

                         log.debug(" Setting user locale '" + locale + "'");

                 }

                 session.setAttribute(Globals.LOCALE_KEY, locale);

        }

}

此类在struts-config.xml配置文件中有对应的配置项:<controller locale="true">< /controller>其缺省状态locale属性的值为true,也就会调用processLocale方法,并在第一次请求时创建 session对象和生成sessionId。但改为false后,在第一次请求到达ActionServlet后不会调用processLocale方 法,也就不会生成session对象了。

结果也就出来了,在struts应用中,*.do到达server端后经过 ActionServlet后转想我们自己写的IndexAction之前,< controllerlocale="true">< /controller>(缺省状态)时,就已经产生了session对象和sessionId,这是struts框架类中生成的,即使我们在IndexAction中写上HttpSession session = request.getSession();其也是RequestProcess类中的processLocale()方法生成的,此时其session isNew也还是true,因为还没有返回客户端,其是新创建的,那么按照上面的流程,当在login.jsp上通过login.do进入 LoginAction后,其request.getCookies()固然也就有值了!并且其值是RequestProcess类中的 processLocale()方法产生session对象时生成的。

如果我们在struts-config.xml中加上<controller locale="false">< /controller>时,此时如果再根据上面的流程来跟踪程序,并在LoginActionrequest.getCookies()测试 时,其值是为null的,当然在IndexAction写上HttpSession session = request.getSession();时其是进入IndexAction时新创建的,isNew也是true

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/69296.html