Servlet会话跟踪

会话跟踪技术
  • 什么是会话?
    会话可简单理解为:打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器,整个过程称之为一个会话。
  • 会话过程中要解决的问题?
    HTTP 是一种“无状态”协议,每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,服务器要想办法为每个用户保存这些数据:
    如:用户登录场景,当不同的用户登录系统后,我们如何在主页面显示不同的用户名?
  • 会话跟踪技术是一种在客户端与服务器间保持HTTP状态的解决方案,管理浏览器客户端和服务器端之间会话过程中产生的会话数据。从开发角度考虑,是使上一次请求所传递的数据能够维持状态到下一次请求,并且辨认出是否相同的客户端所发送出来的。
  • 会话跟踪技术的解决方案主要分为以下几种:
    Cookie技术
    Session技术
    URL重写技术
    隐藏表单域技术
一、Cookie
  • Cookie技术是一种在客户端保持会话跟踪的解决方案,会话数据保存在客户端浏览器。
  • Cookie在用户第一次访问服务器时,由服务器通过响应头的方式发送给客户端浏览器;当用户再次向服务器发送请求时会附带上这些文本信息。
  • 在使用Cookie时,要保证客户端浏览器接受Cookie。


    Servlet会话跟踪_第1张图片
  • 存储Cookie会话数据

1.构造Cookie对象

  • Cookie(java.lang.String name, java.lang.String value);

2.设置cookie

  • void setPath(java.lang.String uri):设置cookie的有效访问路径。
    默认cookie只能由创建它的应用获得,设置cookie.setPath(“/”),则可在同一应用服务器内的所有应用共享访问。
  • void setMaxAge(int expiry) : 设置cookie的有效时间
    该Cookie失效时间,单位秒。如果为正数,则该Cookie在expiry秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1
  • void setValue(java.lang.String newValue) :设置cookie的值
    Cookie的值不能设置成非ASSIC字符,如果要使用中文可以通过URLEncoder将其编码,否则会出异常。
    Cookie大小和数量的限制,不同的浏览器有所区别,一般每个域名最多可存储
    50个cookie,Cookie总的的大小限制为4KB。

3.将Cookie对象响应给客户端浏览器,存储在客户端。

  • void response.addCookie(Cookie cookie) : 发送cookie
@WebServlet("/CookieStorageServlet")
public class CookieStorageServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      Cookie ck1 = new Cookie("name",URLEncoder.encode("张三","UTF-8"));
      Cookie ck2 = new Cookie("jSessionId", "10001");
      Cookie ck3 = new Cookie("email","[email protected]");
      Cookie ck4 = new Cookie("status","1");
      ck1.setMaxAge(-1);//默认值
      ck2.setMaxAge(0);//删除cookie
      ck3.setMaxAge(24*60*60);//设置1天后失效
      ck3.setPath("/ch03-cookie/shopping");
      ck4.setMaxAge(10);//10秒后失效
      response.addCookie(ck1);
      response.addCookie(ck2);
      response.addCookie(ck3);
      response.addCookie(ck4);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request, response);
  }
}
  • 获取Cookie会话数据

存储在客户端的Cookie,通过HttpServletRequest对象的getCookies()方法获取,该方法返回所访问网站的所有Cookie的对象数组,遍历该数组可以获得各个Cookie对象。

