cookie、session会话技术详细讲解与实例

1 HTTP协议

是一个无状态协议,所谓的无状态协议,是指上一次的请求和当前的请求之间没有任何的联系,无法共享数据。
会话技术概述
为了能够让多次请求之间可以共享数据,需要提供一门新的技术,这门技术就是会话技术
会话技术,就是为了实现某个功能,在浏览器和服务器建立连接之后,发送多次请求和响应可以共享数据,直到浏览器关闭,发送多次请求和多次响应都属于一次会话

2 会话技术—cookie

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 会话技术—session

概述
由于数据存储在浏览器安全性较差,所以考虑把数据存储在服务器中,提升数据的安全性。
将数据存储在服务器中这门技术—会话技术,就是session会话技术

3.1 session的原理

在浏览器访问服务器,如果有session对象创建的代码执行,则会在服务器其中创建一个session对象,这个session对象可以存储浏览器的数据,为多个浏览器创建多个单独的session对象,这些对象通过sessionID来进行区分。
session是一个基于Cookie工作的对象。本质是个cookie。浏览器中会保存sessionID,存储session对象的ID。

3.2session对象的创建

request.getSession();//如果当前服务器中没有当前浏览器的session对象,则会立刻创建一个session对象,如果有这个当前的session对象直接拿过来使用。
request.getSession(true);//如果当前服务器没有当前浏览器的session对象,则会立刻创建session对象,如果有这个当前的session对象直接拿过来使用。
request.getSession(false);//如果当前服务器中没有当前浏览器的session对象,则会返回一个null值,如果有这个当前session对象直接拿过来使用。

3.3session特点

服务器端技术,数据存储在服务器,安全性较高。擅长存储短时间的数据
功能一:作为域对象使用
域对象:如果一个对象身上有一个被看见的范围,在这个范围之内利用对象身上的map实现数据共享,对象就是域对象。
使用API
setAttribute(String name,Object obj);
getAttribute(String name);
removeAttribute(String name);
getAttributeNames();
生命周期
request.getSession();调用的时候,session对象创建,生命周期开始。
a.自杀:主动调用session.invalidate()方法释放对象。
b.意外身亡:在服务器中存有session对象,服务器意外关闭,session对象会被立刻销毁。如果服务器正常关闭,session对象里有数据,这个session就会被序列化到磁盘上—钝化 ,当服务器重启时会从之前磁盘已经序列化好的信息读取进来—活化
c.超时死亡:如果一个session兑现超过了30分钟未被使用,会被服务器自动销毁。这个超时的时间可以通过web.xml来设置
以上三种方式都会让session对象销毁,生命周期结束
作用范围:整个会话
作用范围:整个会话
作用范围:整个会话
代码实现:

package cn.tedu.session;
 
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;
 
@WebServlet("/SessionDemo1")
public class SessionDemo1 extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取session对象--域对象
        HttpSession session = request.getSession();
        //设置域属性---共享数据
        session.setAttribute("name","朴老师");
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doPost(request, response);
    }
}
在这里插入代码片
package cn.tedu.session;
 	
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;
 
@WebServlet("/SessionDemo2")
public class SessionDemo2 extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获取session对象
        HttpSession session = request.getSession();
        //获取域属性的值
        System.out.println("name:"+session.getAttribute("name"));
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doPost(request, response);
    }
}

实现简易的购物车来付账

修改index.jsp页面:

<%--
  Created by IntelliJ IDEA.
  User: tedu
  Date: 2020/12/3
  Time: 9:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>购物车</title>
  </head>
  <body>
  <%--添加商品信息--%>
  <a href="<%=request.getContextPath()%>/BuyServlet?prod=小米手机"
  >小米手机</a>
  <a href="<%=request.getContextPath()%>/BuyServlet?prod=拖鞋"
  >拖鞋</a>
  <a href="<%=request.getContextPath()%>/BuyServlet?prod=电脑"
  >电脑</a>
  <a href="<%=request.getContextPath()%>/BuyServlet?prod=大腰子"
  >大腰子</a>
  <a href="<%=request.getContextPath()%>/BuyServlet?prod=火龙果"
  >火龙果</a>
  <a href="<%=request.getContextPath()%>/PayServlet"
  >付款</a>
  </body>
</html>

新建BuyServlet:

package cn.tedu.session;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
 
