Session会话技术

一、session基础

解决浏览器和服务器间的数据共享问题。

1.创建session对象

    HttpSession session=request.getSession();

    HttpSession session=request.getSession(false);

    false:在内存中查找,如果找不到也不创建session(只查找不创建)

2.属性设置,删除和获取:

    session.setAttribute("name","张三");

    String nameString=session.getAttribute("name");

    session.removeAttribute("name");

3.获得session 的id

    session.getId();

4.生命周期:

    a.默认存储在浏览器的缓存中,浏览器关闭即结束;如果浏览器不关闭,默认的生命周期为:由开发者决定,tomcat默认30分钟.

        tomcat session生命周期设置:

       

            30

        

    b.可存储在硬盘上(一般不存储,没有必要),存储步骤如下:

        Cookie cookie=new Cookie("JSESSION",session.getId());

        cookie.setMaxAge(Integer.MAX_VALUE);

        cookie.setPath(request.getContextPath());

        response.addCookie(cookie);

    c.设置立刻失效

        session.invalidate();

二.session的应用:

1.购物车

    思路:将物品放在集合中,集合再放在session中。

    (1).显示所有的书籍以及书籍信息链接,并提供查看购物车的超链。

    (2).显示每一本书的详细信息,提供放入购物车的链接并提供书籍id,以及返回首页的链接。

    (3).查看购物车

        a.从session中获取所购书籍集合

            List list=(List)request.getSession().getAttribute("carlist");

            if(list=null){

                outer.writer("您还没有选择要购买的书籍...");

                outer.writer("返回");

                return 0;

            }

            outer.write("购买书籍如下");

            for(Book book:list){

                outer.write(book.getName()+":"+book.getCount()+"
"));

            }

            outer.write("继续购物
");

            outer.write("结账
");

    (4).将购买的书籍放入购物车中。

        a.首先从session中拿取集合对象。

            HttpSession session=request.getSeesion();

            List list=(List)session.getAttribute("carlist");

            第一次访问时carlist不存在,需创建。

        b.找到要放入购物车的商品id

            String bookid=request.getParameter("id");

            Book book=BookUtils.getBookById(bookid);

        c.判断集合中是否已经购买了该书

            //直接获得该书在集合中的索引。

            int index=list.indexOf(book);//需重写equals方法,在book类中。

            /*

                public boolean equals(Object obj){

                    Book b=(Book)obj;

                    return id.equals(b.getId());

                }

            */

            如果没有购买

            if(index==-1){

                book.setCount(1);

                list.add(book);

            }else{

                //书的属性是没有数量的,实际中需要另外建立类文件存储。

                Book book=list.get(index);

                book.setCount(book.getCount()+1);

            }

        d.将添加后的书籍列表存入session

            session.setAttribute("carlist",list);

        e.打印放入购物车成功信息,并提供返回首页按钮。

    (5)结账

        a.判断支付页面是否直接访问(如果直接访问,session为新创建的)

            HttpSession session=request.getSession();

            //判断session是否为新创建的

            //实际当中不能使用该方法(如果多次刷新该页面即可破解该步骤);

            if(session.isNew()){

                outer.write("需要先添加购物商品...两秒后自动跳转到主页...");

                response.setHeader("Refresh","2;url="+request.getContextPaht()+"/servlet/ShowAllBook");

            }

        b.拿到购物车中的信息并统计价格

            List list =(List)session.getAttribute("carlist");

            float sum=0;

            for(Book book:list){

                sum+=book.getPrice()*book.getCount();

            }

            outer.writer("商品总价为:"+sum+"$
");

2.防止重复提交

    思路:在服务端设置”口令“,该”口令“只有一次有效期,客户端有一个和服务端相同的”口令。

        第一次提交口令对比成功则提交,提交后口令失效。

        第二次提交时由于口令失效不能提交。

    具体实现:

    (a).提交页面在生成前需先产生一个唯一的“口令”

        如何生成唯一的“口令”

        方式一:

            String word="";

            //生成一个唯一的时间值。

            word=System.nanoTime()+"";

        方式二:

            //生成唯一的值;

            word=UUID.randomUUID().toString();

        //前两种可查看值,不大安全。

        方式三:

            byte[] bs=word.getBytes();

            //数据指纹

            word=System.nanoTime()+new Random().nextLong()+"";   

            //加密数据

            MessageDigest md=MessageDegest.getInstance("MD5");

            //对字节数组进行md5加密。

            bs=md.degest(bs);

            //将加密后的字节数组转化为string

            //引入Base64Encoder: java build path ->access ->Accessable->**

            BASE64Encoder base=new BASE64Encoder();

            word=base.encode(bs);

            将word存入session

            session.setAttribute("tooken",word);

        在表单中放置一个隐藏的文本框

       

        提交时在服务端对word和session中的word进行对比,如果匹配则提交,否则不处理。

    (b).在提交页面中拿到用户名和口令,再拿到session中的口令,并对比两个口令。

        if(clientToken.equals(servToken)){

            //保存用户。

            //用户保存后将口令销毁

            session.removeAttribute("token");

        }else{

            outer.write();

        }

详细代码实现:

表单提交和口令加密部分:

 
  
  1: package net.csing;
  2: 
  3: import java.io.IOException;
  4: import java.io.PrintWriter;
  5: import java.security.MessageDigest;
  6: import java.security.NoSuchAlgorithmException;
  7: import java.util.Random;
  8: 
  9: import javax.servlet.ServletException;
 10: import javax.servlet.http.HttpServlet;
 11: import javax.servlet.http.HttpServletRequest;
 12: import javax.servlet.http.HttpServletResponse;
 13: 
 14: import sun.misc.BASE64Encoder;
 15: 
 16: public class Index extends HttpServlet {
 17: 
 18:   public void doGet(HttpServletRequest request, HttpServletResponse response)
 19:       throws ServletException, IOException {
 20: 
 21:     response.setContentType("text/html;charset=utf-8");
 22:     PrintWriter out=response.getWriter();
 23:     //创建口令
 24:     String word="";
 25:     word=System.nanoTime()+new Random().nextLong()+"";  
 26:     byte[] bs=word.getBytes();
 27:     //加密口令
 28:     MessageDigest md;
 29:     try {
 30:       /*
 31:        * 此部分为口令加密部分。
 32:        */
 33:       md = MessageDigest.getInstance("MD5");
 34:       //对字节数组进行md5加密。
 35:       bs=md.digest(bs);
 36:       //将加密后的字节数组转化为string
 37:       //引入Base64Encoder: java build path ->access ->Accessable->**
 38:       BASE64Encoder base=new BASE64Encoder();
 39:       //编码,word为完成加密后的口令。
 40:       word=base.encode(bs);
 41:     } catch (NoSuchAlgorithmException e) {
 42:       
 43:       e.printStackTrace();
 44:     }
 45:     //向session中写入口令信息;
 46:     request.getSession().setAttribute("token", word);
 47:     
 48:     //设置表单提交路径和提交方式。
 49:     out.write("
"+request.getContextPath()+"/servlet/manage method='post'>");
 50:     out.write("用户名
");
 51:     //口令信息随着表单一块提交。
 52:     out.write("
");
 53:     out.write("");
 54:     /*
 55:      * 该口令只在页面刷新时生成,并写进session中;
 56:      * 如果同一个页面提交多次,表单中的口令为原口令,但session中的口令已经通过服务器设置失效。
 57:      */
 58:     
 59:   }
 60: 
 61:   public void doPost(HttpServletRequest request, HttpServletResponse response)
 62:       throws ServletException, IOException {
 63: 
 64:     response.setContentType("text/html");
 65: 
 66:   }
 67: 
 68: }
 69: 

口令验证:

 
  
  1: package net.csing;
  2: 
  3: import java.io.IOException;
  4: import java.io.PrintWriter;
  5: 
  6: import javax.servlet.ServletException;
  7: import javax.servlet.http.HttpServlet;
  8: import javax.servlet.http.HttpServletRequest;
  9: import javax.servlet.http.HttpServletResponse;
 10: import javax.servlet.http.HttpSession;
 11: 
 12: public class manage extends HttpServlet {
 13: 
 14:   public void doGet(HttpServletRequest request, HttpServletResponse response)
 15:       throws ServletException, IOException {
 17:     response.setContentType("text/html");
 19:   }
 20: 
 21:   public void doPost(HttpServletRequest request, HttpServletResponse response)
 22:       throws ServletException, IOException {
 23: 
 24:     //表单中设置了post提交方式,在doPost函数中处理表单信息。
 25:     response.setContentType("text/html;charset=utf-8");
 26:     
 27:     PrintWriter out=response.getWriter();
 28:     //获得表单中的口令信息;
 29:     String wordString=request.getParameter("token");
 30:     //获得session中的口令信息;
 31:     HttpSession session=request.getSession();
 32:     String word=(String)session.getAttribute("token");
 33:     //将session中的口令和表单中的口令进行对比。
 34:     //如果口令对比成功则设置该口令立即失效,该口令只能使用依次,即仅进行一次提交。
 35:     if(wordString.equals(word)){
 36:       out.write("提交成功");
 37:       session.removeAttribute("token");
 39:     }
 40:     //如果口令不对,则为重复提交。
 41:     else{
 42:       out.write("请不要重复提交。");
 43:     }
 44:   }
 46: }

3.客户端禁止cookie如何解决?

    (a).告诉客户端不要禁止。

    (b).URL重写

        目的:在网址之后附加JSESSIONID:id;(传递本页面的JSESSION到请求的页面)

        解决部分客户端浏览器禁止cookie导致session不能用。

        url=request.getContextPath+"/servlet/servletDemo2";

        url=response.encodeURL(url);

        缺点:所有的url都需要重写,比较麻烦。

4.session的状态

    获取session的状态,防止服务器出现故障;或者服务器内存不够(服务器将释放部分内存)。

        服务器重启时需将session数据存储到硬盘中防止数据丢失,重启后重新读取到内存。

        session存储到硬盘的过程叫做搁置或者固化;

        session从硬盘重新读取到内存的过程叫做激活或者活化;

你可能感兴趣的:(Session会话技术)