@WebServlet("/CookieGetServlet")
public class CookieGetServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      response.setContentType("text/html;charset=UTF-8");
      request.setCharacterEncoding("utf-8");
      PrintWriter out = response.getWriter();
      
      Cookie[] cookies = request.getCookies();
      for(Cookie c:cookies) {
          if("name".equals(c.getName())) {
              out.println("

" + URLDecoder.decode(c.getValue(),"UTF-8") + "

"); }else { out.println("

" + c.getValue() + "

"); } out.println("

" + c.getName() + "

"); out.println("=========================="); } out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

  • Cookie的局限性
  • Cookie可能被禁用,当用户非常注重个人隐私保护时,很可能会禁用浏览器的Cookie功能;
  • Cookie可能被删除,因为每个Cookie都是硬盘上的一个文件,因此很有可能被用户删除;
  • Cookie的大小和个数受限,不同浏览器有所区别,Cookie保存的数据不能超过4095个字节,50个/每个域名;
  • Cookie安全性不够高,所有的Cookie都是以纯文本的形式记录于文件中,因此如果要保存用户名密码等信息时,最好事先经过加密处理。
二、Session
  • Session是指使用HttpSession对象实现会话跟踪的技术,是一种在服务器端保持会话跟踪的解决方案。
  • HttpSession对象会在用户第一次访问服务器时由容器创建(注意只有访问JSP、Servlet等程序时才会创建,只访问HTML、IMAGE等静态资源并不会创建),当用户调用其失效方法(invalidate()方法)或超过其最大不活动时间时会失效。在此期间,用户与服务器之间的多次请求都属于同一个会话。
  • Session和Cookie的主要区别在于:
    Cookie是把用户的数据写给用户的浏览器。
    Session技术把用户的数据写到用户独占的session中。
  • Session工作原理

服务器在创建会话对象时,会为其分配一个唯一的会话标识——SessionId,以“JSESSIONID”的属性名保存在客户端Cookie中,在用户随后的请求中,服务器通过读取Cookie中的JSESSIONID属性值来识别不同的用户,从而实现对每个用户的会话跟踪。


Servlet会话跟踪_第2张图片
  • 获取HttpSession对象
@WebServlet("/CreateSessionServlet")
public class CreateSessionServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取HttpSession对象标识sessionid
        out.println("

" + session.getId() + "

"); //获取HttpSession对象产生的时间,单位是毫秒 out.println("

" + session.getCreationTime() + "

"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
  • Session存取数据
  • 存储会话域属性
    session.setAttribute("username"," neuedu ");
  • 会话域中获取属性值
    String uname = (String)session.getAttribute("username");
  • 会话域中删除属性
    session.removeAttribute("username");
  • 例:当用户当用户登录成功后,将用户信息存储到session中,并重定向到主页面显示用户信息。




Insert title here


    


@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取session对象
        HttpSession session = request.getSession();
        //模拟登陆成功
        String userName = request.getParameter("userName");
        //向session中存储用户名
        session.setAttribute("userName",userName);
        response.sendRedirect("index");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获取session对象
        HttpSession session = request.getSession();
        String userName = (String)session.getAttribute("userName");
        //判断是否登录成功:
        if(userName == null || "".equals(userName)) {
            //没有登录成功,跳转到login.html
            response.sendRedirect("login.html");
            return;
        }
        //设置session的非活动时间
        session.setMaxInactiveInterval(10);
        out.println("

欢迎你:" + userName + "

"); out.println("退出登录"); out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

  • Session生命周期
  • Session失效时间
    session具有一定声生命周期,如果session超过会话的最大不活动时间,会话自动失效,会话的最大不活动时间指会话超过此时间段不进行任何操作;
  • 设置Session的失效时间
    方法1:在工程的web.xml中配置session的生命周期,单位为分钟;
    15
    方法2:在程序硬编码设置
    session.setMaxInactiveInterval(30 * 60);//设置单位为秒,设置为-1永不过期;
    方法3:在Tomcat安装目录下conf/web.xml中配置(Web容器级别)
    15
  • 手动销毁Session
    可以通过调用invalidate()方法立即清除会话对象及其所有会话域属性,同时响应客户端浏览器清除Cookie中的JSESSIONID
  • 在实际应用中,此方法多用来实现系统的“安全退出”功能。
@WebServlet("/logout")
public class LogoutSerlvet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        //手动销毁sessoin
        request.getSession().invalidate();
        response.sendRedirect("login.html");
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}
三、其它会话技术
  • URL重写技术
  • URL重写技术是实现动态网站会话跟踪的重要保障。在实际应用中,当客户端浏览器禁用Cookie后的session处理,当不能确定客户端浏览器是否支持Cookie的情况下,使用URL重写技术可以对请求的URL地址追加会话标识,从而实现用户的会话跟踪功能。
  • 例如,对于如下格式的请求地址:
    http://localhost:8080/Demo/EncodeURLServlet
    经过URL重写后,地址格式变为:
    http://localhost:8080/Demo/EncodeURLServlet;jsessionid=24666BB458B4E0A68068CC49A97FC4A9
    其中:“jsessionid”即为追加的会话标识,服务器即通过它来识别跟踪某个用户的访问。
  • URL重写实现方法
@WebServlet("/UrlRewriterServlet")
public class UrlRewriterServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();
      HttpSession session = request.getSession();
      // 两个请求地址进行URL重写
      String link1 = response.encodeURL("UrlRewriterResultServlet");
      String link2 = response.encodeURL("UrlRedirectServlet");
      // 使用超链接形式对URL重写地址进行请求
      out.println("

对一个普通Servlet的请求

"); out.println("

对一个含有重定向代码的Servlet的请求

"); } protected void doPost(HttpServletRequest request, HttpServletResponse >response) throws ServletException, IOException { doGet(request, response); } }
@WebServlet("/UrlRewriterResultServlet")
public class UrlRewriterResultServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      java.io.PrintWriter out = response.getWriter();
      // 获取经URL重写传递来的会话标识值
      String sessionId = request.getSession().getId();
      out.println(sessionId);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      doGet(request, response);
  }
}
@WebServlet("/UrlRedirectServlet")
public class UrlRedirectServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      String url = response.encodeRedirectURL("UrlRewriterResultServlet");
      response.sendRedirect(url);
  }
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub
      doGet(request, response);
  }
}
  • URL重写技术应用注意事项:
    1.如果应用需要使用URL重写,那么必须对应用的所有请求(包括所有的超链接、表单的action属性值和重定向地址)都进行重写,从而将jsessionid维持下来;
    2.由于浏览器对URL地址长度的限制,特别是在对含有查询参数的GET请求进行URL重写时,需要注意其总长度;
    3.由于静态页面不能进行会话标识的传递,因此所有的URL地址都必须为动态请求地址。
  • 隐藏表单域
  • 利用Form表单的隐藏表单域,在用户无法从页面显示看到隐藏标识的情况下,将标识随请求一起传送给服务器处理,从而实现会话的跟踪。
  • 在Form表单中定义隐藏域
  • 在服务器端通过HttpServletRequest对象获取隐藏域的值
    String flag = request.getParameter("userID");

你可能感兴趣的:(Servlet会话跟踪)