会话跟踪
要实现由状态的会话,就需要在Web服务器程序和客户端浏览器之间来回传递会话ID,以关联同一客户端浏览器向Web服务器程序发出的连续请求。实现在Web服务器程序和客户端浏览器之间来回传递会话ID的技术称为会话跟踪技术。会话跟踪技术主要有两种:一种是通过Cookie技术在请求消息首部中传递会话ID;另一种是通过URL重写,即在URL的末尾添上这个会话ID。
1、Cookie技术
Cookie是在浏览器访问Web服务器的某个资源时,由Web服务器再HTTP响应消息头中附带传送给浏览器的一段数据。浏览器可以决定是否保存这段数据。一旦浏览器保存了这段数据,那么它在以后每次访问该Web服务器时,都会在HTTP请求头中将这段数据传回给Web服务器。很显然,Cookie最先是由Web服务器发出的,是否发送Cookie和发送的Cookie的具体内容,完全由Web服务器端程序决定。
Web服务器程序是通过在HTTP响应消息头中增加Set-Cookie字段将Cookie信息发送给浏览器的,浏览器则通过在HTTP请求消息头中增加Cookie字段将Cookie信息回传给Web服务器。
在Servlet类中操作Cookie:
· public Cookie(String name, String value):Cookie类中提供的一个构造方法,用来创建Cookie实例,name用来指定Cookie的名称,value用来指定它的值。
· getName():用来获取该Cookie的名称。
· setValue()和getValue():用来设置和获取CookieCookie的值。
· setMaxAge()和getMaxAge():用来设置和获取Cookie在客户端浏览器上保持有效的时间秒值。
· setPath()和getPath():用于设置和获取Cookie的有效目录路径。
· setDomain()和getDomain():用于设置和获取Cookie的有效域。
如果想把一个构造好的Cookie实例的消息添加到响应消息头中,可以使用HttpServletResponse接口中提供的addCookie()方法。如果有多个Cookie实例消息要添加到响应消息头中,可以多次调用这个方法。相反,如果想从HTTP请求消息头中读取所有的Cookie信息,可以使用HttpServletRequest接口中提供的getCookies()方法,这个方法会读取该请求消息头中的所有Cookie消息,并封装成各个 Cookie实例,存储在一个数组中再返回。遍历这个cookie数组,就可以获取想要的Cookie信息了。
Servlet类,在它的请求处理方法中往响应中写入Cookie信息,同时还从用户的这个请求消息中获取当前所有的Cookie信息。
package com.yyq.cookies; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by gao on 16-4-14. */ public class CookieServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //创建一个Cookie实例 Cookie cookie = new Cookie("username", "yuqin"); //设置有效时间为1天 cookie.setMaxAge(24 * 3600); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); //往响应中写入Cookie resp.addCookie(cookie); //获取Cookie数组 Cookie[] cookies = req.getCookies(); if (null == cookies) { out.println("<h3>还没有Cookie</h3>"); } else { out.println("<h3>Cookie列表</h3>"); //遍历Cookie信息 for (int i = 0; i < cookies.length; i++) { out.print("Cookie名称:" + cookies[i].getName()); out.println(",对应的值为:" + cookies[i].getValue()); out.println("<br />"); } } } @Override public void destroy() { //空 } @Override public void init() throws ServletException { //空 } }
web.xml注册:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <!--CookieServlet的配置--> <servlet> <servlet-name>cookieservlet</servlet-name> <servlet-class>com.yyq.cookies.CookieServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cookieservlet</servlet-name> <url-pattern>/cookieservlet</url-pattern> </servlet-mapping> </web-app>
2、Session技术
为了在服务器端保存用户会话的状态信息,Servlet API规范中提供了一个javax.serlvet.http.HttpSession接口,这个接口中定义了各种管理和操作会话状态的方法。一个客户端在Web服务器端对应一个各自的HttpSession实例。Web容器并不在每个客户端第一次访问时就自动创建HttpSession实例。只有客户端访问某个编写了创建HttpSession实例代码的Servlet时,才会创建一个HttpSession实例,Web容器创建这个HttpSession实例时,会为它分配一个独一无二的会话ID,再返回响应给客户端时会在响应消息中把这个会话ID以Cookie的方式传递给客户端。客户端需要记住这个会话ID,并在后续的每次访问请求中都带上这个会话ID,传回给Web服务器,Web服务器程序会根据传回的会话ID找到对应的HttpSession实例。
1)创建HttpSession实例
· public HttpSession getSession():调用此方法时,容器会先检查客户端先前送出的请求是否建立过HTTP会话;如果没有,容器会新建一个会话,并赋予一个唯一的会话ID;如果有,容器会根据客户请求中的会话ID找到相匹配的会话。
· public HttpSession getSession(boolean flag):此方法的flag参数用来指定是否有必要创建一个会话,调用getSession(false)时,若客户先前没有建立过会话,则方法将返回null。
2)Session的常用操作
序号 | 方法 & 描述 |
---|---|
1 | public Object getAttribute(String name) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null。 |
2 | public Enumeration getAttributeNames() 该方法返回 String 对象的枚举,String 对象包含所有绑定到该 session 会话的对象的名称。 |
3 | public long getCreationTime() 该方法返回该 session 会话被创建的时间,自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。 |
4 | public String getId() 该方法返回一个包含分配给该 session 会话的唯一标识符的字符串。 |
5 | public long getLastAccessedTime() 该方法返回客户端最后一次发送与该 session 会话相关的请求的时间自格林尼治标准时间 1970 年 1 月 1 日午夜算起,以毫秒为单位。 |
6 | public int getMaxInactiveInterval() 该方法返回 Servlet 容器在客户端访问时保持 session 会话打开的最大时间间隔,以秒为单位。 |
7 | public void invalidate() 该方法指示该 session 会话无效,并解除绑定到它上面的任何对象。 |
8 | public boolean isNew( 如果客户端还不知道该 session 会话,或者如果客户选择不参入该 session 会话,则该方法返回 true。 |
9 | public void removeAttribute(String name) 该方法将从该 session 会话移除指定名称的对象。 |
10 | public void setAttribute(String name, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话。 |
11 | public void setMaxInactiveInterval(int interval) 该方法在 Servlet 容器指示该 session 会话无效之前,指定客户端请求之间的时间,以秒为单位。 |
package com.yyq.session; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; /** * Created by gao on 16-4-24. */ public class SessionServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 如果不存在 session 会话,则创建一个 session 对象 HttpSession session = request.getSession(true); // 获取 session 创建时间 Date createTime = new Date(session.getCreationTime()); // 获取该网页的最后一次访问时间 Date lastAccessTime = new Date(session.getLastAccessedTime()); String title = "Session例子"; Integer visitCount = new Integer(0); String visitCountKey = new String("visitCount"); String userIDKey = new String("userID"); String userID = new String("ABCD"); // 检查网页上是否有新的访问者 if (session.isNew()){ title = "Session例子"; session.setAttribute(userIDKey, userID); } else { visitCount = (Integer)session.getAttribute(visitCountKey); visitCount = visitCount + 1; userID = (String)session.getAttribute(userIDKey); } session.setAttribute(visitCountKey, visitCount); // 设置响应内容类型 response.setContentType("text/html"); PrintWriter out = response.getWriter(); String docType = "<!doctype html public \"-//w3c//dtd html 4.0 " + "transitional//en\">\n"; out.println(docType + "<html>\n" + "<head><title>" + title + "</title></head>\n" + "<body bgcolor=\"#f0f0f0\">\n" + "<h1 align=\"center\">" + title + "</h1>\n" + "<h2 align=\"center\">Session 信息</h2>\n" + "<table border=\"1\" align=\"center\">\n" + "<tr bgcolor=\"#949494\">\n" + " <th>Session 信息</th><th>值</th></tr>\n" + "<tr>\n" + " <td>id</td>\n" + " <td>" + session.getId() + "</td></tr>\n" + "<tr>\n" + " <td>Creation Time</td>\n" + " <td>" + createTime + " </td></tr>\n" + "<tr>\n" + " <td>Time of Last Access</td>\n" + " <td>" + lastAccessTime + " </td></tr>\n" + "<tr>\n" + " <td>User ID</td>\n" + " <td>" + userID + " </td></tr>\n" + "<tr>\n" + " <td>Number of visits</td>\n" + " <td>" + visitCount + "</td></tr>\n" + "</table>\n" + "</body></html>"); } }