会话管理
Posted Asu_PC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了会话管理相关的知识,希望对你有一定的参考价值。
一、会话管理的基本原理
web应用程序的请求与响应是基于HTTP,为无状态的通信协议,服务器不会记得这次请求和下次请求的关系,如购物车,用户可能在多个购物网页之间采购商品,web应用程序必须有个方式来得知用户在这些网页中采购了哪些商品,这种记得此次请求与之后请求间关系的方式,就称为会话管理(Session Management).
1、使用隐藏域
隐藏域就是主动告知服务器多次请求间必要信息的方式之一。以问卷作答的为例,上一页的问卷答案,可以用隐藏域的方式放在下一页的窗体中,这样发送下一页窗体,就可以一并发送这些隐藏域,每一页的问卷答案就可以保留下来。上一次的结果如何成为下一页的隐藏域呢?做法之一就是将上一页的结果发送至服务器,由服务器将上一页结果以隐藏域的方式再响应给浏览器。
例1:程序中有两页问卷,第一页的结果会在第二页成为隐藏域,当第二页发送时,就可以看到两页问卷的所有答案。
1 package Session.Management; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.io.UnsupportedEncodingException; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.annotation.WebServlet; 9 import javax.servlet.http.HttpServlet; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletResponse; 12 import javax.servlet.http.HttpSession; 13 14 /** 15 * Servlet implementation class Questionnaire 16 */ 17 @WebServlet("/questionnaire") 18 public class Questionnaire extends HttpServlet { 19 private static final long serialVersionUID = 1L; 20 21 /** 22 * @see HttpServlet#HttpServlet() 23 */ 24 public Questionnaire() { 25 super(); 26 // TODO Auto-generated constructor stub 27 } 28 29 /** 30 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 31 */ 32 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 33 // TODO Auto-generated method stub 34 processRequest(request,response); 35 } 36 37 private void processRequest(HttpServletRequest request, 38 HttpServletResponse response) throws IOException { 39 // TODO Auto-generated method stub 40 request.setCharacterEncoding("UTF-8"); 41 response.setContentType("text/html;charset=UTF-8"); 42 PrintWriter out=response.getWriter(); 43 out.println("<!DOCTYPE html>"); 44 out.println("<html>"); 45 out.println("<head>"); 46 out.println("<meta content=\'text/html; charset=UTF-8\' http-equiv=\'content-type\'>"); 47 out.println("<title>Questionnaire</title>"); 48 out.println("</head>"); 49 out.println("<body>"); 50 String page=request.getParameter("page");//page请求参数决定哪一个页面问卷 51 out.println("<form action=\'questionnaire\' method=\'post\'>"); 52 if(page==null){ 53 out.println("问题一:<input type=\'text\' name=\'p1q1\'><br>"); 54 out.println("问题二:<input type=\'text\' name=\'p1q2\'><br>");//第一页的问卷题目 55 out.println("<input type=\'submit\' name=\'page\' value=\'下一页\'>"); 56 }else if("下一页".equals(page)){ 57 String p1q1=request.getParameter("p1q1"); 58 String p1q2=request.getParameter("p1q2"); 59 60 //使用隐藏域 61 // out.println("<input type=\'hidden\' name=\'p1q1\' value=\'"+p1q1+"\'>"); 62 // out.println("<input type=\'hidden\' name=\'p1q2\' value=\'"+p1q2+"\'>"); 63 64 //使用HttpSession存储第一页的答案 65 HttpSession session=request.getSession(); 66 session.setAttribute("p1q1", p1q1); 67 session.setAttribute("p1q2", p1q2); 68 69 out.println("问题三:<input type=\'text\' name=\'p2q1\'><br>");//第二页的问卷题目 70 //out.println("问题四:<input type=\'text\' name=\'p2q2\'><br>"); 71 out.println("<input type=\'submit\' name=\'page\' value=\'完成\'>");//第一页问卷答案,使用隐藏域发送答案 72 }else if("完成".equals(page)){ 73 74 HttpSession session=request.getSession(); 75 session.getAttribute("p1q1"); 76 77 out.println(session.getAttribute("p1q1")+"<br>"); 78 out.println(session.getAttribute("p1q2")+"<br>"); 79 out.println(request.getParameter("p2q1")+"<br>");//问卷结果网页 80 } 81 out.println("</form>"); 82 out.println("</body>"); 83 out.println("</html>"); 84 out.close(); 85 } 86 87 /** 88 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 89 */ 90 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 91 // TODO Auto-generated method stub 92 processRequest(request,response); 93 } 94 95 }
使用隐藏域的方式,在关掉网页后,显然会丢失先前的请求的信息,所以仅适合用于一些简单的状态管理,如在线问卷。在查看网页源代码时,就可以看到隐藏域的值,这个方法不适合隐秘性较高的数据。
2、使用Cookie
Cookie是在浏览器存储信息的一种方式,服务器可以响应浏览器set-cookie标头,浏览器收到这个标头与数值后,会将它以文件的形式存储在计算机上,这个文件就是Cookie。可以给Cookie设定一个存活期限,保留一些有用的信息在客户端,如果在关闭浏览器之后,再次打开浏览器并连接服务器时,这些cookie仍在有效期限中,浏览器会使用cookie标头自动将Cookie发送给服务器,服务器就可以得知一些先前请求的信息。
如果创建Cookie,可以使用Cookie类,创建时指定Cookie中的名称与数值,并使用HttpServletResponse的addCookie()方法在响应中新增Cookie。例如:
Cookie cookie=new Cookie("user","caterpillar");
cookie.setMaxAge(7*24*60*60);//单位是秒,所以一星期有效
response.addCookie(cookie);
如果想要取得浏览器上存储的Cookie,则可以HttpServletRequest的getCookie()来取得,这可取得属于该网页所有域的所有Cookie,所以返回值时cookie[]数组。取得cookie对象后,可以使用Cookie的getName()与getValues()方法,分别取得Cookie的名称和数值。
Cookie[] cookies=request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
String name = cookie.getName();
String value = cookie.getValue();
}
}
例2:用Cookie实现自动登录功能。当访问首页时,会检查用户先前时是否允许自动登录,如果是的话,就直接转送至用户界面。
1 package Session.Management; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.Cookie; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 /** 13 * Servlet implementation class Index 14 */ 15 @WebServlet("/index.do") 16 public class Index extends HttpServlet { 17 private static final long serialVersionUID = 1L; 18 19 /** 20 * @see HttpServlet#HttpServlet() 21 */ 22 public Index() { 23 super(); 24 // TODO Auto-generated constructor stub 25 } 26 27 /** 28 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 29 */ 30 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 31 // TODO Auto-generated method stub 32 processRequest(request,response); 33 } 34 35 private void processRequest(HttpServletRequest request, 36 HttpServletResponse response) throws IOException, ServletException { 37 // TODO Auto-generated method stub 38 Cookie[] cookies=request.getCookies();//取得Cookie 39 if(cookies!=null){ 40 for(Cookie cookie:cookies){ 41 String name=cookie.getName(); 42 String value=cookie.getValue(); 43 if("user".equals(name)&&"caterpillar".equals(value)){ 44 request.setAttribute(name, value); 45 request.getRequestDispatcher("/user.view").forward(request, response); 46 return; 47 } 48 } 49 } 50 response.sendRedirect("index.html");//如果没有相对应的Cookie名称与数值,表示尚未允许自动登录,重定向到登录窗体。 51 52 } 53 54 /** 55 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 56 */ 57 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 58 // TODO Auto-generated method stub 59 processRequest(request,response); 60 } 61 62 }
运行结果:
1 package Session.Management; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.Cookie; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 /** 13 * Servlet implementation class Login1 14 */ 15 @WebServlet("/login1.do") 16 public class Login1 extends HttpServlet { 17 private static final long serialVersionUID = 1L; 18 19 /** 20 * @see HttpServlet#HttpServlet() 21 */ 22 public Login1() { 23 super(); 24 // TODO Auto-generated constructor stub 25 } 26 27 /** 28 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 29 */ 30 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 31 // TODO Auto-generated method stub 32 } 33 34 /** 35 * *- 36 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 37 */ 38 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 39 // TODO Auto-generated method stub 40 String user=request.getParameter("user"); 41 String passwd=request.getParameter("password"); 42 if("nihao".equals(user)&&"123456789".equals(passwd)){ 43 // String login=request.getParameter("login"); 44 // if("auto".equals(login)){ 45 // Cookie cookie=new Cookie("user", "nihao"); 46 // cookie.setMaxAge(7*24*60*60); 47 // response.addCookie(cookie); 48 // } 49 //request.setAttribute("user", user); 50 51 request.getSession().setAttribute("login", user); 52 53 request.getRequestDispatcher("user.view").forward(request, response); 54 }else{ 55 response.sendRedirect("index.html"); 56 } 57 } 58 59 }
1 package Session.Management; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import javax.servlet.http.HttpSession; 12 13 /** 14 * Servlet implementation class User 15 */ 16 @WebServlet("/user.view") 17 public class User extends HttpServlet { 18 private static final long serialVersionUID = 1L; 19 20 /** 21 * @see HttpServlet#HttpServlet() 22 */ 23 public User() { 24 super(); 25 // TODO Auto-generated constructor stub 26 } 27 28 /** 29 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 30 */ 31 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 // TODO Auto-generated method stub 33 processRequest(request,response); 34 } 35 36 private void processRequest(HttpServletRequest request, 37 HttpServletResponse response) throws IOException { 38 // TODO Auto-generated method stub 39 response.setContentType("text/html;charset=UTF-8"); 40 HttpSession session=request.getSession(); 41 if(session.getAttribute("login")==null){ 42 response.sendRedirect("index.html"); 43 }else{ 44 PrintWriter out=response.getWriter(); 45 out.println("<!DOCTYPE html>"); 46 out.println("<html>"); 47 out.println("<head>"); 48 out.println("<meta content=\'text/html; charset=UTF-8\' http-equiv=\'content-type\'>"); 49 out.println("<title>欢迎"+session.getAttribute("login")+"</title>"); 50 out.println("</head>"); 51 out.println("<body>"); 52 out.println("<h1>用户 "+session.getAttribute("login")+"已登录</h1><br><br>"); 53 out.println("<a href=\'logout.view\'>注销</a>"); 54 out.println("</body>"); 55 out.println("</html>"); 56 out.close(); 57 } 58 59 } 60 61 /** 62 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 63 */ 64 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 65 // TODO Auto-generated method stub 66 processRequest(request,response); 67 } 68 69 }
当登录名正确时候,下次再次登录atuoindex.java时就会自动登录,并转到user.java
3、使用URL重写
所谓URL重写,其实就是GET请求参数的应用,当服务器响应浏览器上一次请求时,将某些信息以超链接的方式响应给浏览器,超链接中包括请求参数信息。
例3:模拟搜索分页结果,比如当点击第五页的时候,就会显示第五页的内容。
1 package Session.Management; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.annotation.WebServlet; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 /** 13 * Servlet implementation class Search 14 */ 15 @WebServlet("/search") 16 public class Search extends HttpServlet { 17 private static final long serialVersionUID = 1L; 18 19 /** 20 * @see HttpServlet#HttpServlet() 21 */ 22 public Search() { 23 super(); 24 // TODO Auto-generated constructor stub 25 } 26 27 /** 28 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 29 */ 30 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 31 // TODO Auto-generated method stub 32 response.setContentType("text/html;charset=UTF-8"); 33 34 PrintWriter out=response.getWriter(); 35 out.println("<!DOCTYPE html>"); 36 out.println("<html>"); 37 out.println("<head>"); 38 out.println("<meta content=\'text/html; charset=UTF-8\' http-equiv=\'content-type\'>"); 39 out.println("<title>搜索结果</title>"); 40 out.println("</head>"); 41 out.println("<body>"); 42 String start=request.getParameter("start"); 43 while(start==null){ 44 start="1"; 45 } 46 int count=Integer.parseInt(start); 47 int begin=10*count-9; 48 int end=10*count; 49 out.println("第 "+begin+" 到 "+end+" 搜索结果<br>"); 50 out.println("<ul>"); 51 for(int i=1;i<=10;i++){ 52 out.println("<li>搜寻结果"+i+"</li>"); 53 } 54 out.println("</ul>"); 55 for(int i=1;i<10;i++){ 56 if(i==count){ 57 out.println(i); 58 continue; 59 } 60 out.println("<a href=\'search?start="+i+"\'>"+i+"</a>"); 61 } 62 out.println("</body>"); 63 out.println("</html>"); 64 out.close(); 65 } 66 67 /** 68 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 69 */ 70 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 71 // TODO Auto-generated method stub 72 73 } 74 75 }
运行结果:
二、HttpSession会话管理
可以将必须共享的数据,保存在HttpSession中成为属性,当关掉浏览器接收Cookie的功能,HttpSession也可以改用URL重写继续其会话管理。
1、使用HttpSession
使用HttpServletRequest的getSession()方法取得HttpSession对象。
HttpSession session = request.getSession();
HttpSession最常用的方法大概是setAttribute()与getAttribute(),这与HttpServletRequest的setAttribute()和getAttribute()类似,可以让你在对象中设置及取得属性,这是可以存放属性的第二个地方。(ServletAPI 中第三个可以存放属性的地方是在ServletContext中)。
例3:将例1的在线问答,从隐藏域改为HttpSession方式来实现会话管理。