Session会话技术

Session对象

这里写目录标题

  • Session对象
    • 一.what?什么是Session技术
    • 二.How?Session技术怎么用
    • 三.Session的超时管理
    • 四.Session案例
    • 六.URL重写处理Cookie的禁用
    • 七.案例2:实现用户登录
    • 八.Cookie和Session的对比

首先客服浏览器向web服务器端,发送一个请求,web服务器端给客户浏览器应答,只要浏览器不关,就会不断的通信,就会有多个请求多个应答,一个请求一个应答一一对应。
Cookie技术解决的是多个请求和应答之间数据共享的问题。
其实多组请求和应答,不断的请求和应答就是一个会话过程,Cookie为什么能访问到上次购买的记录,是因为把上次Cookie的键值对放到请求头,这是浏览器自动进行的工作,这样请求1和请求2直接就可以达到共享数据

Session会话技术_第1张图片

就如上面的图,就是因为请求1的Cookie的键值对放到了请求2的请求头中,所以接算的时候才可以有请求1的购买记录
那什么是session技术呢?


一.what?什么是Session技术

打个很简单的比方,就比如我们去餐馆吃饭会购买那种会员卡,会员卡里面会存有钱,通过会员卡来消费就是Cookie技术,而我们如果没有带会员卡就只需要报出自己的手机号就可以了,这就是Session技术。

Session会话技术_第2张图片

第一次访问的时候还是请求,因为是第一次访问会创建一个Session,为了区分多个Session,每个Session有自己的一个id,Session会在服务器端存储下来,给用户浏览器端也会发一个set-Cookie键值对,但是不再是像上面那样存的是购买的信息,购买的信息已经在服务器端的Session里面存下来了他给客户浏览器端发送的应答其实是Session的id号。这个时候键值对的键就是Session的id,值就是id的值
客户端收到这个set-Cookie这个应答之后,会把这个Session的id给存下来,然后再次请求的时候会把这个Session的id放到请求头里
每次服务器收到这个Session的id的时候,他就会在服务器去找这个Session,然后通过API把上次的记录从Session取出来

其实我们不难发现,Session技术是依托于Cookie技术的。
因为Session技术要通过Cookie去保存Session的id。这个id不正是类似于餐馆消费可以不用带卡而是用电话号码吗?餐馆就会把这个电话号码记录下来,餐馆就可以通过这个电话号码来查到你的消费。一样的道理。

Session会话技术_第3张图片

Cookie技术是在客户端实现的,而Session技术是在服务器端实现的

Session会话技术_第4张图片

会话是占用服务器资源的,会话也有自己的生命周期



二.How?Session技术怎么用

Session是与每个请求消息紧密相关的,为此HttpServlet定义了用于获取Session对象的getSession()方法,还有两种重载形式,具体如下:

  • public HttpSession getSession (boolean create)
  • public HttpSession getSession ( )
    上面两个重载方法的区别是:
    当Session对象存在的时候,第一个方法和第二个方法都是返回的Session对象,而如果当Session对象不存在的时候,带参数的getSession( )方法,如果参数是true,就会自己创建一个HttpSession对象然后返回这个新的HttpSession对象,false的话就会返回null,而不带参数的getSession( )方法总是创建新的HttpSession对象并且返回

我们获取了Session对象就可以调用Session对象的相关的方法

Session会话技术_第5张图片



三.Session的超时管理

之前说过,会话是占用服务器资源的,所以无法一直存在于服务器。但是web服务器也无法判断浏览器是否还会访问,也无法检测客户端浏览器是否关闭,所以当会话越来越多的时候,服务器的内存终将会被耗尽
为了解决这个问题,web服务器采用了"超时限制"来判断客户端是否还在继续访问
在一定的时间内,如果某个客户端一直没有请求访问,服务器就会认为该客户的会话已经结束,并将对应的HttpSession对象变成垃圾对象,等待垃圾收集器从内存中彻底的清除,反之,如果浏览器超时之后再进行访问,那么服务器会创建一个新的Session对象,并且会为这个Session对象配一个新的id。

