前言
session它是一个域对象
三大域对象:ServletContext,Session,Request
注意:
由于客户端需要接收、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。
一,Session
(1)使用Cookie的问题:
1,最多存储4k字符串
2,存储数据不太安全
session的作用:在一次会话的多次请求之间共享数据,将数据保存到服务器
(2)HTTPSession也是一个域对象
void setAttribute(String name, Object value)
在session中保存数据
Object getAttribute(String name)
从session中获取数据
void removeAttribute(String name)
从session中移除数据
使用:
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");
code:
@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);
}
}
(3)工作原理
Session基于Cookie技术实现
(4)Session细节
--1.客户端关闭,服务器不关闭
两次获取的Session数据是否为相同:
* 默认情况下,浏览器关闭,再次打开二次获取的session不一样
基于cookie实现(浏览器关闭,cookie销毁)
* 设置cookie的存活时间(JESSIONID)
这里我们代替服务器,做一个小操作,覆盖这个JSESSIONID,指定持久化时间
--2客户端不关闭,服务器关闭
两次获取的Session数据是否相同?
* 当服务器正常关闭,重启后,二次获取的session数据一样
tomcat这实现以下二个功能
钝化(序列化)
当服务器正常关闭时,session中的数据,会序列化到磁盘
活化(反序列化)
当服务器开启后,从磁盘文件中,反序列化到内存中
注意一个问题:Idea问题:
支持钝化,但是在重新启动的时候又会删除了钝化文件,所以导致会变,解决方法如下:
进行打对勾,强制设置idea重启时,不清除Session会话
(4)生命周期:
* 何时创建
用户第一次调用request.getSession()方法时,创建
* 何时销毁
服务器非正常关闭
非活跃状态30分钟后
tomcat进行配置 /tocmat安装目录/conf/web.xml
session.invalidate(); 自杀
* 作用范围
一次会话中,多次请求之间
注意:每一个浏览器跟服务器都是独立的会话...
(5)URL重写
什么是url重写?如果浏览器不支持 Cookie 或用户阻止了所有 Cookie ,可以把会话 ID 附加在 HTML 页面中所有的 URL 上,这些页面作为响应发送给客户。这样,当用户单击 URL 时,会话 ID 被自动作为请求头的一部分而不是作为头行发送回服务器。这种方法称为 URL 重写 (URL rewriting) 。作用:当客户机不接受 cookie 时, server 就使用 URL 重写作为会话跟踪的基本方式 .URL 重写,添加了附加数据 ( 会话 ID) 到请求的 URL 路径上 .会话 ID 必须被编码作为该 URL 字符串中的路径参数。该参数的名称为 jsessionid,简单说就是 cookie 禁用了 jsessionid 就不能携带,那么每次请求,都是一个新的 session 对象。如果想要使用同一个 session 对象,可以使用 url 重写url 重写实现:response. encodeRedirectURL(java.lang.String?url)用于对 sendRedirect 方法后的 url 地址进行重写。response. encodeURL(java.lang.String?url)用于对表单 action 和超链接的 url 地址进行重写
Session基于Cookie技术实现;浏览器的Cookie是可以禁用的,一旦禁用了之后,Session就会出现问题了。
开发中,一般我们是不关注用户的cookie是否禁用的,若用户禁用了cookie,只能用其他网站了
若真想处理用户端的cookie禁用,我们可以使用url重写技术:
@WebServlet("/SessionDemo")
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 = "/dsession/GetSession";
// 重写url,拼接JSESSIONID
url = response.encodeURL(url); // /dsession/GetSession?JSESSIONID=xxsdfasdf
System.out.println(url);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<a href='" + url + "'>跳转到获取session内容</a>");
}
}
(6)Session特点
1. session存储数据在服务器
2. session存储类型任意(Object)
3. session存储大小和数量没有限制(相对于内存)
4. session存储相对安全
cookie和session的选择
-
cookie将数据保存在浏览器端,数据相对不安全.建议敏感的数据不要放在cookie中,而且数据大小是有限制的
-
成本低,对服务器要求不高
-
浏览器,解决这个不足,localStroage【项目二中讲解...】
-
-
session将数据保存在服务器端,数据相对安全.数据的大小要比cookie中数据灵活很多
-
成本较高,对服务器压力较大
-
二、三大域对象总结:
request、session、ServletContext
相关API
1. 设置数据
void setAttribute(String name, Object o)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
生命周期:
ServletContext域对象
* 何时创建
服务器正常启动,项目加载时,创建
* 何时销毁
服务器关闭或项目卸载时,销毁
* 作用范围
整个web项目(共享数据)
针对一个 WEB 应用。一个 WEB 应用只有一个 ServletContext 对象,使用该对象保存的数据在整个 WEB 应用中都有效。创建 : 服务器启动的时候 .销毁 : 服务器关闭的时候或者项目移除的时候 .
HTTPSessiont域对象
* 何时创建
用户第一次调用request.getSession()方法时,创建
用户访问携带的jsessionid与服务器不匹配时,创建
* 何时销毁
服务器非正常关闭
未活跃状态30分钟
自己消灭自己
* 作用范围
一次会话中,多次请求间(共享数据)
针对一次会话。使用该对象保存数据,一次会话(多次请求)内数据有效。创建 : 可以暂且认为在服务器第一次调用 getSession() 的时候 . 服务器创建 session 的对象 . 因为 session 销毁后 , 再次调用 getSession() 的时候也会创建 .销毁 :非正常关闭服务器Session 过期了 , 默认时间是 30 分钟 .手动调用 session 的 invalidate 的方法
HttpServletRequest域对象
* 何时创建
用户发送请求时,创建
* 何时销毁
服务器做出响应后,销毁
* 作用范围
一次请求中,多次转发间(共享数据)
针对一次请求。使用该对象保存数据,一次请求(一个页面,如果是请求转发多个页面)内数据有效 .创建 : 客户端向服务器发送一次请求销毁 : 服务器为这次请求作出响应之后 , 销毁 request.
总结:
-
能用小的不用大的:request<session<servletContext
-
常用的场景:
-
request:一次查询的结果(servlet转发jsp)
-
session:存放当前会话的私有数据
-
用户登录状态
-
验证码
-
购物车
-
-
-
servletContext:若需要所有的servlet都能访问到,才使用这个域对象.
三 。案例:
1.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>goods.jsp</title>
</head>
<body>
<h3>商品列表</h3>
<a href="/dsession/AddCartServlet?name=电视机">电视机</a><br>
<a href="/dsession/AddCartServlet?name=冰箱">冰箱</a><br>
<a href="/dsession/AddCartServlet?name=洗衣机">洗衣机</a><br>
<a href="/dsession/AddCartServlet?name=电脑">电脑</a><br>
</body>
</html>
@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='/dsession/goods.jsp'>继续浏览</a><br>");
// 10.查看购物车
response.getWriter().write("<a href='/dsession/cart.jsp'>查看购物车</a><br>");
}
}
<%@ 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>
2.用户登录
<%--
Created by IntelliJ IDEA.
User: apple
Date: 2020/4/19
Time: 18:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
<style type="text/css">
.content{
margin: 0 auto;
height: 600px;
width: 800px;
background-color: white;
}
#errormsg{
font-size: 16px;
color: red;
}
input{
width: 160px;
height: 40px;
}
</style>
</head>
<body>
<div class="content">
<h3>用户登录</h3>
<form action="/day20200419/LoginServlet" method="post">
<span id="errormsg"></span><br>
用户名:<input type="text" name="username"><br>
密码: <input type="password" name="password"> <br>
验证码:<input type="text" name="checkcode"><img src="/d19/CheckCodeServlet" alt="" id="checkcode"> <br>
<input type="submit" value="登录">
</form>
</div>
<script type="text/javascript">
let elementById = document.getElementById("errormsg");
<%
String errormsg = (String) request.getAttribute("errormsg");
if (errormsg==null||errormsg.length()==0){
errormsg="";
}
%>
elementById.innerHTML=`<%=errormsg%>`;
document.getElementById("checkcode").onclick = function () {
this.src="/d19/CheckCodeServlet?"+new Date().getTime();
}
</script>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: apple
Date: 2020/4/19
Time: 18:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>您登录成功了:
<%
String username = (String) request.getSession().getAttribute("username");
out.write(username);
%>
</h1>
</body>
</html>
package com.wsl.zy;
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("/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String checkcode = request.getParameter("checkcode");
String codeSession = (String) request.getSession().getAttribute("codeSession");
if (!checkcode.equalsIgnoreCase(codeSession)){
request.setAttribute("errormsg","验证码有误!");
request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
//获取输入的用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判断用户名或者密码不正确
if (!("wsl".equals(username)&&"123456".equals(password))){
request.setAttribute("errormsg","用户名或者密码错误");
request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
request.getSession().setAttribute("username",username);
response.sendRedirect(request.getContextPath()+"/success.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}