javaweb之会话技术cookie&session

一,会话技术

1,会话:一次会话中包含多次请求和响应。一次会话,即浏览器第一次给服务器资源发送请求,会话建立,直到一方断开为止。
2,功能:在一次会话的范围内多次请求间共享数据。
3,方式
客户端会话技术:cookie;
服务端会话技术:session.

二,Cookie技术

1,概念:客户端会话技术,将数据保存到客户端。
2,入门
(1),创建cookie对象,绑定数据;

new Cookie(String name, String value) 

(2),发送cookie对象;

response.addCookie(Cookie cookie) 

(3),获取cookie对象,拿到数据。

Cookie[]  request.getCookies() 
@WebServlet("/cookieDemo1")
public class CookieDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie cookie = new Cookie("msg", "hello");
        Cookie cookie2 = new Cookie("name", "张三");
        
        //20s后清除该cookie消息
        //cookie.setMaxAge(300);

        //删除浏览器中该cookie消息
        //cookie.setMaxAge(0);

        response.addCookie(cookie);
        response.addCookie(cookie2);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

@WebServlet("/cookieDemo2")
public class CookieDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie[] cs = request.getCookies();
        for (Cookie c : cs) {
            String name = c.getName();
            String value = c.getValue();
            System.out.println(name+":"+value);
        }
        /*
        msg:hello
        name:张三
        Pycharm-360fce62:285bf332-1657-478a-a3bf-ccb521740439
        Idea-a77fa8ec:bf922fbc-6589-4632-9a1c-c2788ffca99f
         */
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

3,实现原理:基于响应头set-cookie和请求头cookie实现。
在这里插入图片描述
4,cookie技术细节

(1) 一次可不可以发送多个cookie?
可以,创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可。

(2) cookie在浏览器中保存多长时间?

  1. 默认情况下,当浏览器关闭后,Cookie数据被销毁;
  2. 持久化存储:setMaxAge(int seconds),参数意义如下:
    (a),正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效
    (b),负数:默认值
    (c),零:删除cookie信息

(3),cookie能不能存中文?
在tomcat 8 之前 cookie中不能直接存储中文数据,需要将中文数据转码—一般采用URL编码(%E3);
在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析.

(4), cookie共享问题?
1. 假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下cookie不能共享, setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录,即如果要共享,则可以将path设置为"/"

2.不同的tomcat服务器间cookie共享问题?
setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享;
setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享。

5,cookie特点及作用
特点:
(1),cookie在客户端浏览器存储数据;
(2),浏览器对于单个cookie大小有限制(4kb),以及同一个域名下总cookie数量也有限制(20个)。
作用:
(1),cookie一般用于存储少量不太敏感的数据;
(2),在不登录的情况下,完成服务器对客户端的识别。

6,cookie应用案例:记住上一次访问时间
需求:

  1. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
  2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
@WebServlet("/cookieVisit")
public class CookieVisit extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie[] cookies = request.getCookies();
        response.setContentType("text/html;charset=utf-8");
        boolean flag = false;

        if (cookies != null) {
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                if ("time".equals(name)) {
                    flag = true;
                    String timeVal = cookie.getValue();
                    timeVal = URLDecoder.decode(timeVal, "utf-8");

                    Date day = new Date();
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String time = df.format(day);

                    //cookie值包含特殊字符,需要进行URL编解码
                    time = URLEncoder.encode(time, "utf-8");

                    cookie.setValue(time);
                    response.addCookie(cookie);

                    response.getWriter().write("欢迎回来!您上次登录的时间为: " + timeVal);
                    break;
                }
            }
        }
        if (flag == false || cookies == null) {
            Date day = new Date();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = df.format(day);
            time = URLEncoder.encode(time, "utf-8");
            Cookie timeCookie = new Cookie("time", time);
            response.addCookie(timeCookie);

            response.getWriter().write("欢迎您首次登陆!");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
三,JSP脚本

1,概念:Java Server Pages,java服务端页面,是一个特殊的页面,既可以定义HTML标签,也可以定义java代码,用于简化书写。
2,原理:本质上是一个Servlet。
在这里插入图片描述
3,JSP脚本

  1. <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
  2. <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
  3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <h1>index页面</h1>

  <%
    System.out.println("hello,jsp");
    int i = 1;
  %>

  <%!
    int i = 2;
  %>

  <%=
    i
  %>

  <%
    out.print("out输出");
  %>

  <%
    response.getWriter().write("response输出");
  %>

  <%--response输出--%>
  <%--index页面--%>
  <%--1 out输出--%>
  </body>
</html>

4,jsp内置对象
概念:在jsp页面中不需要获取和创建,可以直接使用的对象。如以下三个:
(1)request
(2)response
(3)out:字符输出流对象。可以将数据输出到页面上,和response.getWriter()类似。

response.getWriter()和out.write()的区别:
在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据,所以response.getWriter()数据输出永远在out.write()之前。

5,通过jsp改造Cookie案例

<%@ page import="java.net.URLDecoder" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.net.URLEncoder" %><%--
  Created by IntelliJ IDEA.
  User: ASUS
  Date: 2020/7/5
  Time: 12:23
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    Cookie[] cookies = request.getCookies();
    response.setContentType("text/html;charset=utf-8");
    boolean flag = false;

    if (cookies != null) {
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            if ("time".equals(name)) {
                flag = true;
                String timeVal = cookie.getValue();
                timeVal = URLDecoder.decode(timeVal, "utf-8");

                Date day = new Date();
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String time = df.format(day);

                //cookie值包含特殊字符,需要进行URL编解码
                time = URLEncoder.encode(time, "utf-8");

                cookie.setValue(time);
                response.addCookie(cookie);

%>
<h1>"欢迎回来!您上次登录的时间为: <%= timeVal%>"</h1>
<%
                break;
            }
        }
    }
    if (flag == false || cookies == null) {
        Date day = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = df.format(day);
        time = URLEncoder.encode(time, "utf-8");
        Cookie timeCookie = new Cookie("time", time);
        response.addCookie(timeCookie);

%>
<h1>"欢迎您首次登陆!"</h1>
<%
    }
