HttpSession 和上下文

150 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情

HttpSession 和上下文

内容说明

编写两个Servlet:

  1. Servlet1实现显示当前该Servlet1在当前会话中访问的次数(要求使用HttpSession),并且显示当前整个web应用项目被访问的次数(要求使用上下文,记录所有servlet被访问的次数。
  2. Servlet2实现显示当前该Servlet2在当前会话中访问的次数(要求使用HttpSession),并且显示当前整个web应用项目被访问的次数(要求使用上下文,记录所有servlet被访问的次数)

知识点

HttpSession

会话

从特定客户端到服务器的一系列请求称为会话。在Web服务器看来,一个会话是由在一次浏览过程中所发出的全部HTTP请求组成的。换句话说,一次会话是从客户打开浏览器开始到关闭浏览器结束。

会话跟踪

记录会话信息的技术称为会话跟踪,对于开发人员而言会话跟踪不是容易解决的问题。

会话跟踪的第一个障碍是如何唯一标识每一个客户会话。这只能通过为每一个客户分配一个某种标识,并将这些标识保存在客户端上,以后客户端发给服务器的每一个HTTP请求都提供这些标识来实现。那么为什么不能用客户端的IP地址作为标识呢?这是因为在一台客户端上可能同时发出多个不同的客户请求,而且,如果多个不同客户请求还可能是通过同一个代理服务器发出的,因此IP地址不能作为唯一标识。

HttpSession

为消除代码中手工管理会话信息的需要(无论使用什么会话跟踪方式),Servlet规范定义了HttpSession接口以方便Servlet容器进行会话跟踪。这个高级接口实际上是建立在Cookie和URL重写这两种会话跟踪技术之上的,只不过由Web容器自动实现了关于会话跟踪的底层机制,不再需要开发人员了解具体细节。HttpSession接口允许Servlet查看和管理关于会话的信息,确保信息持续跨越多个用户连接等。

使用HttpSession接口进行程序开发的基本步骤

  1. 获取HttpSession对象。
  2. 对HttpSession对象进行读或写。
  3. 手工终止HttpSession,或者什么也不做,让它自动终止。每个HttpSession对象都有一定的生命周期,超过这个周期,容器自动将HttpSession对象中止。

经常使用的HttpSession接口方法

  1. isNew()。如果客户端还不知道会话,则返回true。如果客户端已经禁用了Cookie,则会话在每个请求上都是新的。
  2. getId()。返回包含分配给这个会话的唯一标识的字符串。在使用URL改写已标识会话时比较有用。
  3. setAttribute()。使用指定的名称将对象绑定到会话。
  4. getAttribute()。返回绑定到此会话的指定名称的对象。
  5. setMaxInactiveInterval()。指定在Servlet使该会话无效之前客户端请求间的时间。负的时间表示会话永远不会超时。
  6. invalidate()。终止当前会话,并解开与它绑定的对象。

上下文

上下文

服务器上的每个Web应用都会有一个背景环境对象,称为上下文,Web应用中的所有资源包括Servlet、JSP、JavaBean和静态HTML页面等共享此上下文对象,因此上下文对象提供了一个同一Web应用内的不同资源间共享信息的场所。

Javax.Servlet.ServletContext接口提供正在运行的Servlet所处的Web应用程序的上下文对象的视图,可以通过getServletContext方法得到该Servlet运行的上下文对象。

ServletContext对此Web应用的任何客户端请求在任何时间都有效。要访问ServletContext对象,只要调用getServletContext()就可以了。

分析

要实现分别统计Servlet1和Servlet2在当前会话中访问的次数的功能,使用 HttpSession 进行记录。易发现HttpSession类似一个全局字典,存储若干键值对,在整个Web应用中对同一个键有着相同的取值。且HttpSession的生命周期为当前会话内。

要实现统计整个web应用项目被访问的次数应使用上下文,上下文的声明周期为整个Web应用的运行范围之内。

代码

Servlet 1

package test_2_8;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.sql.Date;
import java.text.DateFormat;

/**
 * Servlet implementation class HitCounter
 */

public class Servlet1 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public Servlet1() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		// 获取会话对象
		HttpSession session = request.getSession(true);
		response.setContentType("text/html;charset=gb2312");
		java.io.PrintWriter out = response.getWriter();
		int count = 1;
		Integer i = (Integer) session.getAttribute("count1");
		if (i != null) {
			count = i.intValue() + 1;
		}
		session.setAttribute("count1", new Integer(count));
		Date lastAccessed = new Date(session.getLastAccessedTime());
		Date sessionCreated = new Date(session.getCreationTime());
		DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
		
		
		//上下文
		String cntString=(String)getServletContext().getAttribute("Cnt");
		int cnt;
		if (cntString==null) {
			getServletContext().setAttribute("Cnt", "1");
			cnt=1;
		} else {
			cnt = Integer.valueOf(cntString).intValue()+1;
			getServletContext().setAttribute("Cnt", ""+cnt);
		}
				
		
		// Print a standard header
		out.println("<html>");
		out.println("<head>");
		out.println("<title>会话计数器1</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("整个web应用项目被访问的次数:"+cnt+"<br>");
		out.println("你的会话ID: <b>" + session.getId() + "<br>");
		out.println("会话创建时间:" + formatter.format(sessionCreated) + "<br>");
		out.println("会话上次访问时间:" + formatter.format(lastAccessed) + "<br>");
		out.println("</b> 会话期间你对页面发起 <b>" + count + "</b> 次请求");
		out.println("<form method=GET action=\"" + request.getRequestURI() + "\">");
		out.println("<input type=submit " + "value=\"再次单击...\">");
		out.println("</form>");
		out.println("<form method=POST action=\"" + request.getRequestURI() + "\">");
		out.println("<input type=submit " + "value=\"终止会话\">");
		out.println("</form>");
		out.println("</body>");
		out.println("</html>");
		out.flush();

		out.close();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub

		HttpSession session = request.getSession(true);
		session.invalidate();
		doGet(request, response);
	}

}

