【Java之会话技术】

会话技术

使用的场景:在web访问的过程中,会话指的就是客户端与服务端之间的通讯过程

HTTP协议无状态性:无状态性体现在在服务器看来,所有的客户端发送过来的请求报文都是完全相同的,服务器压根无法通过HTTP请求报文来区分各个不同的客户端

此时就需要使用Cookie来进行客户端和服务端之间的交流,以此来区分各个不同的客户端

会话技术主要是用来帮助服务端给客户端保存相关数据的

Cookie

客户端技术。客户端技术是指的是数据的存储、保存是在客户端进行的。

数据的产生是在服务器产生的,服务器在做出响应时,会把cookie信息返回给客户端(set-Cookie:key=value响应头),客户端接收到该信息之后,会将该cookie保存下来

当它再次访问服务器时,那么就会把该cookie给再次携带给服务器(Cookie:key=value请求头),通过这种方式,就可以知道请求来自于哪个客户端了。

Cookie本质上是一个响应头,数据是放在响应头中的

Cookie可以作用在服务器上的多个页面中

Cookie的值要求必须是字符串且不能包含空格

使用

使用的三个步骤

1.生成cookie对象

2.利用response.addCookie(cookie)将cookie发送给客户端

3.利用request.getCookies()可以接收cookie

在获取cookie的时候一定要注意判空!!

cookie有很多个,具体在使用的时候也需要使用if判断,否则报错

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        //每次服务器接收浏览器的请求的时候,都应该先获取cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                System.out.println(cookie.getName() + ":" + cookie.getValue());
            }
        }
        Cookie cookie = new Cookie("forrr", "haha");//新建一个cookie用于返回给客户端
        response.addCookie(cookie);
    }
}

案例

登录案例:用户通过登录页面进行登录,登录成功之后进入一个新的页面, 要求可以显示出用户的用户名

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //这里面需要获取cookie并转发到欢迎页面
    //首先要获取到请求参数
    request.setCharacterEncoding("utf-8");
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    //新建cookie
    Cookie cookie = new Cookie("username", username);
    //将cookie发送给客户端
    response.addCookie(cookie);
    //跳转页面
    response.setHeader("refresh","2;url="+request.getContextPath()+"/infoc");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //这里只需要获取cookie然后进行判断即可
    response.setContentType("text/html;charset=utf-8");
    Cookie[] cookies = request.getCookies();
    if (cookies!=null){
        for (Cookie cookie : cookies) {
            if ("username".equals(cookie.getName())){
                //如果cookie的名字是username,那么就说明是用户名,输出即可
                response.getWriter().println("登陆成功"+ cookie.getValue());
            }
        }
    }
}

显示用户上次访问时间:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //因为cookie不能含有空格,那么这里的思路就是将当前时间的毫秒数设置到cookie中,显示的时候就转换成data
    //访问的时候也是get请求,获取cookie
    Cookie[] cookies = request.getCookies();
    if (cookies!=null){
        for (Cookie cookie : cookies) {
            if ("date".equals(cookie.getName())){
                //因为cookie有很多个,那要找到是date的那个
                String value = cookie.getValue();
                Date date = new Date(Long.parseLong(value));
                response.getWriter().println(date);
            }

        }
    }

    //先写设置cookie的逻辑
    Cookie cookie = new Cookie("date", System.currentTimeMillis() + "");
    response.addCookie(cookie);
}

设置

设置存活时间

默认情况下,如果没有设置,则cookie的有效期是在浏览器开启的这段时间内有效(也就是存活在浏览器的内存中),浏览器关闭则失效;如果希望cookie可以持久化保存,则可以设置一个MaxAge=正数,表示的是在硬盘上存活多少秒

设置负数,其实就是默认情况,存在于浏览器内存中

设置为0就表示删除cookie

删除cookie

设置MaxAge=0,然后将该设置发送给客户端,一定要发送,否则无效

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   //访问5次后就删除cookie
    Cookie[] cookies = request.getCookies();
    if (cookies!=null){
        for (Cookie cookie : cookies) {
            if ("date".equals(cookie.getName())){
                count++;
                //因为cookie有很多个,那要找到是date的那个
                String value = cookie.getValue();
                Date date = new Date(Long.parseLong(value));
                response.getWriter().println(date);
                if (count==5){
                    cookie.setMaxAge(0);
                    response.addCookie(cookie);
                    return;
                }
            }

        }
    }
    //先写设置cookie的逻辑
    Cookie cookie = new Cookie("date", System.currentTimeMillis() + "");
    cookie.setMaxAge(180);
    response.addCookie(cookie);
}
设置路径

设置cookie的有效路径

默认情况下,访问当前服务器的所有资源时都会携带cookie,可以设置一个路径,仅当访问指定路径时才会携带cookie

