JavaWeb笔记(7):Cookie/Session

x33g5p2x  于2022-02-07 转载在 Java  
字(14.3k)|赞(0)|评价(0)|浏览(326)

1、什么是Cookie?

2、如何创建Cookie

3、服务器如何获取Cookie

4、Cookie值的修改

5、浏览器查看 Cookie

6、Cookie生命控制  

​7、Cookie有效路径Path的设置

​8、免输入用户名登录

9、Session会话

10、如何创建 Session 和获取(id 号,是否为新)​

11、Session 域数据的存取

12、Session 生命周期控制

13、浏览器和 Session 之间关联的技术内幕

14、谷歌 kaptcha 图片验证码的使用

1、什么是Cookie?

  • 1、Cookie 是饼干的意思。
  • 2、Cookie是服务器和客户端保存键值对的一种技术。
  • 3、客户端有了Cookie后,每次请求都发送给服务器。
  • 4、每个Cookie的大小不超过4knnwlc

2、如何创建Cookie

服务端创建,传给客户端,保存在客户端。

先写一个cookie.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <base href="http://localhost:8080/SpringMVC">

    <style type="text/css">
        ul li{
            list-style: none;
        }
    </style>
</head>
<body>

<iframe name="target" width="500" height="500" style="float: left"></iframe>
<div style="float:left;">
    <ul>
        <li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li>
        <li><a href="" target="target">Cookie的获取</a></li>
        <li><a href="" target="target">Cookie值的修改</a></li>
        <li>Cookie的存活周期</li>
        <li>
            <ul>
                <li><a href="" target="target">Cookie的默认存活时间(会话)</a></li>
                <li><a href="" target="target">Cookie立即删除</a></li>
                <li><a href="" target="target">Cookie存活3600s</a></li>
            </ul>
        <li><a href="" target="target">Cookie的路径设置</a></li>
        <li><a href="" target="target">Cookie的用户免登录练习</a></li>
     </ul>
</div>
</body>
</html>

页面效果:


  我们先来解决cookie的创建,要建立一个servlet来实现它的请求。

BaseServlet:

public abstract class BaseServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决post请求中文乱码问题
        // 一定要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");
        // 解决响应中文乱码问题
        resp.setContentType("text/html; charset=UTF-8");

        String action = req.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            System.out.println(method);
            // 调用目标业务 方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

CookieServlet

public class CookieServlet extends BaseServlet {

    protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1 创建 Cookie 对象
        Cookie cookie = new Cookie("key", "value");
        //2 通知客户端保存 Cookie
        resp.addCookie(cookie);
        resp.getWriter().write("Cookie  创建成功");
    }
}

** 运行:**

现在我们只发现了两个初始的Cookie值,当我们点击创建Cookie的按钮时:

我们发现多出来了一个我们建立的Cookie:


我们不是一次只能创建一个Cookie,我们可以一次创建多个Cookie

** 我们再点击一次创建cookie的按钮:

**

3、服务器如何获取Cookie

服务器获取客户端的所有Cookie:
req.getCookie():cookie

public class CookieServlet extends BaseServlet {

    protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1 创建 Cookie 对象
        Cookie cookie = new Cookie("key", "value");
        //2 通知客户端保存 Cookie
        resp.addCookie(cookie);
        resp.getWriter().write("Cookie  创建成功");
    }

    protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Cookie[] cookies = req.getCookies();
        for(Cookie cookie : cookies){
            // getName 方法返回 Cookie 的 key (名)
            // getValue 方法返回 Cookie 的 value 值
            resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br/>");
        }
    }

}

点击Cookie获取按钮:

 

**服务端获取指定key的cookie **

但是我们发现Cookie没法像 map一样通过获取key来直接输出对应的cookie,那如果我们想只输出特定的cookie值应该怎么做呢?

public class CookieServlet extends BaseServlet {

  
    protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Cookie[] cookies = req.getCookies();
        for(Cookie cookie : cookies){
            // getName 方法返回 Cookie 的 key (名)
            // getValue 方法返回 Cookie 的 value 值
            resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "] <br/>");
        }

        Cookie cookie = CookieUtils.findCookie("key1", cookies);
        if(cookie != null){
            resp.getWriter().write(" 找到了需要的 Cookie");
        }
    }

}
public class CookieUtils {

    /**
     * 查找指定名称的cookie
     */
    public static Cookie findCookie(String name, Cookie[] cookies){
        if(name == null || cookies == null || cookies.length == 0 ){
            return null;
        }
        for (Cookie cookie: cookies){
            if(cookie.getName().equals(name)){
                return cookie;
            }
        }
        return null;
    }

}

这种**循环查找特定cookie的方法以后会经常能够用上。**​     

4、Cookie值的修改

方案一:

  • 1、先创建一个要修改的同名的Cookie对象
  • 2、在构造器,同时赋于新的Cookie值
  • 3、通用response.addCookie(Cookie)
<li><a href="cookieServlet?action=updateCookie" target="target">Cookie值的修改</a></li>
public class CookieServlet extends BaseServlet {

    protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //先创建一个要修改的同名(指的就是 key)的 Cookie 对象
        //在构造器,同时赋于新的 Cookie 值。
        Cookie cookie = new Cookie("key" , "newValue");
        // 调用 response.addCookie( Cookie ); 通知 客户端 保存修改
        resp.addCookie(cookie);
        resp.getWriter().write("key的cookie已经修改好");
    }

}

点击修改Cookie的按钮:


** 方案二:**

  • 1、先查找到需要修改的Cookie对象
  • 2、调用setValue()方法赋予新的Cookie值
  • 3、调用response.addCookie()通知客户端保存修改
public class CookieServlet extends BaseServlet {

    protected void updateCookie1(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //1 、先查找到需要修改的 Cookie 对象
        Cookie cookie = CookieUtils.findCookie("key1", req.getCookies());
        if (cookie != null) {
            // 2 、调用 setValue() 方法赋于新的 Cookie 值。
            cookie.setValue("newValue2");
            // 3 、调用 response.addCookie() 通知客户端保存修改
            resp.addCookie(cookie);
        }
        
    }

}

谷歌和火狐浏览器怎么查看Cookie
谷歌:

火狐:

6、Cookie生命控制  

Cookie的生命控制指的是如何管理Cookie什么时候被销毁(删除)
setMaxAge()

  • 正数:表示在指定的秒数后过期
  • 负数:表示浏览器一关,Cookie就会被删除(默认值是-1)
  • 零:表示马上删除Cookie
    setMaxAge(-1):
protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Cookie cookie = new Cookie("defaultLife", "defaultLife");
        cookie.setMaxAge(-1);
        resp.addCookie(cookie);
        resp.getWriter().write("浏览器关闭,cookie删除");
    }

点击默认存活按钮:

出现了defalutLife的Cookie,当我们关闭浏览器时,再重新打开浏览器:

defalutLife被删除了。
** setMaxAge(0):**

点击立即删除, 我们发现Name为key4的Cookie直接就被删除了:

点击立即删除:

** 还可以设置Cookie的存活时间:**
** setMaxAge(60*60)**


7、Cookie有效路径Path的设置

Cookie的path属性可以有效的过滤哪些Cookie可以发送给服务器,哪些不发。

path属性是通过请求的地址来进行有效的过滤。

  •  CookieA        path=/工程路径
  • CookieB        path=/工程路径/abc

请求地址如下:http://ip:port/工程路径/a.html

  • CookieA 发送
  • CookieB  不发送

http://ip:port/工程路径/abc/a.html

  • CookieA 发送
  • CookieB  发送


8、免输入用户名登录

原理:

  • login.jsp 页面
<form action="http://localhost:8080/ServletTest/loginServlet" method="get">
    用户名:<input type="text" name="username" value="${cookie.username}"> <br>
    密码:<input type="password" name="password"> <br>
    <input type="submit" value=" 登录">
</form>
  • Servlet 程序中的代码:
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决中文乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if ("Tommey周".equals(username) && "123456".equals(password)) {
            Cookie cookie = new Cookie("cookie", username);
            cookie.setMaxAge(60 * 60 * 24 * 7);// 当前 Cookie 一周内有效
            resp.addCookie(cookie);
            resp.getWriter().write("登录成功");
        } else {
            resp.getWriter().write("登录失败");
        }
    }

9、Session会话

  • ①、Session 就一个接口(HttpSession)
  • ②、Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术
  • ③、每个客户端都有自己的一个 Session 会话
  • ④、Session 会话中,我们经常用来保存用户登录之后的信息

10、如何创建 Session 和获取(id 号,是否为新)

创建和获取 Session
request.getSession()

  • 第一次调用是:创建 Session 会话
  • 之后调用都是:获取前面创建好的 Session 会话对象。

isNew():判断到底是不是刚创建出来的(新的),true 表示刚创建,false 表示获取之前创建

每个会话都有一个身份证号。也就是 ID 值。而且这个 ID 是唯一的。getId() 得到 Session 的会话 id 值。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

    <title>Cookie</title>

    <base href="http://localhost:8080/WebServlet_war_exploded/">
    <style type="text/css">
        ul li{
            list-style: none;
        }
    </style>
</head>
<body>

<iframe name="target" width="500" height="500" style="float: left"></iframe>
<div style="float:left;">
    <ul>
        <li><a href="sessionServlet?action=createOrGetSession">Session的创建和获取</a></li>
        <li><a href="sessionServlet?action=updateCookie" target="target">Session值的修改</a></li>
        <li>Session的存活周期</li>
        <li>
            <ul>
                <li><a href="sessionServlet?action=defaultLife" target="target">Session的默认存活时间(会话)</a></li>
                <li><a href="sessionServlet?action=deleteNow" target="target">Session立即删除</a></li>
                <li><a href="sessionServlet?action=lift3600" target="target">Session存活3600s</a></li>
            </ul>
        <li><a href="sessionServlet?action=testPath" target="target">Session的路径设置</a></li>
     </ul>
</div>
</body>
</html>
@WebServlet("/sessionServlet")
public class SessoniServlet extends BaseServlet {

