JavaWeb开发中的会话技术[Cookie/Session]

会话

会话:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。

会话过程中要解决的一些问题:

  • 每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自回产生一些数据,程序要想办法为每个用户保存这些资源。电商中的保存用户的购买的商品。

保存会话数据的两种技术

  • Cookie:Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去,这样web资源处理的就是用户自己的数据。
  • Session:Session是服务器技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其他web资源时,其他的web资源再从用户各自德尔session中取出数据为用户服务。
  • Cookie的访问过程:
    JavaWeb开发中的会话技术[Cookie/Session]_第1张图片

  • javax.servlet.http.Cookie类用于创建一个Cookie,response接口也定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。同样在request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。

  • Cookie类的方法有(最好查看其API):

    • public Cookie(String name, String value)
    • setValue 与 getValue
    • setMaxAge 与 getMaxAge() [秒]
    • setPath 与 getPath
    • setDomain 与 getDomain
    • getName
  • 一个Cookie是一个键值对。

  • 通过Cookie可以保存用户的信息,示例:保存用户的上次的访问的时间并显示出来(通过request获取请求头中带有的Cookie,再通过response的响应头将Cookie值返回给浏览器):

package com.hsx.cookie;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

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 com.hsx.constant.MyConstant;

/**
 * 保存用户的上次的访问的时间并显示出来
 * @author hsx
 *
 */
public class CookieDemo1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("您上次获取的时间是:");
        // 从客户端的请求获取指定的cookie
        Cookie[] cookies = request.getCookies();
        System.out.println(cookies); // 第一次访问时cookie的值可能为null
        for (int i = 0; cookies != null && i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            System.out.println(cookie.getName());
            if (MyConstant.LAST_ACCESS_TIME.equals(cookie.getName())) {
                long value = Long.parseLong(cookie.getValue());
                out.println(new Date(value).toLocaleString());
            }
        }
        // 把当前的时间写给客户端
        Cookie cookie1 = new Cookie(MyConstant.LAST_ACCESS_TIME, System.currentTimeMillis() + "");
        cookie1.setPath(request.getContextPath());
        cookie1.setMaxAge(10 * 24 * 60 * 60); //存活的时间,默认浏览器的进程
        response.addCookie(cookie1);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        this.doGet(request, response);
    }

}

--------------------------------------------------------

/**
 * 常量接口设计模式(这里只是设置了Cookie的name值)
 * @author hsx
 *
 */
public interface MyConstant {

    String LAST_ACCESS_TIME = "lastAccessTime";
}
  • Cookie细节:
    • 获取Cookie采用:request.getCookies();
    • 设置Cookie采用:response.addCookie(cookie);
    • 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(name)和设置值(value)。
    • 一个Web站点可以给一个Web浏览器发送多个Cookie,一个Web浏览器也可以存储多个Web站点提供的Cookie。
    • 浏览器一般存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
    • 如果创建了一个Cookie,并将它发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该Cookie存储在磁盘上,则需要使用maxAge(默认是浏览器的进程),并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该Cookie。
    • path:默认是产生cookie的应用的访问路径,删除Cookie时,path必须一致,否则不会删除。在应用程序中设置Cookie时[cookie.setPath(“xxx”)]注意:
    • 如果设置了路径,只能被包含的此路径的资源访问。
    • 如果设置的路径是”/servletCS”,该Cookie只能被servletCS这个应用访问。
    • 如果设置的路径是”/servletCS2”,虽然是servletCS应用产生的Cookie,但是该Cookie只能被servletCS2这个应用访问,servletCS是访问不到的。
    • cookie.setPath(request.getContextPath())这条语句设置的Cookie是本身这个应用的。由此可得:request.getContextPath()是获取该应用[项目]的路径。
    • 如果设置的路径是cookie.setPath("http://localhost:8080/")或者cookie.setPath("/")这条语句设置的Cookie能被”http://localhost:8080/“下的所有的应用访问。
    • 如果设置的路径是cookie.setPath("http://localhost:8080/ServletCS/servlet/")这条语句设置的Cookie能只能被该Servlet访问;即某个Servlet的url-pattern配置是servlet2,则该servlet2都不能访问其Cookie。
    • 总结:Cookie是否能被访问到是根据其设置的路径而言的。
//--- 删除指定的cookie  cookie.setMaxAge(0);---//
// 先获取指定的Cookie
Cookie[] cookies = request.getCookies();
for (int i = 0; cookies != null && i < cookies.length; i++) {
    Cookie cookie = cookies[i];
    if (MyConstant.LAST_ACCESS_TIME.equals(cookie.getName())) {
        //设置其maxAge(0):必须有path一致
        cookie.setMaxAge(0);
        cookie.setPath(request.getContextPath());
        //写个客户端
        response.addCookie(cookie);
    }
}
  • Cookie应用
    • 模拟用户名登陆,始终保存用户的用户名[CookieDemo2中输入用户名,提交到CookieDemo3中,CookieDemo3对其用户名的Cookie做永久保存,在以后访问CookieDemo2时,用户名能显示出来]