如果设置了path,再次去删除cookie,那么此时需要注意,在删除时,必须要把path在写一遍,否则无法删除

如果cookie没有设置path,那么直接设置MaxAge=0即可

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Cookie cookie = new Cookie("name", "zs");
    cookie.setPath(request.getContextPath()+"/path2");
    response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
        IOException {
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("name".equals(cookie.getName())){
                String value = cookie.getValue();
                response.getWriter().println(value);
                cookie.setMaxAge(0);
                cookie.setPath(request.getContextPath()+"/path2");
                response.addCookie(cookie);
            }
        }
    }
}
设置域名

客户端对于设置指定域名的cookie是有限制的。你不可以设置和当前域名无关的cookie

比如当前域名是localhost,你设置了一个域名是baidu.com的cookie,不允许的(安全性考虑)

但可以进行父子类名的设定

ccc.com

xxxx.ccc.com

比如,你当前所在的系统是在ccc.com,你设置了一个域名是ccc.com的cookie

紧接着你去访问sub.ccc.com,那么此时多个域名的系统之间可以共享当前的cookie信息

好处是可以运用在一个集团的系统中

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Cookie cookie = new Cookie("domain", "fh.com");
    cookie.setDomain("fh.com");
    response.addCookie(cookie);
}

cookie优缺点

优点:小巧、减轻了服务器压力

缺点:容量有限制、存储字符串、只能够存储一些非敏感数据

Session

服务器技术。

数据的产生以及数据的存储均是在服务器上面完成的。相当于一个客户端和一个session对象进行绑定。

只要是同一个客户端访问不同的servlet,都可以拿到同一个session对象,session就可以作为一个共享数据的场所。

但是由于HTTP协议的无状态性,服务器无法识别不同的客户端,于是就需要借助于Cookie,服务器使用cookie将JESESSIONID传给客户端,客户端下次访问的时候带着这个id,这样就可以拿到同一个session对象

使用

拿到session对象

HttpSession getSession()

如果当前请求有关联的session对象,那么返回;如果没有关联的对象,就需要创建一个;必须携带一样的id才会返回

HttpSession getSession(boolean create)

如果当前请求有关联的session对象,那么返回;如果没有关联的session对象,并且create是true,则创建一个,如果是false,则返回null。

如何判断当前请求有没有关联的session对象?

仅凭请求报文中有没有携带Cookie:JSESSIONID=xxxx(key一定要求是固定的写法)

如果自定义一个session可能会有问题,必须使用session.getId()

因为必须要使用相同的ID来获取同一个session对象,如果是自定义的会导致id不同

如果不使用request.getSession,那么是不会创建对象的,本质是这个原因

Session的执行过程

第一次访问request.getSession会创建一个新的Session对象

第二次再访问则不会创建对象

关闭浏览器之后再次访问会创建新的session对象,因为此时请求头中没有用携带的cookie了,关闭浏览器会使cookie失效

利用session对象进行数据存取

HttpSession session = request.getSession();
session.setAttribute("username", "zhangsan");

取出数据

Object username = session.getAttribute("username");

三个域的区别

Context:存储一些全局性的数据,服务器上的任何客户端都可以访问

Session:存一些用户的数据,同一个客户端之间数据共享,不同的客户端不能共享,通过cookie中的JESSIONID来判断

request:某一次请求时需要用到,后面就不用了,只有转发的两个组件之间可以共享,其他的不行

问题一:关闭浏览器,session对象会销毁吗?数据能访问到吗?

没有,数据访问不到了。

生成了一个新的session对象,使得原先的session以及数据不可达。

问题二:关闭服务器,session对象会销毁吗?数据能访问到吗?

销毁了后依然可以访问到,不能通过idea来验证,原因是idea的tomcat在重启的时候会将原先的tomcat相关文件全部删除,然后重新读取新的tomcat配置文件

使用tomcat管理器来关闭应用

1.本地tomcat的webapps下需要有maanger应用

2.本地tomcat conf/tomcat-users.xml文件配置

<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>

重启服务器之后,session的地址发生了变化,但是session的id以及数据均没有变化。

服务器关闭时,会将session的相关信息全部序列化到本地硬盘上面

下次再次启动时,服务器会重新读取序列化文件里面的数据,生成新的session对象,将文件里面的信息全部注入到新的session对象中。

如何使用本地tomcat来部署我们idea里面的web应用

复制idea中的映射地址即可

购物车案例

主页