%>
<h3>登录表单1</h3>
<form action="">
    账号:<input type="text">
    密码:<input type="password">
    <input type="submit" value="登录">
</form>

</body>
</html>
四,session技术

1,概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象HttpSession中。
2,入门:
(1)获取session对象:request.getSession();
(2)使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
3,原理:session的实现是依赖于cookie的。
在这里插入图片描述

4,session技术细节

(1)当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
默认情况下不是。如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。

@WebServlet("/sessionDemo3")
public class SessionDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        System.out.println(session);

        //设置cookie值,关闭浏览器后访问的session对象是同一个
        Cookie c = new Cookie("JSESSIONID", session.getId());
        c.setMaxAge(60*60);
        response.addCookie(c);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

(2)客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作
(a)session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上;
(b) session的活化: 在服务器启动后,将session文件转化为内存中的session对象即可。

(3)session什么时候被销毁?
(a) 服务器关闭
(b) session对象调用invalidate() 。
(c)session默认失效时间 30分钟,可选择性配置修改

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

5,session的特点
(a)session用于存储一次会话的多次请求的数据,存在服务器端;
(b) session可以存储任意类型,任意大小的数据。

6, session与Cookie的区别
(a)session存储数据在服务器端,Cookie在客户端;
(b)session没有数据大小限制,Cookie有;
(c) session数据安全,Cookie相对于不安全。

五,验证码案例

案例需求:
1. 访问带有验证码的登录页面login.jsp
2. 用户输入用户名,密码以及验证码。
* 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
* 如果验证码输入有误,跳转登录页面,提示:验证码错误
* 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>

    <script>
        window.onload = function () {
            document.getElementById("checkcode").onclick = function () {
                this.src = "/day5/checkCodeDemo1?" + new Date().getTime();
            }
        }
    </script>

    <style>
        .error{
            color: red;
        }
    </style>
</head>
<body>
    <table>
        <form action="/day5/login" method="post">
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td class="error"><%=request.getAttribute("up_error") == null ? "" : request.getAttribute("up_error")%></td>
            </tr>
            <tr>
                <td>验证码:</td>
                <td>
                    <input type="text" name="checkcode">
                </td>
            </tr>
            <tr>
                <td class="error"><%=request.getAttribute("ccode_error") == null ? "" : request.getAttribute("ccode_error")%></td>
            </tr>
            <tr>
                <td colspan=20>
                    <img  id="checkcode" src="/day5/checkCodeDemo1" alt="">
                </td>
            </tr>
            <tr>
                <td colspan=20>
                    <input  type="submit" value="登录">
                </td>
            </tr>
        </form>
    </table>
</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3><%=request.getSession().getAttribute("username")%>登录成功</h3>
</body>
</html>
@WebServlet("/login")
public class login extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String checkcode = request.getParameter("checkcode");

        String session_code = (String)request.getSession().getAttribute("session_code");

        if (session_code != null && session_code.equalsIgnoreCase(checkcode)){
            //验证码匹配
            if ("张三".equals(username) && "123".equals(password)){
                //用户名和密码正确
                request.getSession().setAttribute("username",username);
                response.sendRedirect(request.getContextPath()+"/success.jsp");

            }else{
                //用户名和密码错误
                request.setAttribute("up_error","用户名或密码错误!请重试");
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }
        }else{
            //验证码错误
            request.setAttribute("ccode_error","验证码错误!请重试");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}
@WebServlet("/checkCodeDemo1")
public class CheckCodeDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        int width = 160;
        int height = 80;
        //创建图片对象
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        //美化图片
        Graphics gh = image.getGraphics();
        gh.setColor(Color.PINK);
        gh.fillRect(0,0,width,height);

        gh.setColor(Color.BLUE);
        gh.drawRect(0,0,width-1,height-1);

        Random rd = new Random();
        String s = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";

        StringBuilder session_ckcode = new StringBuilder();
        for (int i = 1; i <= 4; i++) {
            int index = rd.nextInt(s.length());
            char ch = s.charAt(index);
            session_ckcode.append(ch);
            gh.drawString(ch+"",width/5*i,height/2);
        }
        //将验证码存储到session当中
        String session_code = session_ckcode.toString();
        HttpSession session = request.getSession();
        session.setAttribute("session_code",session_code);

        gh.setColor(Color.GREEN);
        for (int i = 0; i < 10; i++) {
            int x1 = rd.nextInt(width);
            int x2 = rd.nextInt(width);
            int y1 = rd.nextInt(height);
            int y2 = rd.nextInt(height);
            gh.drawLine(x1,y1,x2,y2);

        }


        //将图片输出到页面展示
        ImageIO.write(image,"jpg",response.getOutputStream());

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        this.doPost(request,response);
    }
}

效果展示:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值