/*---------------CookieDemo2---------------------*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

    String name = "";
    String rem = "";

    // 从Cookie中获取用户名
    Cookie[] cookies = request.getCookies();
    for (int i = 0; cookies != null && i < cookies.length; i++) {
        Cookie cookie = cookies[i];
        if (MyConstant.USER_NAEM.equals(cookie.getName())) {
            name = cookie.getValue();
            rem = "checked='checked'";
        }
    }

    // 显示出登陆页面
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("");
    out.println("用户登陆");
    out.println("");
    out.println("
"); out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("");out.println("
用户名
密码
+ rem + " />记住用户名
"
); out.println(""
); out.println(""); out.println(""); } /*------------------CookieDemo3--------------------------*/ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); Cookie cookie = null; String remember = request.getParameter("remember"); System.out.println(remember); if (remember != null) { cookie = new Cookie(MyConstant.USER_NAEM, request.getParameter("username")); cookie.setPath(request.getContextPath()); cookie.setMaxAge(Integer.MAX_VALUE); //永久保存 response.addCookie(cookie); } out.println(cookie.getName() + "
"
); out.println(cookie.getValue()); } /*--------------------常量接口设计模式------------------------*/ public interface MyConstant { String USER_NAEM = "username"; }

Seesion

  • session的访问过程
    JavaWeb开发中的会话技术[Cookie/Session]_第2张图片

  • 在Web开发中,服务器可以为每一个用户浏览器创建一个会话对象(Session对象),注意:一个浏览器独占一个Session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的Session中,当用户使用浏览器访问其他程序时,其他程序可以从用户的Session中取出该用户的数据,为用户服务。

  • Session和Cookie的主要区别在于:
    • Cookie是把用户的数据写给用户的浏览器。
    • Seesion技术把用户的对象写到用户独占的session中。
  • Session对象是由服务器创建的,开发人员可以调用request对象的getSession方法得到session对象。
  • Session技术实际上用的Cookie技术。图解说明:
  • 注意:
    • IE7及以下版本,新开的窗口都会开启一次新会话。
    • 每一个客户端都有各自的Session对象,以SeesionID标识。
    • Seesion技术实际上是借助Cookie技术实现的,在创建Session对象时,会将该Session对象的ID以Cookie的JSESSIONID=SessionID的形式写给客户端。
    • session的原理图:
      JavaWeb开发中的会话技术[Cookie/Session]_第3张图片
    • Session默认何时时效?时间到了,就会失效,默认是30分钟。更改Session的默认时间:
      在web.xml文件的根元素中增加,单位为分钟。
<session-config>
    <session-timeout>1ssession-timeout>
session-config>

注意:

request.getSession(); // 要是没有Session对象,就立马创建Session对象
request.getSession(false); // 设置了false,要是没有Session对象,不会创建session对象。
  • IE禁用Cookie后的session处理
    • 解决方案:URL重写(以下方法先检查浏览器是否禁用Cookie,若禁用Cookie那么会在地址栏上加上jsesssionid=xxx,若没有禁用Cookie那么不加jsessionid–>很智能。注意:当禁用Cookie后,要对所有的URL进行重写)
    • response.encodeRedirectURL(java.lang.String url); //用于对sendRedirect方法后的url地址进行重写。
    • response.encodeURL(java.lang.String url); //用于对表单action和超链接的url地址进行重写。
String url1 = request.getContextPath() + "/PayServlet";
url1 = response.encodeURL(url1);
out.println("
结账"
);
  • 案例:
/*-----IndesServlet-----显示所有的商品,提供购买链接 -- 放入购物车*/ 

response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("");
out.println("商品");
out.println("");
// 显示所有的商品
List productList = Product.getAllProduct();
out.println("本站有以下好商品:
"
); for (String product : productList) { out.println(product); String url = request.getContextPath() + "/BuyServlet?name=" + product; url = response.encodeURL(url); //禁用浏览器的Cookie时使用的 out.println("购买
"
); } // 转向结账 String url1 = request.getContextPath() + "/PayServlet"; url1 = response.encodeURL(url1); out.println("
结账"
); out.println(""); out.println(""); out.close(); /*-----BuyServlet-----购买的Servlet,将商品加入购物车*/ String productName = request.getParameter("name"); productName = new String(productName.getBytes("ISO-8859-1"), "UTF-8"); // 查看Session中是否有购物车 HttpSession session = request.getSession(); Object object = session.getAttribute(MyConstant.MY_CART); if (null != object) {// 有:取出来,放商品 List cartList = (List) object; cartList.add(productName); } else {// 没有,先构件购物车 List cartList = new ArrayList(); cartList.add(productName); session.setAttribute(MyConstant.MY_CART, cartList); } response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("您已经购买了:" + productName); String url = request.getContextPath() +"/IndesServlet"; url = response.encodeURL(url); out.println("

继续购买"
); /*-----PayServlet-----显示购物车中的商品*/ response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); HttpSession session = request.getSession(false); //只是取 if (session == null) { out.println("您还未购物"); } else { List myCartList = (List) session.getAttribute(MyConstant.MY_CART); out.println("您购买了以下商品:
"
); for (Object object : myCartList) { out.println(object + "
"
); } } out.close();
  • Session开发中遇到的问题?
    1. 内存中的Session非常多,怎么办?
    2. 用户在购物中,服务器停了该web应用(或者重启了),那么用户购物车中的东西怎么办?
      • 解决办法:将内存中的Session持久化。
      • 何时session会被持久化?[具体是根据服务器的实现定的,对用户来说完全是透明的]
    3. 当服务器停止当前应用
    4. 内存中的session对象太多
    5. session长时间没有活动(并没有被销毁)
      • 何时会被激活?
    6. 当前web应用又启动了
    7. 用户又开始使用了(鼠标、键盘又开始使用了)
      • session中的序列与反序列基本图:
        JavaWeb开发中的会话技术[Cookie/Session]_第4张图片

你可能感兴趣的:(javaee)