package com.fh.Session.cart;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(value = "/index",loadOnStartup = 1)
public class IndexServlet extends HttpServlet {
    @Override
    public void init() throws ServletException { //初始化商品列表
        Product p1 = new Product("1", "西瓜");
        Product p2 = new Product("2", "梨子");
        Product p3 = new Product("3", "桃子");
        Product p4 = new Product("4", "香蕉");
        List<Product> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        getServletContext().setAttribute("products",list);
    }

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

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        List<Product> products = (List<Product>) getServletContext().getAttribute("products");
        for (Product product : products) {
            //循环打印出商品的列表,根据不同的商品渲染页面
            response.getWriter().println("<div><a href='" + request.getContextPath()+"/product?id="+product.getId()+
                    "'>"+product.getName()+"</a></div>");
        }
    }
}

详情页

package com.fh.Session.cart;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@WebServlet("/product")
public class ProductServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //获取请求参数,判断不同的商品
        String id = request.getParameter("id");
        if (id==null||"".equals(id.trim())){
            response.getWriter().println("参数不合法");
            return;
        }
        //获取商品列表,判断该id对应的是哪个商品,然后再生成页面
        List<Product> products = (List<Product>) getServletContext().getAttribute("products");
        HttpSession session = request.getSession();
        LinkedList<String> footprint = (LinkedList<String>) session.getAttribute("lastView"); //获取历史足迹中的商品列表
        if (footprint==null){
            //如果是null,那么就要创建
            footprint = new LinkedList<>();
            session.setAttribute("lastView",footprint);
        }
        for (Product product : products) { //查看当前商品
            if (id.equals(product.getId())){
                response.getWriter().println(product);
            }
        }
        //查看完毕后,添加进list中
        if (footprint.contains(id)){
            footprint.remove(id);
        }else {
            if (footprint.size()==2){
                footprint.removeLast(); //删除最后一个,因为每次都要放在最新的
            }
        }
        footprint.addFirst(id);
        response.getWriter().println("<a href='" + request.getContextPath() + "/index" + "'>返回首页</a>");
        response.getWriter().println("<a href='" + request.getContextPath() + "/addCart?id=" + id + "'>加入购物车</a>");
        response.getWriter().println("<a href='" + request.getContextPath() + "/viewCart" + "'>查看购物车</a>");
        response.getWriter().println("<a href='" + request.getContextPath() + "/lastView" + "'>查看历史足迹</a>");
    }
}

添加购物车

package com.fh.Session.cart;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/addCart")
public class AddCartServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //获取请求参数,判断不同的商品
        String id = request.getParameter("id");
        if (id==null||"".equals(id.trim())){
            response.getWriter().println("参数不合法");
            return;
        }
        HttpSession session = request.getSession();
        //必须先取出session中的list,如果不去除的话,就会导致每次都重复创建list覆盖
        List<String> cart = (List<String>) session.getAttribute("cart");
        if (cart==null){
            //如果此时的购物车list是null,那么就需要创建,否则就不执行创建,也就不存在覆盖的问题
            cart = new ArrayList<>();
            session.setAttribute("cart",cart);
        }
        cart.add(id);//每次将商品的id添加进去即可
    }
}

查看购物车

package com.fh.Session.cart;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

@WebServlet("/viewCart")
public class ViewCartServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        HttpSession session = request.getSession();
        List<String> cart = (List<String>) session.getAttribute("cart");
        if (cart==null){
            response.getWriter().println("购物车为空");
            return;
        }
        List<Product> products = (List<Product>) getServletContext().getAttribute("products");
        for (String id : cart) {
            for (Product product : products) {
                if (id.equals(product.getId())){
                    response.getWriter().println(product);
                }
            }
        }
    }
}

查看历史记录

package com.fh.Session.cart;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@WebServlet("/lastView")
public class LastServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        HttpSession session = request.getSession();
        List<Product> products = (List<Product>) getServletContext().getAttribute("products");
        LinkedList<String> footprint = (LinkedList<String>) session.getAttribute("lastView");
        if (footprint==null){
            response.getWriter().println("历史足迹为空!");
        }
        for (String id : footprint) {
            for (Product product : products) {
                if (id.equals(product.getId())) {
                    response.getWriter().println(product.getName());
                }
            }
        }
    }
}

思路:判断是否在历史足迹中—>有就删除---->判断是否已满---->满了就删除最久远的,因为我们是头插法,所以直接删除尾部元素---->将新元素添加到头部

session生命周期

创建:

对象创建是通过第一次调用request.getSession()来创建的

数据的创建:

​ 通过调用setAttribute来放入session域

销毁:

​ 对象的销毁是当应用卸载、服务器关闭

数据的销毁:

session对象的销毁不会导致数据的销毁

数据的销毁只和以下情况有关:

1.session有效期到达(默认情况下,tomcat默认配置是30min),30分钟这个session没有被访问,就会删除

2.主动调用session.invalidate()方法

调用removeAttribute()(该方法只是把session里面的某个键值对清空,不是清空整个session)

禁用cookie之后的策略

session底层依赖于cookie,如果cookie禁用之后,session可以采用URL重写的方式(主流的网站都要求打开cookie

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值