会话技术
一.作用域对象
1.作用域对象概述
- 有作用域的对象
- 作用域对象可以用来存储数据并且可以在不同的组件之间进行传递
- 传递的范围受作用域的限制,一旦超过范围,立即失效
2.两个作用域对象
作用域对象 | 描述 |
---|---|
request对象 | 作用范围是一次请求 |
ServletContext对象 | 作用范围是当前模块 |
3.常用方法
方法 | 描述 |
---|---|
setAttribute(“key”,”value”) | 向作用域中放值 |
getAttribute(“key”) | 根据key获取值 |
removeAttribute(“key”) | 根据key移除值 |
4.request对象
(1)FirstServlet
package com.demo.servlet;
import javax.servlet.ServletContext;
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;
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("color","red");
System.out.println(req.getAttribute("color"));
resp.sendRedirect("second");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
(2)SecondServlet
package com.demo.servlet;
import javax.servlet.ServletContext;
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;
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("second中的数据:"+req.getAttribute("color"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
(3)结论
- request作用域的范围就只有一次请求,下一个请求发出时上一个请求就失效。
5.ServletContext对象
(1)在web.xml中配置
- 上下文对象
- 该对象属于当前这个模块,对当前模块中所有Servlet公开的。
a.配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>house</param-name>
<param-value>my house</param-value>
</context-param>
<context-param>
<param-name>car</param-name>
<param-value>BYD</param-value>
</context-param>
</web-app>
b.Servlet中获取上下文对象信息
- ServletContext对象属于当前模块,被当前模块中所有的Servlet共享
package com.demo.servlet;
import javax.servlet.ServletContext;
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;
@WebServlet("/context")
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//获取ServletContext对象
ServletContext sc = getServletContext();
System.out.println(sc.getInitParameter("car"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
(2)重定向方式
a.FirstServlet
package com.demo02.servlet;
import javax.servlet.ServletContext;
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;
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ServletContext sc = getServletContext();
sc.setAttribute("color","green");
System.out.println(sc.getAttribute("color"));
resp.sendRedirect("second");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
b.SecondServlet
package com.demo02.servlet;
import javax.servlet.ServletContext;
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;
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("second中的数据:"+getServletContext().getAttribute("color"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
(3)结论
- ServletContext作用域对当前模块中所有的Servlet有效
- 服务器关闭,ServletContext作用域就会被清理掉
二.会话技术
1.会话技术概述
- Web会话可简单理解为:用户打开一个浏览器,访问一个Web站点,在该站点点击多个超链接,访问服务器多个Web茨院,然后关闭浏览器,整个过程称之为一个会话。
- 会话(Session)是一个可与与服务器之间的不中断的请求响应序列。对客户的每个请求,服务器能够识别出请求来自于同一个客户。当一个未知的客户想Web应用程序发送第一个请求时就开始了一个会话。当客户明确结束会话或服务器在预定义的时限内不从客户接受任何请求时,会话就结束了。当会话结束后,服务器就忘记客户及客户的请求。
- 客户向Web应用程序发送的首次请求并不是客户与服务器的第一次交互。首次请求指的是需要创建会话的请求。我们称之为首次请求时因为该请求时对多个请求技术的开始(逻辑上),也是服务器开始记住客户的请求。例如,当用户登录或想购物车中天健一件商品时,就必须开始一个会话。
2.会话技术分类
- 客户端会话:Cookie
- 服务器会话:Session
3.Cookie
(1)Cookie概述
- Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息 [1] 。
(2)Cookie在项目应用
- QQ记住密码
- 网站登录页面账号密码回填
- 购物网站,根据用户购买记录,浏览记录,搜索记录进行定向推荐
(3)Cookie作用
- 将数据存在客户端上
- 减少了服务器压力
- 增强了用户体验
(4)Cookie的位置(Edge浏览器)
a.方式一
a.1
a.2
b.方式二
(5)删除Cookie
- Ctrl+Shift+Delete
(6)Cookie在代码中使用
a.创建页面发送请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="cookieServlet">测试Cookie</a>
</body>
</html>
b.Servlet中创建Cookie并将之发送到客户端存起来
package com.demo.servlet;
import javax.servlet.ServletContext;
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("/cookieServlet")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//创建Cookie
Cookie cookie = new Cookie("color","red");
//将Cookie放入响应中,随着响应回到客户端
resp.addCookie(cookie);
resp.sendRedirect("result.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
c.在result.jsp页面上获取Cookie
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//获取当前站点所有的cookie
//cookie不能一个一个获取,只能一次性获取所有
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie:cookies) {
out.write(cookie.getName()+","+cookie.getValue());
}
}
%>
</body>
</html>
(7)Cookie注意事项
1、Cookie是以字符串的形式存储数据的,key不能是中文
2、Cookie是小型文本文件,极限是4kb
3、Cookie储存在客户端上的,不安全
4、Cookie默认浏览器关闭时自动失效,但是可以手动设置时效
cookie.setMaxAge(60*60*24**30);
4.Cookie案例记住密码
(1)功能描述
- 第一次访问登录页面,用户输入账号密码
- 如果选中了记住密码,那么在第二次访问该页面时,自动填充账号密码。(如果输入的账号密码登录失败,就算选中了记住密码,也不需要记忆)
- 如果没有选记住密码,那么在第二次访问该页面时,还是需要手动输入
- 如果之前记住了密码,在后续登录过程中,点击取消了记住密码,就要将之前记住的内容删除掉
(2)登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<%
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie:cookies){
if ("username".equals(cookie.getName())) {
pageContext.setAttribute("username",cookie.getValue());
}
if ("password".equals(cookie.getName())) {
pageContext.setAttribute("password",cookie.getValue());
}
}
}
%>
<form action="cookieLogin" method="post">
账号:<input type="text" name="username" value="${username}"><br>
密码:<input type="password" name="password" value="${password}"><br>
<%--empty password:判断password是否为空,为空则返回true,反之返回false--%>
<input type="checkbox" name="remember" value="ok" ${empty password ?'':'checked'}>记住密码<br>
<input type="submit" value="登录">
</form>
</body>
</html>
(3)CookieLoginServlet.java
package com.demo.servlet;
import javax.servlet.ServletContext;
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("/cookieLogin")
public class CookieLoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
@Override
protected void doPost(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");
//默认登录成功
boolean res = true;
if (res) {
//登录成功的情况下,获取用户是否需要记住密码
//特殊情况,这一组复选框中只有一个复选框时,直接使用getParameter即可
String rem = req.getParameter("remember");
if ("ok".equals(rem)) {
//选中了记住密码
Cookie nameCookie = new Cookie("username",username);
Cookie passwordCookie = new Cookie("password",password);
//设置时效
nameCookie.setMaxAge(60*60*24*30);
passwordCookie.setMaxAge(60*60*24*30);
//将cookie放到响应中
resp.addCookie(nameCookie);
resp.addCookie(passwordCookie);
} else {
//创建两个跟客户端cookie同名的cookie
Cookie nameCookie = new Cookie("username",null);
Cookie passwordCookie = new Cookie("password",null);
//设置时效为0
nameCookie.setMaxAge(0);
passwordCookie.setMaxAge(0);
//回到客户端,立即将以前同名的cookie覆盖掉(客户端不能出现同名cookie),覆盖掉后立刻失效
resp.addCookie(nameCookie);
resp.addCookie(passwordCookie);
}
resp.sendRedirect("index.jsp");
} else {
resp.sendRedirect("login.jsp");
}
}
}
5.Session
(1)Session概述
- Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。
(2)Session在项目中的使用
- 登录某网站后,该网站下所有页面共享登录信息
- 未登录情况下,某些页面无法访问
(3)案例一
- 实现项目中登录信息的共享
a.设计登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<form action="sessionLogin" method="post">
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
b.SessionLoginServlet.java
package com.etime.servlet;
import javax.servlet.ServletContext;
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("/sessionLogin")
public class SessionLoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
@Override
protected void doPost(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");
//默认登录成功
boolean res = true;
if (res) {
//登录成功的情况下,将当前登录用户信息放入Session
HttpSession session = req.getSession();
session.setAttribute("name",username);
resp.sendRedirect("index.jsp");
} else {
resp.sendRedirect("login.jsp");
}
}
}
c.在index.jsp获取登录信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
恭喜您${sessionScope.name},登录成功
</body>
</html>
(4)案例二
- 未登录情况下,某些页面无法访问
a.result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Object name = session.getAttribute("name");
if (name == null) {
//未登录,跳转到登录页面
response.sendRedirect("login.jsp");
}
%>
result页面测试:恭喜您${sessionScope.name},登录成功
</body>
</html>
(5)Session跟踪技术
- Session本身不具备识别浏览器关闭与打开的功能,原因在JSESSIONID。也就是说,Session依赖于Cookie。
6.Session案例退出登录
(1)index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
恭喜您${sessionScope.name},登录成功<a href="logoutServlet">退出</a>
</body>
</html>
(2)LogoutServlet.java
package com.demo.servlet;
import javax.servlet.ServletContext;
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("/logoutServlet")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//将登录成功时放入session中的数据移除掉
HttpSession session = req.getSession();
//session.removeAttribute("name");
//干掉session
session.invalidate();
resp.sendRedirect("login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
7.Session购物车
(1)准备数据
CREATE DATABASE mydb;
USE mydb;
CREATE TABLE commodity(
cid INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
price DOUBLE(8,2)
);
(2)index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="commodityServlet?flag=getAllCommodity">展示所有商品</a>
</body>
</html>
(3)实体类Commodity.java
package com.demo.entity;
public class Commodity {
private int cid;
private String name;
private double price;
public Commodity() {
}
public Commodity(int cid, String name, double price) {
this.cid = cid;
this.name = name;
this.price = price;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
(4)CommodityServlet.java
package com.demo.servlet;
import com.demo.entity.Commodity;
import com.demo.service.CommodityService;
import com.demo.service.impl.CommodityServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet("/commodityServlet")
public class CommodityServlet 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 flag = req.getParameter("flag");
CommodityService commodityService = new CommodityServiceImpl();
if ("getAllCommodity".equals(flag)) {
List<Commodity> list = commodityService.getAllCommodity();
req.setAttribute("comList",list);
req.getRequestDispatcher("commodity.jsp").forward(req,resp);
} else if ("addTrolley".equals(flag)) {
int cid = Integer.parseInt(req.getParameter("cid"));
Commodity commodity = commodityService.getCommodityByCid(cid);
HttpSession session = req.getSession();
//改变session的时效
Cookie cookie = new Cookie("JSESSIONID",session.getId());
cookie.setMaxAge(60*60);
resp.addCookie(cookie);
//将session当作购物车
List<Commodity> list = (List<Commodity>)session.getAttribute("com");
//做第一个加入购物车商品的判断
if (list == null) {
list = new ArrayList<>();
}
list.add(commodity);
session.setAttribute("com",list);
resp.sendRedirect("trolley.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
(5)CommodityService.java
package com.demo.service;
import com.demo.entity.Commodity;
import java.util.List;
public interface CommodityService {
List<Commodity> getAllCommodity();
Commodity getCommodityByCid(int cid);
}
(6)CommodityServiceImpl.java
package com.demo.service.impl;
import com.demo.dao.CommodityDao;
import com.demo.dao.impl.CommodityDaoImpl;
import com.demo.entity.Commodity;
import com.demo.service.CommodityService;
import java.util.List;
public class CommodityServiceImpl implements CommodityService {
CommodityDao commodityDao = new CommodityDaoImpl();
@Override
public List<Commodity> getAllCommodity() {
return commodityDao.getAllCommodity();
}
@Override
public Commodity getCommodityByCid(int cid) {
return commodityDao.getCommodityByCid(cid);
}
}
(7)CommodityDao.java
package com.demo.dao;
import com.demo.entity.Commodity;
import java.util.List;
public interface CommodityDao {
List<Commodity> getAllCommodity();
Commodity getCommodityByCid(int cid);
}
(8)CommodityDaoImpl.java
package com.demo.dao.impl;
import com.demo.dao.CommodityDao;
import com.demo.entity.Commodity;
import com.demo.util.C3P0Util;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.SQLException;
import java.util.List;
public class CommodityDaoImpl implements CommodityDao {
QueryRunner queryRunner = new QueryRunner(C3P0Util.getDataSource());
@Override
public List<Commodity> getAllCommodity() {
List<Commodity> list = null;
String sql = "select * from commodity";
try {
list = queryRunner.query(sql, new BeanListHandler<>(Commodity.class));
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
@Override
public Commodity getCommodityByCid(int cid) {
Commodity commodity = null;
String sql = "select * from commodity where cid=?";
try {
commodity = queryRunner.query(sql, new BeanHandler<>(Commodity.class), cid);
} catch (SQLException e) {
e.printStackTrace();
}
return commodity;
}
}
(9)commodity.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0" width="500">
<tr>
<td>编号</td>
<td>商品名称</td>
<td>价格</td>
<td>操作</td>
</tr>
<c:forEach var="com" items="${comList}">
<tr>
<td>${com.cid}</td>
<td>${com.name}</td>
<td>${com.price}</td>
<td>
<a href="commodityServlet?flag=addTrolley&cid=${com.cid}">加入购物车</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
(10)trolley.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>购物车</title>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0" width="500">
<tr>
<td>编号</td>
<td>商品名称</td>
<td>价格</td>
</tr>
<c:forEach var="com" items="${sessionScope.com}">
<tr>
<td>${com.cid}</td>
<td>${com.name}</td>
<td>${com.price}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
三.Cookie和Session的区别
Cookie | Session | |
---|---|---|
存储位置 | 客户端 | 服务器端 |
限制 | 大小、个数限制 | 没有大小限制和服务器的内存大小有关 |
存储类型 | 字符串数据 | 任意类型数据 |
安全性 | 通过拦截或本地文件找得到你的cookie后可以进行攻击 | |
时效性 | 手动设置时效 | 务器端上会存在一段时间(默认30分钟)才会消失,如果session过多会增加服务器的压力。 |