回顾
1. 会话技术
http是无状态协议,多次请求之间相互独立,不能共享数据
会话技术为了解决多次请求之间,共享数据问题
cookie将数据存储到客户端
2. cookie快速入门
设置cookie
Cookie cookie = new Cookie(String name,String value);
response.addCookie(cookie);
接收cookie
Cookie[] cookies = rqeuest.getCookies();
3. cookie使用细节
服务器一次可以发送多个cookie
tomcat8及以上版本支持中文,但不支持特殊符号(空格、逗号、分号、加号)
URLEncoder 编码
URLDecoder 解码
cookie.setPath(String path);设置cookie的携带路径
cookie.setMaxAge(int second);
正数
负数
零
4. cookie特点
数据存储在客户端,只能存中文,单个大小不能超过4KB,数量不能超过50个,数据不太安全..
5. 综合案例
上次访问时间 --> jsp
上次访问记录
Session&三大域对象总结
今日目标
1. session【重点】
它也是一个域对象
2. 三大域对象总结
servletContext
session
request
3. 综合案例
商品购物车
用户登录(验证码)
一 Session
1.1 概述
使用Cookie问题
- 最多存储4K字符串
- 存储数据不太安全
session作用:在一次会话的多次请求之间共享数据,将数据保存到服务器端
1.2 快速入门
HttpSession也是一个域对象
* API
1. 存储数据
void setAttribute(String name,Object value)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
步骤分析
1. 将数据存储到session中
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,存储数据
session.setAttribute("username","哈哈,呵呵");
2. 从session中获取数据
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,获取数据
session.getAttribute("username");
@WebServlet("/SetSession")
public class SetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,存储数据
session.setAttribute("username", "哈哈,呵呵");
}
}
@WebServlet("/GetSession")
public class GetSession extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,获取数据
String username = (String) session.getAttribute("username");
System.out.println("GetSession获取:" + username);
}
}
1.3 工作原理
Session基于Cookie技术实现
1.4 Session细节
1.4.1 客户端关闭,服务器不关闭
两次获取的Session数据是否为相同?
* 默认情况下,浏览器关闭,再次打开二次获取的session不一样
基于cookie实现(浏览器关闭,cookie销毁)
* 设置cookie的存活时间(JESSIONID)
这里我们代替服务器,做一个小操作,覆盖这个JSESSIONID,指定持久化时间
1.4.2 客户端不关闭,服务器关闭
两次获取的Session数据是否为相同?
* 当服务器正常关闭,重启后,二次获取的session数据一样
tomcat这哥们实现以下二个功能
钝化(序列化)
当服务器正常关闭时,session中的数据,会序列化到磁盘
活化(反序列化)
当服务器开启后,从磁盘文件中,反序列化到内存中
我们使用的idea工具有坑....
支持钝化
我们可以强制设置idea重启时,不清除session会话
1.4.3 生命周期
* 何时创建
用户第一次调用request.getSession()方法时,创建
* 何时销毁
服务器非正常关闭
非活跃状态30分钟后
tomcat进行配置 /tocmat安装目录/conf/web.xml
session.invalidate(); 自杀
* 作用范围
一次会话中,多次请求之间
注意:每一个浏览器跟服务器都是独立的会话...
1.4.4 URL重写(了解)
Session基于Cookie技术实现;浏览器的Cookie是可以禁用的,一旦禁用了之后,Session就会出现问题了。
开发中,一般我们是不关注用户的cookie是否禁用的,若用户禁用了cookie,只能别用网站了
若真想处理用户端的cookie禁用,我们可以使用url重写技术:
@WebServlet("/SessionDemo2")
public class SessionDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取session对象
HttpSession session = request.getSession();
// 向session中存数据
session.setAttribute("username", "哈哈,即使浏览器禁用了cookie,也不影响我使用");
// 定义url
String url = "/day12_session/GetSession";
// 重写url,拼接JSESSIONID
url = response.encodeURL(url); // /day12_session/GetSession?JSESSIONID=xxsdfasdf
System.out.println(url);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");
}
}
1.5 Session特点
1. session存储数据在服务器
2. session存储类型任意(Object)
3. session存储大小和数量没有限制(相对于内存)
4. session存储相对安全
cookie和session的选择
- cookie将数据保存在浏览器端,数据相对不安全.建议敏感的数据不要放在cookie中,而且数据大小是有限制的
- 成本低,对服务器要求不高
- 浏览器,解决这个不足,localStroage【项目二中讲解...】
- session将数据保存在服务器端,数据相对安全.数据的大小要比cookie中数据灵活很多
- 成本较高,对服务器压力较大
二 三大域对象总结
request、session、ServletContext
2.1 API
1. 设置数据
void setAttribute(String name, Object o)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
2.2 生命周期
2.2.1 ServletContext域对象
* 何时创建
服务器正常启动,项目加载时,创建
* 何时销毁
服务器关闭或项目卸载时,销毁
* 作用范围
整个web项目(共享数据)
2.2.2 HttpSession域对象
* 何时创建
用户第一次调用request.getSession()方法时,创建【不太标准..】
用户访问携带的jsessionid与服务器不匹配时,创建
* 何时销毁
服务器非正常关闭
未活跃状态30分钟
自杀
* 作用范围
一次会话中,多次请求间(共享数据)
2.2.3 HttpServletRequest域对象
* 何时创建
用户发送请求时,创建
* 何时销毁
服务器做出响应后,销毁
* 作用范围
一次请求中,多次转发间(共享数据)
2.3 小结
-
能用小的不用大的:request<session<servletContext
-
常用的场景:
- request:一次查询的结果(servlet转发jsp)
- session:存放当前会话的私有数据
- 用户登录状态
- 验证码
- 购物车
-
servletContext:若需要所有的servlet都能访问到,才使用这个域对象.
- spring课程中会涉及到
三 综合案例
3.1 商品购物车
需求
有一个商品页面,可以点击超链接将商品添加到购物车,还有一个超链接,点击它的时候可以查看购物车中商品信息
3.1.1 需求分析
3.1.2 代码实现
① goods.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>goods.jsp</title>
</head>
<body>
<h3>商品列表</h3>
<a href="/day12_session/AddCartServlet?name=电视机">电视机,加入购物车</a><br>
<a href="/day12_session/AddCartServlet?name=冰箱">冰箱,加入购物车</a><br>
<a href="/day12_session/AddCartServlet?name=洗衣机">洗衣机,加入购物车</a><br>
<a href="/day12_session/AddCartServlet?name=电脑">电脑,加入购物车</a><br>
</body>
</html>
② AddCartServlet
@WebServlet("/AddCartServlet")
public class AddCartServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); // 请求解码
response.setContentType("text/html;charset=utf-8");// 响应编码
// 1.获取请求参数
String product = request.getParameter("name");
// 2.返回结果
response.getWriter().write(product + ",商品已成功加入购物车 <br>");
// 3.从session中获取购物车
Map<String, Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
// 4.判断购物车是否为空
if (cart == null) {
cart = new HashMap<>();
}
// 5.判断购物车中是否包含本次添加的商品
if (cart.containsKey(product)) {// 6.存在,数量+1
Integer oldCount = cart.get(product); // 之前数量
cart.put(product, oldCount + 1);// 数量加1
} else { // 7.不存在,直接添加商品,数量为1
cart.put(product, 1);
}
// 8.重新将购物车,写入到session中
request.getSession().setAttribute("cart", cart);
// 9.继续浏览
response.getWriter().write("<a href='/day12_session/goods.jsp'>继续浏览</a><br>");
// 10.查看购物车
response.getWriter().write("<a href='/day12_session/cart.jsp'>查看购物车</a><br>");
}
}
③cart.jsp
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>cart</title>
</head>
<body>
<h3>购物车页面</h3>
<table border="1" width="200px" align="center">
<tr>
<th>商品</th>
<th>数量</th>
</tr>
<%
// 1.从session中获取购物车
Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
// 2.判断是否为空
if(cart == null){
out.write("购物车内暂时没有商品<br>");
}else{
for (String s : cart.keySet()) {
out.write("<tr><td>"+s+"</td><td>"+cart.get(s)+"</td></tr>");
}
}
%>
</table>
</body>
</html>
3.2 用户登录(验证码)
需求
用户访问带有验证码的登录页面,输入用户名,密码以及验证码实现登录功能。
3.2.1 需求分析
3.2.2 代码实现
- 明天休息,感觉那丑自己优化...问题自己解决.....
① 创建web项目
② 导入验证码Servlet
③ login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login.jsp</title>
</head>
<body>
<h3>用户登录</h3>
<form action="/day12_login/LoginServlet" method="post">
用户:<input type="text" name="username"> <br>
密码:<input type="password" name="password"><br>
验证码:<input type="text" name="checkcode"> <img src="/day12_login/CheckcodeServlet" alt=""><br>
<input type="submit" value="登录">
<span style="color:red">
<%
String error = (String) request.getAttribute("error");
if (error != null) {
out.write(error);// 输出提示信息
}
%>
</span>
</form>
</body>
</html>
④ LoginServlet
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
// 课下作业,实现非空判断...
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 1.获取用户输入的验证码
String checkcode = request.getParameter("checkcode");
// 2.获取session中验证码
String codeSession = (String) request.getSession().getAttribute("code_session");
// 3.校验是否匹配
if (!checkcode.equalsIgnoreCase(codeSession)) {
// 验证码不配,友情提示...
request.setAttribute("error", "验证码输入错误...");
// 转发到login.jsp
request.getRequestDispatcher("/login.jsp").forward(request, response);
// 代码不在往下执行....
return;
}
// 4.获取用户输入的用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 5.判断用户名密码不正确
if (!("jack".equals(username) && "123".equals(password))) {
// 友情提示
request.setAttribute("error", "用户名或密码错误...");
// 转发到login.jsp
request.getRequestDispatcher("/login.jsp").forward(request, response);
// 代码不在往下执行....
return;
}
// 6. 将用户名存入到session中
request.getSession().setAttribute("username", username);
// 7.重定向到success.jsp
response.sendRedirect(request.getContextPath() + "/success.jsp");
}
}
⑤ success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h3><%
// 获取用户信息
String username = (String) request.getSession().getAttribute("username");
if (username != null) {
out.write("用户您好,登录成功:"+username);
}
%></h3>
</body>
</html>
老师下午总结
疑惑点|易错点|拓展
session钝化要注意的事项
-
关闭tomcat服务器的时候,tomcat服务器会对session的数据进行钝化,重启
服务器的时候可以重新读取到session的数据。
-
钝化的数据所属类一定要实现Serializable接口,否则无法钝化。
User类
package com.itheima.model;
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
设置session数据
package com.itheima.web;
import com.itheima.model.User;
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("/setSession")
public class SetSessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 创建一个User对象
User user = new User();
user.setId(110);
user.setName("狗娃");
//2. 获取sesison
HttpSession session = request.getSession();
//3. 把User对象存储到Session中
session.setAttribute("user",user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
获取Session的数据
package com.itheima.web;
import com.itheima.model.User;
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("/getSession")
public class GetSessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
HttpSession session = request.getSession();
//从session获取User
User user = (User) session.getAttribute("user");
response.getWriter().write("从session获取到的数据:"+user);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
如何检查用户是否关闭cookie
-
在用户浏览商品页面的时候,我们就发送一个cookie
-
在添加购物车的我们就检查是否有我们刚刚发送的cookie,如果没有该用户肯定是关闭了cookie的功能,
如果存在这个cookie,那么用户没有关闭。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
// 在用户浏览器商品的时候,我们就向用户发送一个cookie
Cookie cookie = new Cookie("cookieFlag","true");
response.addCookie(cookie);
%>
<h1>商品列表页面</h1>
电视机 <a href="/day37_session/addShopCart">添加购物车</a><br/>
洗衣机 <a href="/day37_session/addShopCart">添加购物车</a><br/>
</body>
</html>
package com.itheima.web;
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;
import java.io.PrintWriter;
@WebServlet("/addShopCart")
public class AddShopCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
boolean flag = true; // 浏览器是否关闭cookie的一个标记, 默认浏览器是关闭
//添加购物车之前,我先检查是否有刚刚添加的cookie带过来。
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if(cookie.getName().equals("cookieFlag")){
//有cookie过来,那么用户则没有关闭
flag = false;
break;
}
}
}
if(flag){
//关闭了cookie
out.write("<h1>尊敬的用户,我们的购物车功能需要开启cookie才可以使用!</h1>");
}else{
//没有关闭
out.write("<h1>尊敬的用户,添加成功!</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
今日重点
-
获取或创建Session
- request.getSession();
-
session域的操作方法
- setAttribute()
- getAttribute()
- removeAttribute()
-
session的原理
- 第一次获取session的时候,服务器会创建一个session,并且把该session的编号以cookie的形式发送给浏览器
-
关闭浏览器,如何找回session
- 我们需要创建一个同名的cookie,保存session的id,并且设置有效时间。
-
关闭服务器,如何保存session的数据
- tomcat会完成钝化的工作,只不过钝化的数据所属的类一定要实现Serializable接口。
-
session的生命周期
- 第一次调用request.getSesion()方法创建
- 默认情况session的销毁时间是30分钟.
- invildate() 立即销毁
网友评论