Servlet 2

package test_2_8;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.sql.Date;
import java.text.DateFormat;

/**
 * Servlet implementation class Servlet2
 */

@WebServlet(name="Servlet2",urlPatterns={"/Servlet2"},initParams={@WebInitParam(name="Cnt",value="0")})
public class Servlet2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public Servlet2() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
		HttpSession session = request.getSession(true);
		response.setContentType("text/html;charset=gb2312");
		java.io.PrintWriter out = response.getWriter();
		int count = 1;
		Integer i = (Integer) session.getAttribute("count2");
		if (i != null) {
			count = i.intValue() + 1;
		}
		session.setAttribute("count2", new Integer(count));
		Date lastAccessed = new Date(session.getLastAccessedTime());
		Date sessionCreated = new Date(session.getCreationTime());
		DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
		
		
		//上下文
		String cntString=(String)getServletContext().getAttribute("Cnt");
		int cnt;
		if (cntString==null) {
			getServletContext().setAttribute("Cnt", "1");
			cnt=1;
		} else {
			cnt = Integer.valueOf(cntString).intValue()+1;
			getServletContext().setAttribute("Cnt", ""+cnt);
		}
		
		// Print a standard header
		out.println("<html>");
		out.println("<head>");
		out.println("<title>会话计数器2</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("整个web应用项目被访问的次数:"+cnt+"<br>");
		out.println("你的会话ID: <b>" + session.getId() + "<br>");
		out.println("会话创建时间:" + formatter.format(sessionCreated) + "<br>");
		out.println("会话上次访问时间:" + formatter.format(lastAccessed) + "<br>");
		out.println("</b> 会话期间你对页面发起 <b>" + count + "</b> 次请求");
		out.println("<form method=GET action=\"" + request.getRequestURI() + "\">");
		out.println("<input type=submit " + "value=\"再次单击...\">");
		out.println("</form>");
		out.println("<form method=POST action=\"" + request.getRequestURI() + "\">");
		out.println("<input type=submit " + "value=\"终止会话\">");
		out.println("</form>");
		out.println("</body>");
		out.println("</html>");
		out.flush();

		out.close();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		// 获取会话对象
		HttpSession session = request.getSession(true);
		session.invalidate();
		doGet(request, response);
	}

}