JavaEE精选-会话技术

本文涉及的产品
.cn 域名,1个 12个月
简介: JavaEE精选-会话技术

会话技术

使用的场景:在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

目录
相关文章
|
4月前
|
存储 安全 搜索推荐
【JavaWeb 秘籍】Cookie vs Session:揭秘 Web 会话管理的奥秘与实战指南!
【8月更文挑战第24天】本文以问答形式深入探讨了Web开发中关键的会话管理技术——Cookie与Session。首先解释了两者的基本概念及工作原理,随后对比分析了它们在存储位置、安全性及容量上的差异。接着,通过示例代码详细介绍了如何在JavaWeb环境中实现Cookie与Session的操作,包括创建与读取过程。最后,针对不同应用场景提供了选择使用Cookie或Session的指导建议,并提出了保障二者安全性的措施。阅读本文可帮助开发者更好地理解并应用这两种技术。
81 1
|
4月前
|
开发者 前端开发 Apache
Apache Wicket Ajax揭秘:轻松几步,让你的Web应用告别“呆板”,焕发新生!
【8月更文挑战第31天】随着互联网技术的发展,Web应用的交互性成为评价网站成功的关键指标。Apache Wicket作为一款卓越的Java Web框架,不仅具备强大的组件化开发能力,还内置了对Ajax技术的支持,使开发者能轻松提升Web应用的交互体验。通过简单的代码示例展示了如何在不刷新页面的情况下异步更新页面元素,极大提升了用户体验。Wicket提供了多种Ajax组件和行为,如AjaxFallbackLink、AjaxButton等,满足不同场景需求,并支持自定义Ajax行为,帮助开发者实现复杂交互效果。合理运用Wicket的Ajax功能,可显著增强网站竞争力。
52 0
|
4月前
|
监控 前端开发 Java
揭秘Web开发神器:Servlet、过滤器、拦截器、监听器如何联手打造无敌博客系统,让你的用户欲罢不能!
【8月更文挑战第24天】在Java Web开发中,Servlet、过滤器(Filter)、拦截器(Interceptor,特指Spring MVC中的)及监听器(Listener)协同工作,实现复杂应用逻辑。以博客系统为例,Servlet处理文章详情请求,过滤器(如LoginFilter)检查登录状态并重定向,Spring MVC拦截器(如LoggingInterceptor)提供细粒度控制(如日志记录),监听器(如SessionListener)监控会话生命周期事件。这些组件共同构建出高效、有序的Web应用程序。
42 0
|
7月前
|
域名解析 缓存 网络协议
JavaEE精选-Web组件
JavaEE精选-Web组件
46 1
|
7月前
|
SQL 前端开发 Java
JavaEE精选-项目一
JavaEE精选-项目一
53 0
|
存储
JavaWeb 速通Cookie
JavaWeb——会话技术 Cookie 内容分享。
63 0
|
应用服务中间件 容器
JavaWeb 速通Session
JavaWeb——会话技术 Session 内容分享。
65 0
|
存储 设计模式 JavaScript
掌握JavaWeb开发的必备技能:Servlet、JSP、Cookie、Session、EL、JSTL详解 ~~~~B站老杜--Servlet-JSP-课堂笔记(三)
当某个特殊的事件发生(特殊的事件发生其实就是某个时机到了。)之后,被web服务器自动调用。 思考一个业务场景
85 0
|
缓存 前端开发 Java
掌握JavaWeb开发的必备技能:Servlet、JSP、Cookie、Session、EL、JSTL详解 ~~~~B站老杜--Servlet-JSP-课堂笔记(二)
我们只需要service方法,其他方法大部分情况下是不需要使用的。代码很丑陋。 适配器设计模式Adapter
71 0
|
前端开发 Java 应用服务中间件
掌握JavaWeb开发的必备技能:Servlet、JSP、Cookie、Session、EL、JSTL详解 ~~~~B站老杜--Servlet-JSP-课堂笔记(一)
对于一个动态的web应用来说,一个请求和响应的过程有多少个角色参与,角色和角色之间有多少个协议
86 0