tomcat 二级域名 相关
tomcat 二级域名 session共享 Tomcat 2010-08-02 19:16:09 阅读19 评论0 字号:大中小 订阅Tomcat 下,不同的二级域名之间或根域与子域之间,Ses
tomcat 二级域名 session共享 Tomcat 2010-08-02 19:16:09 阅读19 评论0 字号:大中小 订阅
Tomcat 下,不同的二级域名之间或根域与子域之间,Session 默认是不共享的,因为Cookie 名称为JSESSIONID 的Cookie 根域是默认是没设置 的,访问不同的二级域名,其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
修改配置:tomcatconf�talina.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 代码
1. public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
2.
3. Cookie cookie = null;
4.
5. PrintWriter out = response.getWriter();
6. out.println("");
7.
,8. Cookie[] cookies = request.getCookies();
9.
10. // 如果没有COOKIE ,新建一个COOKIE
11. if (cookies == null) {
12.
13. out.println("cookies is null.
"); 14.
15. cookie = new Cookie("new", "1");
16.
17. response.addCookie(cookie);
18.
19. } else {
20.
21. out.println("cookies is not null.
"); 22.
23. for (int i = 0; i < cookies.length; i ) { 24.
25. cookie = cookies[i];
26.
27. out.println("cookie" i " name: " cookie.getName() "
");
28. }
29. }
30.
31. HttpSession session = request.getSession();
32.
33. if (session == null) {
34. out.println("session is null.
"); 35.
36. } else {
37. out.println("session is not null.
");
38. out.println("session id: " session.getId() "
");
39. }
40.
41. out.println("");
42.}
第一次访问这个SERVLET ,页面显示
引用
,cookies is null.
session is not null.
session id: 0D0AABB6F911362FEE87BEEB2953C33F
第二次访问,页面显示
引用
cookies is 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 代码
1. cookie.setMaxAge(1000);
然后本地硬盘里就有“new”这个COOKIE 了。
这下就有疑问了,在没有设置COOKIE 存活期时,自己创建的SESSION 不会存到本地硬盘,会不会TOMCAT 创建的所谓的会话COOKIE 也是没有设置存活期呢?
然后根据zddava 的博客(http://zddava.javaeye.com/blog/311053),找到了TOMCAT 里创建会话COOKIE 的代码。
在
org.apache.catalina.connector.Request.java 里,
Java 代码
1. protected void configureSessionCookie(Cookie cookie) {
2. cookie.setMaxAge(-1);
3. String contextPath = null;
4. if (!connector.getEmptySessionPath() && (getContext() != null)) {
5. contextPath = getContext().getEncodedPath();
6. }
7. if ((contextPath != null) && (contextPath.length() > 0)) {
8. cookie.setPath(contextPath);
,9. } else {
10. cookie.setPath("/");
11. }
12. if (isSecure()) {
13. cookie.setSecure(true);
14. }
15.}
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 下测试,因为IE 6.0的一个BUG 就是IE 的隐私设置。即使是阻止所有cookie 时,也还是会以会话cookie 来保存sessionId 。所以下面都是以会话cookie 来讨论的。
(1)在server 没有关闭,并在session 对象销毁时间内,当客户端再次来请求 server端的servlet 或jsp 时,将会将在第一次请求时生成的sessionId 并附带在请求信息头中并向server 端发送,server 端 收到sessionId 后根据此sessionId 会去搜索 (此过程是透明的)server 对应的session 对象并直接返回这个session 对象,此时不会重新去建立一个新的session 对象。
(2)当server 关闭(之前产生的session 对象也就消亡了) ,或session 对 象过了其销毁时间后,浏览器窗口不关,并在本浏览器窗口再次去请求sever 端的servlet 和jsp 时,此时同样会将 sessionId(server关闭或session 销毁时生成的 sessionId)发送到server 端,server 根据sessionId 去找其对应的session 对象,但此时session 对象已经不存在, 此时会重新生成一个新的session 对象,并生成新的sessionId 并同样将这个新生成的sessionId 以响应报文的形式送到浏览器内存中。
,(3)当server 没有关闭,并session 对象在其销毁时间内,当请求一个jsp 页面 回客户端后,关闭此浏览器窗口,此时其内存中的 sessionId也就随之销毁,在重新去请求sever 端的servlet 或jsp 时,会重新生成一个sessionId 给客户端浏览器,并存在浏览内 存中。
上面的理论在servlet 中测试都是成立的,下面谈一下在struts 框架下进行上面的测试时的不同的地方。
先简要说下测试程序的流程:
客户端请求index.do--->进入server 端的IndexAction--->转向
login.jsp 页面----->请求login.do----->进入server 端的LoginAction 。
首先说明:IndexAction 中没有去产生session 对象,login.jsp 中设置。
(1)环境servlet 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 ,即使有name 和value ,开始很不理解,因 为根本就没有创建过session 对象,哪来的会话cookie 值呢!但是结果有,那么想着此时浏览器内存中也就应该有会话cookie ,问题就在这里! 从哪里来的?
后来经过仔细考虑后,想到struts 中的特点,我们自己写的Action 类是继承struts 的Action 的,而且之前是经过struts 的中央控制器ActionServlet 来控制转向的,所以我想肯定是在程序进入我自己写的IndexAction 之 前,struts 框架中的代码肯定已经创建了session 对象并已经生成了sessionId 。于是就找到相关书籍查看了ActionServlet 工 作流程以及调用哪些类,看了之后果然在其中看到了HttpSession session = request.getSession();这样一句话! 于是答案也就明白了。
大家知道struts 的ActionServlet 类中在接收到我们客户端的请求(*.do)后(之前会做一系列初始化工作) ,并不是直接去处理我们的请求并调用相应的Action(我们写的如IndexAction) ,而是将处理工作交给RequestProcessor 类,其process 方法中会调用一系列的方法来完成相应的请求处理和转向操作。其中有一个方法引起了我的关注,就是processLocale()方法。
,Struts 框架:RequestProcess类中的processLocale()方法,原型如下: Java 代码
1. protected void processLocale(HttpServletRequest request,
2. HttpServletResponse response) {
3. // Are we configured to select the Locale automatically?
4. if (!moduleConfig.getControllerConfig().getLocale())
5. // Has a Locale already been selected?
6. HttpSession session = request.getSession();
7.
8. if (session.getAttribute(Globals.LOCALE_KEY) != null)
9. // Use the Locale returned by the servlet container (if any)
10. Locale locale = request.getLocale();
11. if (locale != null) {
12. if (log.isDebugEnabled()) {
13. log.debug(" Setting user locale '" locale "'");
14. }
15. session.setAttribute(Globals.LOCALE_KEY, locale);
16. }
17.}
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 之前,< controller
locale="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>时,此时如果再根据上面的流程来跟踪程序,并在LoginAction 用request.getCookies()测试 时,其值是为null 的,当然在IndexAction 写上HttpSession session = request.getSession();时其是进入IndexAction 时新创建的,isNew 也是true 。
应用泛域名解析和java 的filter 实现对三级域名解析
关键字: 泛域名 java filter 域名解析
需求:
为每个在www.ecicc.oom 注册商家提供一个三级域名, 三级域名直接指向商家自己的主页面, 三级域名的组成方式为:注册名称.ecicc.com
商家又分为产业集群用户和专业市场用户, 这两种用户的应用是不同的, 分别对应企业展厅和专业网店。
对于产业集群用户来说,企业展厅的连接构造为:
网店暂未实现
设计:
通过泛域名解析,让http://*.ecicc.com指向www.ecicc.com ,把服务器配置成支持泛域名。
通过java filter 获取访问的域名,截取域名中的三级域名。根据不同的三级域名重定向到相应用户。
如:用户在地址栏中输入:http://csic220.ecicc.com,用filter 截取csic220,重新定向为http://www.ecicc.com/web/csic220
程序代码如下:
web.xml 文件
Java 代码
1.
2.
3.
4.
5.
6.
7.
8.
java 文件
Java 代码
1. package com.csic99.common.tools;
2.
3. import java.io.IOException;
4.
5. import javax.servlet.FilterChain;
6. import javax.servlet.FilterConfig;
7. import javax.servlet.ServletException;
8. import javax.servlet.ServletRequest;
9. import javax.servlet.ServletResponse;
10.
11.import javax.servlet.Filter;
12.import javax.servlet.http.HttpServletRequest;
13.import javax.servlet.http.HttpServletResponse;
14.
15.import org.springframework.context.support.AbstractApplicationContext;
16.import org.springframework.context.support.ClassPathXmlApplicationContext;
17.
18.import com.csic99.area.AcDirectionManager;
19.import com.csic99.product.UmUserManager;
20.import com.csic99.product.pojo.AcDirection;
21.import com.csic99.product.pojo.UmUser;
22./**
23. * 域名访问站点的重新定位
24. * 必须在服务器上已经配置好泛域名解析,
25. * 即http://*.ecicc.com是有效连接,它指定到www.ecicc.com
26. *
27. * @author zhx
28. *
29. */
30.public class URLFilter implements Filter{
31.
32. private static
33. AbstractApplicationContext appContext = new
34. ClassPathXmlApplicationContext("applicationContext-manager.xml");
35.
,36. public void destroy() {
37. // TODO Auto-generated method stub
38.
39. }
40.
41. public void doFilter(ServletRequest request, ServletResponse response,
42. FilterChain chain) throws IOException, ServletException {
43. HttpServletRequest httpServletRequest = (HttpServletRequest) request;
44. HttpServletResponse httpServletResponse = (HttpServletResponse) response;
45. //判断是否是三级域,如http://csic220.ecicc.com
46. //获取域名
47. String serverName = request.getServerName();
48. //判断是否是三级域名
49. int end = serverName.indexOf("ecicc.com");
50. String userName = "";
51. //获取用户名
52. if(end!= -1&&end!=0){
53. userName = serverName.substring(0, end-1);
54. }else{
55. end = serverName.indexOf("csic99.com");
56. if(end!=-1&&end!=0){
57. userName = serverName.substring(0, end-1);
58. }
59. }
60. //用户名不为空
61. if(userName!=null&&!"".equals(userName)){
62. //重定位的url
63. String url = "";
64. //获取用户管理对象
65. UmUserManager umUserManager =(UmUserManager) appContext.getBean("UmUserManager");
66. UmUser umUser = umUserManager.findUmUserByLoginName(userName);
67. if(umUser!=null){
68. AcDirectionManager acDirectionManager =
69. (AcDirectionManager)appContext.getBean("AcDirectionManager");
70. AcDirection acDirection =