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
最近實現網頁訪問量及在線人數的統(tǒng)計,看到一篇好文章。轉之... 引用部分:
當瀏覽器得到這個 sessionid會將它放在自己的進程內存里, 這里不同的瀏覽器會有所不同,IE 進程間不能共享這個sessionid, 也就是新開一個IE 將不能共享 這個sessionid; 而Firefox 進程間可以共享. 然后你繼續(xù)發(fā)請求給這個網站的時候, 瀏覽器就會把這個sessionid 放在請求頭里發(fā)送給該 服務器了, 這樣服務器得到sessionid 后再和自己內存里存放的sessionid 對比鎖定客戶端, 從而區(qū)分不同客戶端, 完成會話.
可以看出如果用這種方式, 當用戶在會話的過程中關閉瀏覽器結束進程, 則這個sessionid 將消失, 如果用戶又打開瀏覽器想繼續(xù)這次會話的時候, 就會因 為發(fā)送的請求中沒有這個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 是我創(chuàng)建的,名為“JSESSIONID”的COOKIE 應該是服務器TOMCAT 創(chuàng)建的,但這時,在本地硬盤里找不到這兩個COOKIE 的文件。
改一下SERVLET ,在創(chuàng)建名為“new”的COOKIE 時,加一句
Java 代碼
1. cookie.setMaxAge(1000);
然后本地硬盤里就有“new”這個COOKIE 了。
這下就有疑問了,在沒有設置COOKIE 存活期時,自己創(chuàng)建的SESSION 不會存到本地硬盤,會不會TOMCAT 創(chuàng)建的所謂的會話COOKIE 也是沒有設置存活期呢?
然后根據zddava 的博客(http://zddava.javaeye.com/blog/311053),找到了TOMCAT 里創(chuàng)建會話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 之分。我們本地創(chuàng)建的“持久COOKIE”和 WEB容器創(chuàng)建的“會話
COOKIE”都是一種COOKIE ,就是javax.servlet.http.Cookie 。只是WEB 容器把存活期設置成了 關閉瀏覽器時刪除而已(TOMCAT )。
首先談一下session 對象在web 開發(fā)中的創(chuàng)建以及sessionId 生成并返回客戶端的運行機制。
session 對象當客戶端首次訪問時,創(chuàng)建一個新的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 端發(fā)送,server 端 收到sessionId 后根據此sessionId 會去搜索 (此過程是透明的)server 對應的session 對象并直接返回這個session 對象,此時不會重新去建立一個新的session 對象。
(2)當server 關閉(之前產生的session 對象也就消亡了) ,或session 對 象過了其銷毀時間后,瀏覽器窗口不關,并在本瀏覽器窗口再次去請求sever 端的servlet 和jsp 時,此時同樣會將 sessionId(server關閉或session 銷毀時生成的 sessionId)發(fā)送到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)環(huán)境servlet jsp
在sevlet jsp測試跟蹤時,在index.do 進入IndexAction 后轉向
login.jsp 時,此時瀏覽器內存中是沒有會話 cookie的,那么在login.jsp 上請求login.do 進入LoginAction 后,用request.getCookies()測試時,其 值是為null 的! 結果是吻合的,因為從始至終沒有產生過session 。
(2)環(huán)境struts jsp
在struts jsp測試跟蹤時,跟上面的流程一樣,開始想結果也應該是一樣的,但經過調 試后發(fā)現結果卻不是所想的那樣。在login.do 進入 LoginActoin后用,用request.getCookies()測試時,發(fā)現其值不為null ,即使有name 和value ,開始很不理解,因 為根本就沒有創(chuàng)建過session 對象,哪來的會話cookie 值呢!但是結果有,那么想著此時瀏覽器內存中也就應該有會話cookie ,問題就在這里! 從哪里來的?
后來經過仔細考慮后,想到struts 中的特點,我們自己寫的Action 類是繼承struts 的Action 的,而且之前是經過struts 的中央控制器ActionServlet 來控制轉向的,所以我想肯定是在程序進入我自己寫的IndexAction 之 前,struts 框架中的代碼肯定已經創(chuàng)建了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>其缺省狀態(tài)locale 屬性的值為true ,也就會調用processLocale 方法,并在第一次請求時創(chuàng)建 session對象和生成sessionId 。但改為false 后,在第一次請求到達ActionServlet 后不會調用processLocale 方 法,也就不會生成session 對象了。
結果也就出來了,在struts 應用中,*.do到達server 端后經過
ActionServlet 后轉想我們自己寫的IndexAction 之前,< controller
locale="true">< /controller>(缺省狀態(tài)) 時,就已經產生了session 對象和sessionId ,這是struts 框架類中生成的,即使我們在 IndexAction中寫上HttpSession session = request.getSession();其也是RequestProcess 類中的
,processLocale()方法生成的,此時其session 的isNew 也還是true ,因為還沒有返回客戶端,其是新創(chuàng)建的,那么按照上面的流程,當在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 時新創(chuàng)建的,isNew 也是true 。
應用泛域名解析和java 的filter 實現對三級域名解析
關鍵字: 泛域名 java filter 域名解析
需求:
為每個在www.ecicc.oom 注冊商家提供一個三級域名, 三級域名直接指向商家自己的主頁面, 三級域名的組成方式為:注冊名稱.ecicc.com
商家又分為產業(yè)集群用戶和專業(yè)市場用戶, 這兩種用戶的應用是不同的, 分別對應企業(yè)展廳和專業(yè)網店。
對于產業(yè)集群用戶來說,企業(yè)展廳的連接構造為:
網店暫未實現
設計:
通過泛域名解析,讓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 =