Tomcat下不同工程Session共享的思路 Demo

直接開門見山,針對一個Tomcat容器裏不同工程Session無法共享問題,參考很多地方博客(會一一標註出處),搭建一個小Demo。

  問題來源:項目比較老的代碼,有三個不同項目,菜單切換的時候訪問到了不同項目下的請求,比如菜單1請求地址http://host:port/projectA/..........  菜單2請求地址:http://host:port/projectB/..........這些菜單都請求了相同的host  port,系統首先肯定登陸進來的,假設請求的都jsp(事實上,這個項目也的確是這樣),每個項目請求到的jsp中都包含了這樣一句<jsp:include page="/pub/UserInfo.jsp" flush="true"/> ,UserInfo.jsp裏嵌套了部分js代碼,將session中用戶信息取出來;可是當不同工程切換的時候,session一會有,切換工程一會有沒有了,項目比較複雜,session不宜於管理,排錯真的不好找;另一種思路,session中信息替換爲存到redis裏,但是鑑於項目工程,所以打消了念頭。

廢話不多說直接進入正題了:

Step1.

新建兩個簡單的web工程SessionA以及SessionB(結構很簡單,不多解釋了.....代碼會貼在step2)

Step2.

SessionA中SessionServlet代碼:

package com.lvbinbin.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


public class SessionServlet extends HttpServlet{

	/**
	 * 
	 */
	private static final long serialVersionUID = -5130555166003468048L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		service(req, resp);
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
//		System.out.println("方法執行..."+req.getParameter("name"));
//		req.getSession().setAttribute("name", req.getParameter("name"));
//		PrintWriter pw = resp.getWriter();
//		pw.println("success done!"+req.getSession().getAttribute("name"));
		System.out.println("doService方法執行..."+req.getParameter("name"));
		req.getSession().setAttribute("name", req.getParameter("name"));
		ServletContext ctx1=req.getSession().getServletContext();
		ctx1.setAttribute("session", req.getSession());
		PrintWriter pw = resp.getWriter();
		pw.println("success done!"+((HttpSession)req.getServletContext().getAttribute("session")).getAttribute("name"));
	}
	
}

SessionA中web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SessionProjectA</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
  	<servlet-name>servletA</servlet-name>
  	<servlet-class>com.lvbinbin.servlet.SessionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>servletA</servlet-name>
  	<url-pattern>/sessionA</url-pattern>
  </servlet-mapping>
</web-app>

SessionA中index.jsp文件

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    Project:  SessionProjectA <br>
    <form action="sessionA">
    姓名:<input type="text" name="name"/><br/>
    <input type="submit" value="點擊保存信息(lvbinbin)進入session"/>
    </form>
  </body>
</html>

 

SessionA就是這樣簡單,補充說明幾句無關緊要的,ServletContext配置我會在Step3說明一下我的看法,隨意看看:

    Tomcat6是不支持@WebServlet註解的,從Tomcat7開始支持Servlet3.0特性,Servlet3.0有很多新特性(感興趣的可以自行百度,因爲我就知道這麼幾個註解特性)

========================================華麗的分割線 SessionB==========================

SessionB的SessionServlet代碼

package com.lvbinbin.servletB;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class SessionServlet extends HttpServlet{

	/**
	 * 
	 */
	private static final long serialVersionUID = -5130555166003468048L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		service(req, resp);
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		ServletContext ctx1 = req.getServletContext();
		ServletContext ctxA = ctx1.getContext("/SessionA");
		System.out.println("servletContext==null?"+(ctxA==null));
		HttpSession session=(HttpSession) ctxA.getAttribute("session");
		System.out.println("session==null?"+(session==null));
		System.out.println("session得到數據:"+session.getAttribute("name"));
		req.getRequestDispatcher("index.jsp").forward(req, resp);
	}

	
}

SessionB的web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>SessionProjectA</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
  	<servlet-name>servletB</servlet-name>
  	<servlet-class>com.lvbinbin.servletB.SessionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>servletB</servlet-name>
  	<url-pattern>/sessionB</url-pattern>
  </servlet-mapping>
</web-app>

 

SessionB的index.jsp文件

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>SessionB</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  <body>
   Project:SessionProjectB.<br>
   <%
   		ServletContext ctx=application.getContext("/SessionA");
   		request.getSession().setAttribute("name", ((HttpSession)ctx.getAttribute("session")).getAttribute("name"));
   %>
  <h3>${sessionScope.name}</h3>
  </body>
</html>

代碼部分就這麼多了

 

Step3.Tomcat的配置以及補充說明

Eclipse裏的server文件夾如下:

重點!把項目部署到Tomcat裏,server.xml這樣配置!

      <Context docBase="SessionA" path="/SessionA" reloadable="true" source="org.eclipse.jst.jee.server:SessionA"  crossContext="true"/>
      <Context docBase="SessionB" path="/SessionB" reloadable="true" source="org.eclipse.jst.jee.server:SessionB"  crossContext="true"/>

其中crossContext必須配置。參考地址( https://blog.csdn.net/jayyanzi/article/details/46561509 ),更詳細的原因有人這麼說:crosscontext="true"表示配置的不同context共享一個session 我菜,先人云亦云吧。

Step4.啓動Tomcat:

瀏覽器訪問SessionA:   http://localhost:8080/SessionA/

點擊進入按鈕

  

可知,Session中已經存了name值。

訪問SessionB: http://localhost:8080/SessionB/sessionB

控制檯打印:

emmmmm 這樣應該對Session共享有一種思路了,ServletContext保存Session.我還要嘗試WebLogic...因爲項目就是Weblogic部署的

總結下本文的Demo,可能有價值的地方:

1.通過SessionB項目的request請求得到另外一個項目的ServletContext,進而得到Session對象

ServletContext ctx1 = req.getServletContext();
ServletContext ctxA = ctx1.getContext("/SessionA");
HttpSession session=(HttpSession) ctxA.getAttribute("session");

2.SessionB項目的index.jsp頁面,我們可以利用application內置對象得到ServletContext,然後把session中的對象存到新的Session中,這樣就可以只在UserInfo.jsp裏改動一小部分代碼,實現原有功能

 <%
   		ServletContext ctx=application.getContext("/SessionA");
   		request.getSession().setAttribute("name", ((HttpSession)ctx.getAttribute("session")).getAttribute("name"));
   %>

3.server.xml文件的配置屬性,其中source屬性應該是Eclipse生成的,各位小心點,別產生不必要的錯誤

<Context docBase="SessionA" path="/SessionA" reloadable="true" source="org.eclipse.jst.jee.server:SessionA"  crossContext="true"/>
<Context docBase="SessionB" path="/SessionB" reloadable="true" source="org.eclipse.jst.jee.server:SessionB"  crossContext="true"/></Host>

就這麼多,我要肥家了,告辭各位!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章