Servlet(4):Session
Session, Cookie及交互
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。
Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。
但是仍然有以下三种方式来维持 Web 客户端和 Web 服务器之间的 session 会话:
Cookies:Session创建成功以后,会创建Cookie(key='JSESSIONID', value=Session ID)。通常情况下,一个浏览器的多个Tag可以共享一个Session对象。
隐藏的表单字段(Form适用):有些浏览器不支持Cookie,可以用表单隐藏域代替。
<input type="hidden" name="sessionid" value="12345">
URL 重写(Link适用):如果使用URL提交时,可以作为URL参数传递。
http://localhost:8080/ServletTest/login?sessionid=12345
下面是一个使用Cookie来维持Session会话的例子。重点代码讲解在例子中。
1 package com.servlettest.session; 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 Login 15 */ 16 @WebServlet("/default") 17 public class Default extends HttpServlet { 18 19 private static final long serialVersionUID = 1L; 20 21 /** 22 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 23 */ 24 @Override 25 protected void doGet(HttpServletRequest request, HttpServletResponse response) 26 throws ServletException, IOException { 27 28 invalidateSession(request); 29 30 response.setContentType("text/html"); 31 request.setCharacterEncoding("UTF-8"); 32 response.setCharacterEncoding("UTF-8"); 33 34 PrintWriter out = response.getWriter(); 35 out.println("<!DOCTYPE html>"); 36 out.println("<html>"); 37 out.println("<head>"); 38 out.println("<title>Login Page</title>"); 39 out.println("</head>"); 40 out.println("<body>"); 41 out.println("<form action=\"login\" method=\"POST\">"); 42 out.println("帐号: <input type=\"text\" name=\"userId\"/><br/>"); 43 out.println("密码: <input type=\"password\" name=\"password\"/><br/>"); 44 out.println("<input type=\"submit\" value=\"提交\"/>"); 45 46 // HttpServletRequest Attribute和Parameter的区别 47 // (1) HttpServletRequest 类有setAttribute()方法,而没有setParameter()方法。 48 // (2) 当两个Web组件之间为链接关系时,被链接的组件通过getParameter()方法来获得请求参数,一般通过表单和链接传递的参数使用getParameter。 49 // (3) 当两个Web组件之间为转发关系时,转发目标组件通过getAttribute()方法来和转发源组件共享request范围内的数据。 50 String message = (String) request.getAttribute("message"); 51 if (message != null && message != "") { 52 out.println("<p>" + message + "</p>"); 53 } 54 out.println("</body>"); 55 out.println("</html>"); 56 } 57 58 /** 59 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 60 */ 61 @Override 62 protected void doPost(HttpServletRequest request, HttpServletResponse response) 63 throws ServletException, IOException { 64 doGet(request, response); 65 } 66 67 private static void invalidateSession(HttpServletRequest request) { 68 HttpSession session = request.getSession(false); 69 if (session != null) 70 session.invalidate(); 71 } 72 }
1 package com.servlettest.session; 2 3 import java.io.IOException; 4 import java.util.HashMap; 5 import java.util.Map; 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 Login 16 */ 17 @WebServlet("/login") 18 public class Login extends HttpServlet { 19 20 private static final long serialVersionUID = 1L; 21 22 private static final Map<String, String[]> USER_INFO = initUserInfo(); 23 24 /** 25 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 26 */ 27 @Override 28 protected void doGet(HttpServletRequest request, HttpServletResponse response) 29 throws ServletException, IOException { 30 31 response.setContentType("text/html"); 32 33 request.setCharacterEncoding("UTF-8"); 34 response.setCharacterEncoding("UTF-8"); 35 36 // 获取用户登录信息 37 String userId = request.getParameter("userId"); 38 String password = request.getParameter("password"); 39 if ((userId == null || userId == "") || (password == null || password == "")) { 40 request.getRequestDispatcher("/default").forward(request, response); 41 } else if (USER_INFO.containsKey(userId)) { 42 String[] info = USER_INFO.get(userId); 43 if (info[1].equals(password)) { 44 // 创建Session 45 setSession(userId, info[0], request, response); 46 request.getRequestDispatcher("/welcome1").forward(request, response); 47 } else { 48 request.setAttribute("message", "帐号或密码错误!"); 49 request.getRequestDispatcher("/default").forward(request, response); 50 } 51 } else { 52 request.setAttribute("message", "帐号或密码错误!"); 53 request.getRequestDispatcher("/default").forward(request, response); 54 } 55 } 56 57 /** 58 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 59 */ 60 @Override 61 protected void doPost(HttpServletRequest request, HttpServletResponse response) 62 throws ServletException, IOException { 63 doGet(request, response); 64 } 65 66 private static Map<String, String[]> initUserInfo() { 67 68 Map<String, String[]> result = new HashMap<>(); 69 String[] user1 = { "张三", "123" }; 70 result.put("101", user1); 71 String[] user2 = { "李四", "456" }; 72 result.put("102", user2); 73 String[] user3 = { "王五", "789" }; 74 result.put("103", user3); 75 76 return result; 77 } 78 79 private void setSession(String userId, String userName, HttpServletRequest request, HttpServletResponse response) { 80 // 如果不存在 session 会话,则创建一个 session 对象 81 HttpSession session = request.getSession(true); 82 String[] userInfo = { userId, userName }; 83 session.setAttribute("USER_INFO", userInfo); 84 } 85 }
1 package com.servlettest.session; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.util.Enumeration; 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 Welcome 16 */ 17 @WebServlet("/welcome1") 18 public class Welcome1 extends HttpServlet { 19 20 private static final long serialVersionUID = 1L; 21 22 /** 23 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 24 */ 25 @Override 26 protected void doGet(HttpServletRequest request, HttpServletResponse response) 27 throws ServletException, IOException { 28 29 response.setContentType("text/html"); 30 request.setCharacterEncoding("UTF-8"); 31 response.setCharacterEncoding("UTF-8"); 32 33 // 注意request.getSession() 等同于 request.getSession(true),除非我们确认session一定存在或者sesson不存在时明确有创建session的需要,否则请尽量使用request.getSession(false) 34 HttpSession session = request.getSession(false); 35 String[] userInfo = (String[]) session.getAttribute("USER_INFO"); 36 PrintWriter out = response.getWriter(); 37 out.println("<!DOCTYPE html>"); 38 out.println("<html>"); 39 out.println("<head>"); 40 out.println("<title>Login Page</title>"); 41 out.println("</head>"); 42 out.println("<body>"); 43 out.println("您好 <b>" + userInfo[0] + "-" + userInfo[1] + "</b>, 这是Welcome1画面!"); 44 out.println("<br/><a href = \"welcome2\">去welcome2</a> | <a href = \"default\">注销</a>"); 45 out.println("<br/>"); 46 out.println("<p>SessionID: " + session.getId() + "</p>"); 47 Enumeration<String> names = session.getAttributeNames(); 48 while (names.hasMoreElements()) { 49 String name = names.nextElement(); 50 out.println("<p>" + names.nextElement() + ": " + session.getAttribute(name) + "</p>"); 51 } 52 out.println("</table>"); 53 out.println("</body>"); 54 out.println("</html>"); 55 out.close(); 56 } 57 58 /** 59 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 60 */ 61 @Override 62 protected void doPost(HttpServletRequest request, HttpServletResponse response) 63 throws ServletException, IOException { 64 doGet(request, response); 65 } 66 }
1 package com.servlettest.session; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.util.Enumeration; 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 Welcome 16 */ 17 @WebServlet("/welcome2") 18 public class Welcome2 extends HttpServlet { 19 20 private static final long serialVersionUID = 1L; 21 22 /** 23 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 24 */ 25 @Override 26 protected void doGet(HttpServletRequest request, HttpServletResponse response) 27 throws ServletException, IOException { 28 29 response.setContentType("text/html"); 30 request.setCharacterEncoding("UTF-8"); 31 response.setCharacterEncoding("UTF-8"); 32 33 // 注意request.getSession() 等同于 request.getSession(true),除非我们确认session一定存在或者sesson不存在时明确有创建session的需要,否则请尽量使用request.getSession(false) 34 HttpSession session = request.getSession(false); 35 String[] userInfo = (String[]) session.getAttribute("USER_INFO"); 36 PrintWriter out = response.getWriter(); 37 out.println("<!DOCTYPE html>"); 38 out.println("<html>"); 39 out.println("<head>"); 40 out.println("<title>Login Page</title>"); 41 out.println("</head>"); 42 out.println("<body>"); 43 out.println("您好 <b>" + userInfo[0] + "-" + userInfo[1] + "</b>, 这是Welcome2画面!"); 44 out.println("<br/><a href = \"welcome1\">去welcome1</a> | <a href = \"default\">注销</a>"); 45 out.println("<br/>"); 46 out.println("<p>SessionID: " + session.getId() + "</p>"); 47 Enumeration<String> names = session.getAttributeNames(); 48 while (names.hasMoreElements()) { 49 String name = names.nextElement(); 50 out.println("<p>" + names.nextElement() + ": " + session.getAttribute(name) + "</p>"); 51 } 52 out.println("</body>"); 53 out.println("</html>"); 54 out.close(); 55 } 56 57 /** 58 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 59 */ 60 @Override 61 protected void doPost(HttpServletRequest request, HttpServletResponse response) 62 throws ServletException, IOException { 63 doGet(request, response); 64 } 65 }
1 package com.servlettest.filter; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import javax.servlet.Filter; 8 import javax.servlet.FilterChain; 9 import javax.servlet.FilterConfig; 10 import javax.servlet.ServletException; 11 import javax.servlet.ServletRequest; 12 import javax.servlet.ServletResponse; 13 import javax.servlet.http.HttpServletRequest; 14 import javax.servlet.http.HttpServletResponse; 15 import javax.servlet.http.HttpSession; 16 17 import com.servlettest.exception.PermissionException; 18 19 public class PermissionFilter implements Filter { 20 21 private final static List<String> URL = new ArrayList<>(); 22 23 @Override 24 public void init(FilterConfig arg0) throws ServletException { 25 URL.add("/ServletTest/welcome1"); 26 URL.add("/ServletTest/welcome2"); 27 } 28 29 @Override 30 public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) 31 throws IOException, ServletException { 32 if (arg0 instanceof HttpServletRequest && arg1 instanceof HttpServletResponse) { 33 HttpServletRequest req = (HttpServletRequest) arg0; 34 if (URL.contains(req.getRequestURI())) { 35 HttpSession session = req.getSession(true); 36 String[] userInfo = (String[]) session.getAttribute("USER_INFO"); 37 if (userInfo == null) { 38 throw new PermissionException(); 39 } 40 } 41 } 42 arg2.doFilter(arg0, arg1); 43 } 44 45 @Override 46 public void destroy() { 47 } 48 }
1 package com.servlettest.exception; 2 3 public class PermissionException extends RuntimeException { 4 5 private static final long serialVersionUID = 1L; 6 7 }
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>Forbidden</title> 6 </head> 7 <body> 8 <h2>403 禁止访问所请求的页面</h2> 9 </body> 10 </html>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://xmlns.jcp.org/xml/ns/javaee" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 5 id="WebApp_ID" version="3.1"> 6 <filter> 7 <filter-name>permissionFilter</filter-name> 8 <filter-class>com.servlettest.filter.PermissionFilter</filter-class> 9 </filter> 10 <filter-mapping> 11 <filter-name>permissionFilter</filter-name> 12 <url-pattern>/*</url-pattern> 13 </filter-mapping> 14 <error-page> 15 <error-code>403</error-code> 16 <location>/html/forbidden.html</location> 17 </error-page> 18 <error-page> 19 <exception-type>com.servlettest.exception.PermissionException</exception-type> 20 <location>/html/forbidden.html</location> 21 </error-page> 22 <welcome-file-list> 23 <welcome-file>default</welcome-file> 24 </welcome-file-list> 25 <session-config> 26 <session-timeout>1</session-timeout> 27 </session-config> 28 </web-app>