@WebServlet("/BuyServlet")
public class BuyServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //1.乱码
        //request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //2.获取请求参数
        String prod = request.getParameter("prod");
        prod = new String(prod.getBytes("iso8859-1"),
                "utf-8");
        //3.创建session对象
        HttpSession session = request.getSession();
 
        //关闭浏览器也可以通过使用上一次会话的JSESSIONID来找到对应session对象
        //通过session对象来获取JSESSIONID
        Cookie cookie=new Cookie("JSESSIONID",session.getId());
        cookie.setMaxAge(60*60*24);
        cookie.setPath(request.getContextPath()+"/");
        response.addCookie(cookie);
 
        //4.设置域属性
        session.setAttribute("prod",prod);
        //5.在浏览器中显示商品已经加入购物车
        response.getWriter().write("恭喜,商品["+prod+"]已经添加到购物车");
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doPost(request, response);
    }
}

新建PayServlet

package cn.tedu.session;
 
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;
 
@WebServlet("/PayServlet")
public class PayServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
 
        response.setContentType("text/html;charset=utf-8");
        //1.创建session对象
        HttpSession session = request.getSession();
        //2.获取域属性
        Object prod = session.getAttribute("prod");
        //3.在浏览器显示已经为商品付款
        if(prod!=null){
    
    
            response.getWriter().write("已为商品["+prod+"]付款$10000");
        }else{
    
    
            response.getWriter().write("您尚未选择任何商品");
        }
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doPost(request, response);
    }
}

记住用户名

1.导入登录页面
在这里插入图片描述
2.修改_head.jsp页面

<divid="content">
<ahref="<%=request.getContextPath()%>/login.jsp">登录</a>&nbsp;&nbsp;|&nbsp;&nbsp;
<ahref="<%=request.getContextPath()%>/regist.jsp">注册</a>
</div>

3.修改login.jsp页面

<form action="<%=request.getContextPath()%>/LoginServlet"method="POST">
<table>
 
<%
/*获取后台(服务器发送cooki)*/
//把所有的cookie存放到数组中
Cookie[]cookies=request.getCookies();
//扩大cookie对象身上值的使用范围
Stringusername="";
//遍历数组,查找指定cookie
if(cookies!=null){
    
    
for(Cookiec:cookies){
    
    
//判断是否是指定的cookie(通过cookie名称来判断)
if("remname".equals(c.getName())){
    
    
//把cookie对象上的值赋值给username
username=c.getValue();
}
}
}
 
 
%>
 
<tr>
<%--回显cookie里存放用户名--%>
<td><inputtype="text"name="username"value="<%=username%>"/></td>

<inputtype="checkbox"name="remname"value="true"
<%--只有拿到了上一次勾选上记住用户名的cookie信息才能回显勾选--%>
<%="".equals(username)?"":"checked='checked'"%>
/>记住用户名

4.新建LoginServlet

package com.easymall.servlet;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //1.乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //2.获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String remname = request.getParameter("remname");
        //3.记住用户名
        //判断记住用户名是否打勾(已勾选)
        if("true".equals(remname)){
    
    
            //进了判断说明已勾选
            //设置cookie信息
            //创建cookie对象
            //remname作为cookie对象的名称,username作为cookie对象的值
            Cookie cookie=new Cookie("remname",username);
            //设置最大生命时长
            cookie.setMaxAge(60*60*24);
            //设置有效路径
            cookie.setPath(request.getContextPath()+"/");
            //发送cookie(响应到浏览器)
            response.addCookie(cookie);
        }
        //4.JDBC连接数据验证用户名和密码是否存在
        //5.登录成功,跳转到首页
        response.sendRedirect(request.getContextPath());
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doPost(request, response);
    }
}

5.cookie中文乱码的问题
在存储cookie时,通过URLEncoder.encode(String str,String enc));设置码表

Cookiecookie=newCookie("remname",URLEncoder.encode(username,"utf-8"));

在获取cookie时,通过URLDecoder.decode(String str,String enc);

username=URLDecoder.decode(c.getValue(),"utf-8");

登录功能实现

保存用户的登录状态,将用户名存放到某个域(域对象)中在需要的位置取出即可,认为是登录状态
request 范围太小
servletContext 范围太大
session 范围适中
修改LoginServlet