在web.xml配置里面可以改超时的时间限制

 <session-config>
 <session-timeout>30session-timeout>
 session-config>


四.Session案例

通过Session来模拟实现一个网上购书,和购物车清单显示。

流程图如下:

Session会话技术_第6张图片

代码实现

//1.首先创建一个图书的实体类

public class Book {
 private static final long serialVersionUID = 1L;    //serialVersionUID版本号。
 private String name;
 private String id;

 public Book() {
 }

 public Book(String id, String name) {
     this.name = name;
     this.id = id;
 }

 public String getName() {
     return name;
 }

 public void setName(String name) {
     this.name = name;
 }

 public String getId() {
     return id;
 }

 public void setId(String id) {
     this.id = id;
 }
}

//新建一个保存图书的数据库的BookDB类
//模拟数据库的类,工具类

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

public class BookDB {
 private static Map<String,Book> books = new LinkedHashMap<>();

 //静态代码块,静态总是优先于非静态,而且静态代码块只执行唯一一次
 static {
     books.put("1",new Book("1","javaweb开发"));
     books.put("2",new Book("2","jdbc开发"));
     books.put("3",new Book("3","java基础"));
     books.put("4",new Book("4","struts开发"));
     books.put("5",new Book("5","spring开发"));
 }

 //获取所有图书
 public static Collection<Book> getAll() {
     return books.values();
 }

 //根据指定的id获取图书
 public static Book getBook(String id) {
     return books.get(id);
 }

}
//ListBookServlet用来显示商城中所有的图书,
//通过单击购买链接就可以加入购物车

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.io.PrintWriter;
import java.util.Collection;

@WebServlet(name = "ListBookServlet",urlPatterns = "/ListBookServlet")
public class ListBookServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 @Override
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

     //处理中文乱码问题
     response.setContentType("text/html;charset=utf-8");
     PrintWriter out = response.getWriter();
     Collection<Book> books = BookDB.getAll();
     out.write("本站的图书有: 
"
); //通过增强for循环来遍历Collection集合 //格式: for(集合/数组中的数据类型 变量名 : 集合名/数组名){ } for (Book book : books) { //通过GET方式给每本书加上购物车的URL String url = "PurchaseServlet?id=" + book.getId(); out.write(book.getName() + "点击购买
"
); } } }

遍历之后实现的链接是这样的

本站的图书有: <br> javaweb开发<a href='PurchaseServlet?id=1'>点击购买a><br>jdbc开发<a href='PurchaseServlet?id=2'>点击购买a><br>java基础<a href='PurchaseServlet?id=3'>点击购买a><br>struts开发<a href='PurchaseServlet?id=4'>点击购买a><br>spring开发<a href='PurchaseServlet?id=5'>点击购买a><br>
/*
4.新建一个购买的Servlet
(1).将用户购买的书籍信息保存在Session中
(2).让用户购买书籍之后,将页面重定向到用户已经购买的图书列表
*/
@WebServlet(name = "PurchaseServlet",urlPatterns = "/PurchaseServlet")
public class PurchaseServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获得用户购买的商品
        String id = request.getParameter("id");
        //如果用户一上来直接访问PurchaseServlet那么id就是null
        if (null == id) {
            //如果id为null,那么就重定向到ListBookServlet
            String url = "ListBookServlet";
            response.sendRedirect(url);
            return;
        }
        Book book = BookDB.getBook(id);
        //创建或者获得用户的Session,采用无参的getSession如果没有总是会新创建Session
        HttpSession session = request.getSession();
        //从Session对象中获得用户的购物车
        List<Book> cart = (List) session.getAttribute("cart");
        if (null == cart) {
            //首次购买为用户创建一个cart
            cart = new ArrayList<Book>();   //采用多态写法
            //将购物车存入Session对象
            session.setAttribute("cart",cart);
        }
        //将商品放入购物车
        cart.add(book);
        //创建Cookie要存放Session的id
        Cookie cookie = new Cookie("JSESSIONID",session.getId());
        //设置Session的超时限制
        cookie.setMaxAge(60 * 30);
        response.addCookie(cookie);
        //重定向到购物车页面
        String url = "CartServlet";
        response.sendRedirect(url);
    }
}