    public void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建和获取session会话
        HttpSession session = req.getSession();
        //判断session是否是新创建
        boolean aNew = session.isNew();
        //获取session唯一标识
        String id = session.getId();
        resp.getWriter().write("session是否是新创建: " + id);
        resp.getWriter().write("session唯一标识:" + aNew);
    }
}

11、Session 域数据的存取

  • 示例代码如下:
  • Servlet类
public class SessionServlet extends BaseServlet {

    /**
     * 往 Session 中保存数据
     */
    protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getSession().setAttribute("key1", "value1");
        resp.getWriter().write(" 已经往 Session  中保存了数据");
    }
    /**
     * 获取 Session 域中的数据
     */
    protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object attribute = req.getSession().getAttribute("key1");
        resp.getWriter().write("从 从 Session  中获取出 key1  的数据是:" + attribute);
    }
}
  • html页面
<base href="http://localhost:8080/WebServlet_war_exploded/">
</head>
<body>
<body>
<a href="sessionServlet?action=setAttribute">保存Session</a>
<a href="sessionServlet?action=getAttribute">获取Session</a>
</body>

12、Session 生命周期控制

设置 Session 的超时时间(以秒为单位),超过指定的时长,Session就会被销毁:
public void setMaxInactiveInterval(int interval)

  • 值为正数的时候,设定 Session 的超时时长。
  • 负数表示永不超时(极少使用)

获取 Session 的超时时间:
public int getMaxInactiveInterval()

让当前 Session 会话马上超时无效:

public void invalidate()

Session 默认的超时时间长为 30 分钟。

因为在Tomcat服务器的配置文件web.xml中默认有以下的配置,它就表示配置了当前Tomcat服务器下所有的Session。超时配置默认时长为:30 分钟。

<session-config>
<session-timeout>30</session-timeout>
</session-config>
  • 如果希望 web 工程,默认的 Session 的超时时长为其他时长。你可以在你自己的 web.xml 配置文件中做以上相同的配置。就可以修改你的 web 工程所有 Seession 的默认超时时长。
  • web.xml:
<!-- 表示当前 web 工程。创建出来 的所有 Session 默认是 20 分钟 超时时长 -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
  • 如果你想只修改个别 Session 的超时时长。就可以使用上面的 API。setMaxInactiveInterval(int interval)来进行单独的设置。
    session.setMaxInactiveInterval(int interval)//单独设置超时时长

Session 超时的概念介绍:

所以当在浏览器一直点击时,session的timeout一值从3开始变化。

只有当点击一下,等3点后session就会timeout=0即超时。

protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 先获取 Session 对象
    HttpSession session = req.getSession();
    // 设置当前 Session3 秒后超时
    session.setMaxInactiveInterval(3);
    resp.getWriter().write(session.getId()+" 当前 Session  已经设置为 3  秒后超时");
}
  • Session 马上被超时示例:
protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 先获取 Session 对象
    HttpSession session = req.getSession();
    // 让 Session 会话马上超时
    session.invalidate();
    resp.getWriter().write(session.getId()+"Session  已经设置为超时(无效)");
}

13、浏览器和 Session 之间关联的技术内幕

  • Session 技术,底层其实是基于 Cookie 技术来实现的。

每次请求,将session以cookie的形式发给服务器:

14、谷歌 kaptcha 图片验证码的使用

  • 谷歌验证码 kaptcha 使用步骤如下:

1、导入谷歌验证码的 jar 包 kaptcha-2.3.2.jar

2、在 web.xml 中去配置用于生成验证码的 Servlet 程序

<servlet>
    <servlet-name>CheckServlet</servlet-name>
    <servlet-class>com.CheckServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>CheckServlet</servlet-name>
    <url-pattern>/checkServlet</url-pattern>
</servlet-mapping>

3、在表单中使用 img 标签去显示验证码图片并使用它

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <base href="http://localhost:8080/ServletTest/" />
</head>
<script type="text/javascript" src="jquery-1.7.2.js"></script>
<script type="text/javascript">
    $(function () {
        // 给验证码的图片,绑定单击事件
        $("#code_img").click(function () {
            // 在事件响应的 function 函数中有一个 this 对象。这个 this 对象,是当前正在响应事件的 dom 对象
            // src 属性表示验证码 img 标签的 图片路径。它可读,可写
            // alert(this.src);
            this.src = "kaptcha.jpg?d=" + new Date();
        });
    })
</script>
<body>
<form action="checkServlet" method="get">
    用户名:<input type="text" name="username" > <br>
    验证码:<input type="text" style="width: 80px;" name="code">
    <img src="kaptcha.jpg" id="code_img" style="width: 100px; height: 28px;"> <br>
    <input type="submit" value=" 登录">
</form>
</body>
</html>

4、在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。

public class CheckServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取 Session 中的验证码
        String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
        // 删除 Session 中的验证码
        req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        String code = req.getParameter("code");
        // 获取用户名
        String username = req.getParameter("username");
        if (token != null && token.equalsIgnoreCase(code)) {
            System.out.println(" 保存到数据库:" + username);
            resp.sendRedirect(req.getContextPath() + "/ok.jsp");
        } else {
            System.out.println(" 请不要重复提交表单");
        }
    }
}

相关文章