HTTP本身是无状态的通信协议,进行会话管理的基本原理,就是将需要维持的状态响应给浏览器,使浏览器在下次请求时主动发送状态信息,让web应用程序“得知”请求之间的联系。
1.隐藏字段
隐藏字段是将状态信息以窗口中看不到的输入字段响应给浏览器,在下次发窗口时一并发送这些隐藏字段。使用隐藏字段的方式,显然,关掉网页后,就会遗失先前的信息,所以这种方式只适合于一些简单的状态管理,像是在线问卷。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Questionnaire extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Questionnaire</title>");
out.println("</head>");
out.println("<body>");
String page = request.getParameter("page");
out.println("<form action=\"question.do\" method=\"post\">");
if("page1".equals(page)) {
out.println("问题一:<input type=\"text\" name=\"p1q1\"><br>");
out.println("问题二:<input type=\"text\" name=\"p1q2\"><br>");
out.println("<input type=\"submit\" name=\"page\" value=\"page2\">");
}
else if("page2".equals(page)) {
String p1q1 = request.getParameter("p1q1");
String p1q2 = request.getParameter("p1q2");
out.println("问题三:<input type=\"text\" name=\"p2q1\"><br>");
out.println("<input type=\"hidden\" name=\"p1q1\" value=\"" + p1q1 + "\">");
out.println("<input type=\"hidden\" name=\"p1q2\" value=\"" + p1q2 + "\">");
out.println("<input type=\"submit\" name=\"page\" value=\"finish\">");
}
else if("finish".equals(page)) {
out.println(request.getParameter("p1q1") + "<br>");
out.println(request.getParameter("p1q2") + "<br>");
out.println(request.getParameter("p2q1") + "<br>");
}
out.println("</form>");
out.println("</body>");
out.println("</html>");
out.close();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
2.Cookie
Cookie是保存在浏览器上的一个小文件,可以设置存活期限,在浏览器请求web应用时,会将属于这个应用的Cookie一并发送给程序。
Cookie cookie = new Cookie("user", "liuping");
cookie.setMaxAge(7*24*60*60);
response.addCookie(cookie);
Cookie的一个常见应用是实现自动登录。
package liuping;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Index extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(int i = 0; i < cookies.length; i++) {
String name = cookies[i].getName();
String value = cookies[i].getValue();
if("user".equals(name) && "liuping".equals(value)) {
request.setAttribute(name, value);
request.getRequestDispatcher("/user.view")
.forward(request, response);
return;
}
}
}
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<form action=\"login.do\" method=\"post\">");
out.println("名称:<input type=\"input\" name=\"user\"><br>");
out.println("密码:<input type=\"password\" name=\"passwd\"><br>");
out.println("自动登录:<input type=\"checkbox\" "
+ " name=\"login\" value=\"auto\"><br>");
out.println("<input type=\"submit\" value=\"送出\">");
out.println("</form>");
out.println("</body>");
out.println("</html>");
out.close();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package liuping;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Login extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
String user = request.getParameter("user");
String passwd = request.getParameter("passwd");
if("liuping".equals(user) && "123456".equals(passwd)) {
request.setAttribute("user", user);
request.getRequestDispatcher("/user.view")
.forward(request, response);
}
else {
response.sendRedirect("index.do");
}
}
}
package liuping;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class User extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String login = request.getParameter("login");
if (login != null && "auto".equals(login)) {
Cookie cookie = new Cookie("user", "liuping");
cookie.setMaxAge(7 * 24 * 60 * 60); // 一星期内有效
response.addCookie(cookie);
}
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet User</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>" +
request.getAttribute("user") + "已登录</h1>");
out.println("</body>");
out.println("</html>");
out.close();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
3.URL重写
URL重写就是GET请求参数的应用,当服务器响应浏览器的上一次请求时,将相关信息以超链接的方式响应给浏览器。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Search extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Search</title>");
out.println("</head>");
out.println("<body>");
String start = request.getParameter("start");
if (start == null) {
start = "1";
}
int count = Integer.parseInt(start);
int begin = 10 * count - 9;
int end = 10 * count;
out.println("第 " + begin + " 到 " + end + " 搜索结果<br>");
out.println("<ul>");
for(int i = 1; i <= 10; i++) {
out.println("<li>搜索结果" + i + "</li>");
}
out.println("</ul>");
for (int i = 1; i < 10; i++) {
if (i == count) {
out.println(i);
continue;
}
out.println("<a href=\"search.do?start=" +
i + "\">" + i + "</a>");
}
out.println("</body>");
out.println("</html>");
out.close();
}
}
4.HttpSession会话管理
执行HttpServlerRequest的getSession()方法可以取得HttpSession对象。在会话阶段,可以利用HttpSession的setAttribute()方法设置会话期间要保留的信息,利用getAttribute()方法可以取得信息。HttpSession是容器中的一个对象,每个HttpSession对象都有一个独特的ID。容器默认使用Cookie在浏览器上保存SessionID,在下次请求时,浏览器会将包括SeesionID的Cookie送至web应用,应用根据ID取得相应的HttpSession对象。如果浏览器禁用Cookie,则无法使用Cookie在浏览器上保存ID,此时可以利用URL重写机制。HttpServletResponse的encodeURL()方法在容器无法从Cookie取得SessionID时,会在设置给它的URL上附上SessionID。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Count extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
int count = 0;
HttpSession session = request.getSession();
if(session.getAttribute("count") != null) {
Integer c = (Integer) session.getAttribute("count");
count = c.intValue() + 1;
}
session.setAttribute("count", new Integer(count));
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Count</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet Count " + count + "</h1>");
out.println("<a href=\""+
response.encodeURL("count.do")+ "\">递增</a>");
out.println("</body>");
out.println("</html>");
out.close();
}
}