Servlet中session的使用


前言

这一篇主要介绍了servlet中的session以及一个session的小案例。


一、Session的概念

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
下面画个图来看下session的工作原理:
在这里插入图片描述
所以对于session来说,不同的客户的数据,其实是通过一个key为JSSESIONID的cookie来区分的。

二、Session常用API

上图中我们已经看到了几个session相关的API,这里我们具体来说下用处:

  • request.getSession() :得到HttpSession对象,在我们设置或者是获取session中的数据时,我们都需要先得到这个对象。
  • session.setSession():设置session;比如,我们设置一个key为name的session,就可以这样写:session.setAttribute(“name”, “xxx”);
  • session.getSession():拿到session的值,这个很好理解,传入key值,就可以获取对应的value值。
    (这里需要说明的一点,session是一个域对象,可以被可以被多个请求共享,只要会话不断,就可以共享;
    同样是域对象的还有之前博客里的request和servletContext,他们之前的作用域的大小是不一样的,request的作用域最小,只在一次请求内;session次之,只要是同一个用户且session没有过期,都可以访问到;servletContext最大,是在一整个应用内有效)
  • session.getId():获取session的id值,通过这个值,我们可以看到,不同的客户端去访问同一个地址,它的session是不同的。这里有一张图,分别用Chrome游览器的普通窗口和无痕窗口来模拟两个不同的用户,我们在servlet中输出session的id:
    在这里插入图片描述
    (忽视图片中其他的字,这是我们案例中的例子。这里我们只观察,不同客户端去访问同一个url,我拿到的id值是不同的,这也印证了session的工作原理,解释了它为什么能为不同的用户提供各自的资源了。)
  • setMaxInactiveInterval():session过期时间,以秒为单位
  • session.incalidate():调用就强制销毁session

三、getSession的内部原理

上面讲解了API的作用,这里我们写个小演示代码:

//在demo1中,通过url传入的name,设置一个session
public class SessionDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        String name = req.getParameter("name");
        HttpSession session = req.getSession();
        session.setAttribute("name",name);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}
//这里访问demo2,获取session
public class SessionDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        HttpSession session = req.getSession();
        String name = (String)session.getAttribute("name");
        writer.print(name);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

看了上面两端代码,不免有个疑问,为什么我去获取一个session里面的值,也要用getSession()去得到session对象?这两个session对象里面会存同一个值么?结果我们当然知道,demo1和demo2两个servlet用的是同一个session对象。但是为什么呢?
这里,我们就需要看下getSession的工作原理了,当我们执行getSession() 的时候,实际的执行过程是这样的:

  1. 获取名为JSESSIONID的cookie值;
  2. 没有这样的cookie,就创建一个新的HttpSession对象,分配唯一的sessionId,并向客户端回写名为JSESSIONID的cookie
  3. 如果有这样的cookie,就获取这个cookie的值,从服务器中根据ID找到HttpSession对象
  4. 找到了,就取出来
  5. 找不到重新创建,回到步骤2的过程

看完原理,我们还有个小注意点:
getSession()里面是可以传入参数的:getSession(boolean create)

  • true:和getSession()功能一样
  • false:根据客户端JESSIONID的cookie值,找到对应的HttpSession对象,找不到就返回null,不会创建新的,只是查询(一般不用)

四、Session小案例

最后通过一个购物车的小案例来回顾下session中API的使用:
我们需要达到以下效果:
在这里插入图片描述
访问index的时候,列出所有的图书名,以及购物车的链接;未加入商品到购物车的时候,提示购物车为空;点击书籍链接,即视为加入购物车,提示添加成功,并且进入购物车可以查看到这个书籍。

//这是index页面展示的内容
public class IndexHome extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.print("以下是本站在售的书籍:<br/>");
        Map<String, Book> books = DBUtils.getAllBooks();
        for (Map.Entry<String, Book> book : books.entrySet()) {
            String id = book.getKey();
            writer.print("<a href='"+req.getContextPath()+"/session/addCart?id="+id+"'>"+book.getValue().getName()+"</a><br/>");
            //查询出每本书的名字,并且用一个链接跳转,提示添加购物车结果
        }
        writer.print("<a href='"+req.getContextPath()+"/session/cart'>你的购物车</a><br/>");
        //购物车的跳转链接
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
//购物车的页面,这里主要是拿到session中保存的书籍信息,并展示出来
public class Cart extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        HttpSession session = req.getSession();
        writer.print("这是你的购物车:<br/>");
        List<Book> books = (List)session.getAttribute("cart");
        if(books!=null) {
            for (Book book : books) {
                writer.print(book.getName() + "<br/>");
            }
        }else {
            writer.print("你还没有加入商品到购物车中哦~");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
//这里主要是为了处理加入购物车这个动作的业务
//我们先拿到session中购物车的对应信息,如果没有书籍,那我们需要创建一个list存放书籍对象
//其次,我们还要做一个判断,我们的有书籍的list中是否有当前这个书籍,有的话,就不重复添加,没有的话,我们就加进购物车
public class AddCart extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        String id = req.getParameter("id");
        Book book = DBUtils.getBook(id);
        HttpSession session = req.getSession();
        List<Book> list = (List)session.getAttribute("cart");
        if(list==null){
            list = new ArrayList<>();
        }
        if (!list.contains(book)) {
            list.add(book);
            session.setAttribute("cart", list);
            writer.print("添加成功");
        }else {
            writer.print("这本书已经在你的购物车中啦~");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

总结

到这里,session的使用就介绍完了,其实session的API还是很好记的,常用的也不是很多。对于session的学习来讲,理解session的工作原理比较重要。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值