//4.JDBC连接数据验证用户名和密码是否存在
Connectionconn=null;
PreparedStatementps=null;
ResultSetrs=null;
try{
    
    
conn=JDBCUtiles.getConnection();
ps=conn.prepareStatement
("select*fromuserwhereusername=?andpassword=?");
ps.setString(1,username);
ps.setString(2,password);
rs=ps.executeQuery();
if(rs.next()){
    
    
//进了判断说明用户名和密码匹配
//保留用户的登录状态
//创建session对象
HttpSessionsession=request.getSession();
//设置域属性来共享数据
session.setAttribute("username",username);
}else{
    
    //用户名或者密码不正确
request.setAttribute("msg","用户名或者密码不正确");
//请求转发
request.getRequestDispatcher("/login.jsp")
.forward(request,response);
return;
}
}catch(SQLException|ClassNotFoundExceptione){
    
    
e.printStackTrace();
}
//5.登录成功,跳转到首页
response.sendRedirect(request.getContextPath());

前台_head.jsp页面回显用户名

<%
//判断是否有session对象,并且对象中是否包含名称为username的域属性
if(request.getSession(false)!=null
&&request.getSession().getAttribute("username")!=null){
    
    
%>
<ahref="#">欢迎,<%=request.getSession().getAttribute("username")%>回来</a>&nbsp;&nbsp;|&nbsp;&nbsp;
<ahref="<%=request.getContextPath()%>/LogoutServlet">登出</a>
<%
}else{
    
    //不需要保留用户登录状态,直接展示登录和注册
%>
<ahref="<%=request.getContextPath()%>/login.jsp">登录</a>&nbsp;&nbsp;|&nbsp;&nbsp;
<ahref="<%=request.getContextPath()%>/regist.jsp">注册</a>
<%
}
 
%>

新建LogoutServlet

packagecom.easymall.servlet;
 
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
 
@WebServlet("/LogoutServlet")
publicclassLogoutServletextendsHttpServlet{
    
    
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
    
    
//判断是否有session对象
if(request.getSession(false)!=null){
    
    
//自杀
request.getSession().invalidate();
}
//跳转到主页---重新判断
response.sendRedirect(request.getContextPath());
}
 
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
    
    
doPost(request,response);
}
}

实现验证码

创建验证码工具类,从课前资料导入(如果出现乱码把内容粘贴过来)
在这里插入图片描述
把main方法注释掉
修改regist.jsp页面

<tr>
<tdclass="tds">验证码:</td>
<td>
<inputtype="text"name="valistr"/>
<imgid="img"src="<%=request.getContextPath()%>/ValistrServlet"width=""height=""alt=""/>
<span></span>
</td>
</tr>
//添加验证码的图片点击事件
$("#img").click(function(){
    
    
vardate=newDate();
vartime=date.getTime();
$(this).attr("src","<%=request.getContextPath()%>/ValistrServlet?time="+time);
});

新建ValistrServlet

packagecom.easymall.servlet;
 
importcom.easymall.utiles.VerifyCode;
 
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
 
@WebServlet("/ValistrServlet")
publicclassValistrServletextendsHttpServlet{
    
    
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
    
    
//控制不使用缓存
response.setDateHeader("Expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("pragma","no-cache");
 
//生成验证码图片
VerifyCodevc=newVerifyCode();
//把图片输出到前台浏览器的验证码图片框
vc.drawImage(response.getOutputStream());
//获取验证码的字符内容
Stringcode=vc.getCode();
 
//把验证码内容存放到session域属性身上来进行共享
HttpSessionsession=request.getSession();
session.setAttribute("valistr",code);
 
}
 
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
    
    
doPost(request,response);
}
}

修改RegistServlet来验证验证码是否正确

//验证码是否正确
//获取域属性的值---验证码的值
Stringvalistr1=(String)request.getSession().
getAttribute("valistr");
//判断输入的验证码的内容和获取的session域属性的验证码的值是否一致
if(valistr!=""&&!valistr.equalsIgnoreCase(valistr1)){
    
    
//域对象设置域属性(共享数据)
request.setAttribute("msg","验证码不正确");
//请求转发---把数据共享到jsp页面
request.getRequestDispatcher("/regist.jsp")
.forward(request,response);
//此处进行非空验证,后续代码不能继续执行
return;
}

猜你喜欢

转载自blog.csdn.net/qq_41536934/article/details/112602310