持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
HttpSession 和上下文
内容说明
编写两个Servlet:
- Servlet1实现显示当前该Servlet1在当前会话中访问的次数(要求使用HttpSession),并且显示当前整个web应用项目被访问的次数(要求使用上下文,记录所有servlet被访问的次数。
- Servlet2实现显示当前该Servlet2在当前会话中访问的次数(要求使用HttpSession),并且显示当前整个web应用项目被访问的次数(要求使用上下文,记录所有servlet被访问的次数)
知识点
HttpSession
会话
从特定客户端到服务器的一系列请求称为会话。在Web服务器看来,一个会话是由在一次浏览过程中所发出的全部HTTP请求组成的。换句话说,一次会话是从客户打开浏览器开始到关闭浏览器结束。
会话跟踪
记录会话信息的技术称为会话跟踪,对于开发人员而言会话跟踪不是容易解决的问题。
会话跟踪的第一个障碍是如何唯一标识每一个客户会话。这只能通过为每一个客户分配一个某种标识,并将这些标识保存在客户端上,以后客户端发给服务器的每一个HTTP请求都提供这些标识来实现。那么为什么不能用客户端的IP地址作为标识呢?这是因为在一台客户端上可能同时发出多个不同的客户请求,而且,如果多个不同客户请求还可能是通过同一个代理服务器发出的,因此IP地址不能作为唯一标识。
HttpSession
为消除代码中手工管理会话信息的需要(无论使用什么会话跟踪方式),Servlet规范定义了HttpSession接口以方便Servlet容器进行会话跟踪。这个高级接口实际上是建立在Cookie和URL重写这两种会话跟踪技术之上的,只不过由Web容器自动实现了关于会话跟踪的底层机制,不再需要开发人员了解具体细节。HttpSession接口允许Servlet查看和管理关于会话的信息,确保信息持续跨越多个用户连接等。
使用HttpSession接口进行程序开发的基本步骤
- 获取HttpSession对象。
- 对HttpSession对象进行读或写。
- 手工终止HttpSession,或者什么也不做,让它自动终止。每个HttpSession对象都有一定的生命周期,超过这个周期,容器自动将HttpSession对象中止。
经常使用的HttpSession接口方法
- isNew()。如果客户端还不知道会话,则返回true。如果客户端已经禁用了Cookie,则会话在每个请求上都是新的。
- getId()。返回包含分配给这个会话的唯一标识的字符串。在使用URL改写已标识会话时比较有用。
- setAttribute()。使用指定的名称将对象绑定到会话。
- getAttribute()。返回绑定到此会话的指定名称的对象。
- setMaxInactiveInterval()。指定在Servlet使该会话无效之前客户端请求间的时间。负的时间表示会话永远不会超时。
- 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);
}
}