/*
5.创建一个购物车CartServlet
 */

@WebServlet(name = "CartServlet",urlPatterns = "/CartServlet")
public class CartServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        List<Book> cart = null;
        //变量purFlag来标记用户是否买过商品
        boolean purFlag = true;
        //获取用户的Session
        HttpSession session = request.getSession();
        //如果Session为null则purFlag为false
        if (null == session) {
            purFlag = false;
        }else {
            //获取用户的购物车
            cart = (List)session.getAttribute("cart");
            //如果购物车为空,purFlag为false
            if (null == cart) {
                purFlag = false;
            }
        }
        //如果purFlag为false,表示用户没有买书,重定向到ListBookServlet
        if (!purFlag) {
            out.write("对不起,您还没有购买任何商品! 
"
); }else { //否则显示用户购买图书的信息 out.write("您购买的图书有:
"
); double price = 0; for (Book book : cart) { out.write(book.getName() + "
"
); } } } }

运行结果:

Session会话技术_第7张图片

Session会话技术_第8张图片

接下来测试一下超时限制,按理说如果Cookie正常的话,我们设置的在30分钟之内访问购物车,购买的书籍应该还是存在的
具体可参考:
https://blog.csdn.net/mdong9/article/details/105731120



六.URL重写处理Cookie的禁用

Session会话技术_第9张图片

当浏览器不支持Cookie或者关闭了Cookie 功能时,在会话过程中,如果想 让Web服务器可以保存用户的信息,必须对所有可能被客户端访问的请求路径进 行URL重写。在HttpServletResponse接口中,定义了两个用于完成URL重写的方法。

  • response.encodeRedirectURL(java.lang.String url) //用于对sendRedirect方法后的url地址进行重写。
  • response.encodeURL(java.lang.String url) //用于对表单action和超链接的url地址进行重写

URL重写,指的是将Session的会话标识号以参数 的形式附加在超链接的URL地址后面。对于Tomcat服务器来说,就是将JSessionID关键字作为参数名以及会话标识号的值作为参数值附加到URL地址 后面。



七.案例2:实现用户登录

Session会话技术_第10张图片

//网页首界面,判断是否有用户登录
@WebServlet(name = "indexServlet",urlPatterns = "/indexServlet")
public class indexServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request,response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        //创建或者获取保存用户信息的Session对象
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        if (null == user) {
            response.getWriter().print("您还没有登录,请登录");
        }else {
            response.getWriter().print("您已经登录,欢迎您" +user.getUsername() + "!");
            response.getWriter().print("退出");
            //创建Cookie存放Session的id
            Cookie cookie = new Cookie("JSESSIONID",session.getId());
            cookie.setMaxAge(60 * 30);
            response.addCookie(cookie);

        }
    }
}

因为是登录首先得有一个登录界面




    
    Insert title here



    
用户名:
密   码:

因为登录界面每个用户会有账号和密码,我们通过JavaBean实体类来封装用户的信息

//创建一个实体类用于封装前端传过来的用户的账号和密码
public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
//写一个用户登录的请求loginServlet
@WebServlet(name = "loginServlet",urlPatterns = "/loginServlet")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        PrintWriter pw = response.getWriter();
        //假设正确的用户名是yangtze,密码是123
        if (("yangtze").equals(username) && ("password").equals(password)) {
            User user = new User(username,password);
//            user.setUsername(username);
//            user.setPassword(password);
            request.getSession().setAttribute("user",user);
            response.sendRedirect("/indexServlet");
        }else {
            pw.write("用户名或密码错误,登录失败");
        }
    }
}

运行结果:

Session会话技术_第11张图片

Session会话技术_第12张图片



八.Cookie和Session的对比

Session会话技术_第13张图片

Session会话技术_第14张图片
Session会话技术_第15张图片
Session会话技术_第16张图片

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