今天学习了Cookie、session和浅了解了一下jsp
时间: 2022/5/13
会话
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。
Web应用中的会话过程类似于生活中的打电话过程,它指的是一个浏览器与Web服务器之间连续发生的一系列请求和响应过程。如图通俗理解
会话技术问题
由于Http是一个无状态协议,他不会记录每次请求的状态,这就造成了同一个会话的两请求之间相互独立,彼此没有联系
解决思路:
在客户端或者服务端需要一种技术,来记录一次会话过程中产生的一些数据
技术引出:
客户端:cookie 服务端:session
Cookie
Cookie可以在一次会话的多次请求响应之间共享数据,将数据保存到客户端(浏览器)
cookie的格式
cookie其实是请求头中的一个键值对
cookie的使用步骤
cookie是在服务器端创建
通过响应的方式从服务端发送给浏览器
在浏览器中保存数据
浏览器在给服务器发送请求时,会携带cookie的数据
//doGet
Cookie cookie = new Cookie("age", "14");
resp.addCookie(cookie);
通过响应的方式从服务端发送给浏览器
//doGet
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name+"="+value);
}
浏览器在给服务器发送请求时,会携带cookie的数据
获取浏览器中携带的cookie数据
工作原理
细节
1.一次可不可以发送多个cookie
可以一次发送多个cookie,注意多个cookie的键不能重复
2.cookie在浏览器中保存多长时间
默认情况下,浏览器关闭cookie数据就被删除了.
可以设置cookie的存活时间
setMaxAge(秒):设置多长时间就存活多长时间
如果设置-1代表默认值
如果设置0代表存活0秒,相当于立马删除
3.cookie能不能存中文
tomcat8之前中文会乱码
tomcat8开始之后服务器已经解决了中文的乱码
但是依旧不能使用特殊符号, 如果要使用特殊符号,需要手动编码解码
URLEncoder类: encode(String s, String enc) 将指定的字符串,按指定的编码表编码
URLDecoder类: decode(String s, String enc) 将指定的字符串,按指定的编码表解码
String name = URLEncoder.encode("你好 世界", "utf-8");
Cookie cookie = new Cookie("name", name);
resp.addCookie(cookie);
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("name")){
String decode = URLDecoder.decode(cookie.getValue(),"utf-8" );
System.out.println(cookie.getName()+"="+decode);
}
}
Session
Session可以在一次会话的多次请求之间共享数据,它将数据保存到服务器,并且无大小限制
session域对象
session域对象范围是当前会话
添加数据 setAttribute(String name, Object value)
获取数据 getAttribute(String name)
删除数据 removeAttribute(String name)
//session域对象
//获取session对象
HttpSession session = request.getSession();
//给session存储键值对
session.setAttribute("aaa","123456");
//request域对象
request.setAttribute("bbb","234567");
//获取session域中的数据
HttpSession session = request.getSession();
Object aaa = session.getAttribute("aaa");
System.out.println(aaa);
//获取request域中的数据
Object bbb = request.getAttribute("bbb");
System.out.println(bbb);
工作原理
细节
1.当浏览器关闭后,服务器不关闭,两次获取session是同一个吗
关闭浏览器后,cookie就消失了,也就是说session的id就没了
所以获取的不是同一个session对象
2. 浏览器不关闭,服务器关闭后,两次获取的session是同一个吗
不是同一个.因为服务器关闭内存中的对象都消失了
重新打开服务器,session对象不存在了…
tomcat可以配置,当服务器关闭之后,把session对象保存在硬盘中,当重新启动服务器之后,把硬盘中的session对象读取到内存中
钝化: 把内存中的session对象----> 硬盘中
活化: 硬盘中的session对象 -----> 内存中
tomcat里面勾选:
Presserve sessions across restarts and redeploys
注意:
钝化和活化底层其实是序列化流
所以session中保存的如果是对象,对象的类型必须要实现Serializable接口
session对象的生命周期
session的创建:
在服务器中第一次使用session的时候会创建session对象
如果服务器中没有使用session对象,那么session就不会创建
session的销毁:
默认情况下,在30分钟内不使用对象就会销毁,或者关闭服务器对象就会销毁
如何修改session对象销毁时间:
tomcat/conf/web.xml配置文件中可以设置时间
可以调用一个方法能立马销毁session对象:
session.invalidate()
cookie和session的区别[面试点]
相同点:
都属于会话技术,能够在一次会话的多次请求响应之间共享数据
区别:
cookie是把数据保存在浏览器上, 不太安全, 对数据大小有限制
session是把数据保存在服务器上, 安全, 对数据大小没限制
销毁时间:
cookie的数据什么时候会销毁:
默认关闭浏览器的时候销毁
setMaxAge()
session的数据什么时候会销毁:
30分钟没有被使用就会销毁,或者服务器关闭
invalidate()方法代表立即销毁
如果cookie被销毁了,就算session对象还在 也无法再获取对象中的数据
EL表达式
EL(Expression Language)表达式语言,主要用来简化jsp中对java代码的操作,它可以从域对象中获取数据
语法:${表达式}
Jsp页面中有四大域对象
- page:当前页面有效
- request:当前请求有效
- session:当前会话有效
- application:当前应用有效
获取域对象中的数据
* 获取精准域中数据
${requestScope.键名} 从HttpServletRequest域中获取
${sessionScope.键名} 从HttpSession域中获取
* 简化写法
${键名}
不写域名称,是按照上面的域范围从小到大依次从四个域中进行查找;
如果从某一个域中找到了,立即返回;
如果四个域中都没有,则返回空内容;
获取不同类型的数据
获取不同类型的数据:
简单类型:$ {键名}
对象类型:$ {键名.属性名}
集合类型:$ {键名[索引]}
案例:显示上次登录时间(session)、登录案例
//@WebServlet("/loginServlet")
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//这里直接用假数据
String u="张三";
String p="123";
String username = request.getParameter("username");
String password = request.getParameter("password");
String yzm = request.getParameter("yzm");
//KAPTCHA_SESSION_KEY
//获取验证码
HttpSession session = request.getSession();
String code = (String) session.getAttribute("KAPTCHA_SESSION_KEY");
session.removeAttribute("code");
//使用session记录登陆时间
if (session.getAttribute("lastTime") == null){
session.setAttribute("log","您第一次访问本页面...");
}else {
session.setAttribute("log","欢迎回来,您上一次访问时间为:"+request.getSession().getAttribute("lastTime"));
}
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM日dd日-HH:mm:ss");
String format = dateFormat.format(date);
session.setAttribute("lastTime",format);
//判断登录,先判断验证码 ,然后在账号密码是否正确
if (code != null && code.equalsIgnoreCase(yzm)){
if (u.equals(username) && p.equals(password)){
request.getRequestDispatcher("/zhuye.jsp").forward(request,response);
}else {
session.setAttribute("msg","账号或者密码错误");
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}else {
session.setAttribute("msg","验证码错误");
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
//login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<style>
span{
color: red;
}
</style>
<body>
<form action="/loginServlet" method="get">
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
验证码:<img src="/kaptchaServlet" id="code"><br>
<input type="text" name="yzm"><br>
<input type="submit" value="提交">
</form>
<span>${msg}</span>
<script>
let code = document.getElementById("code");
code.onclick=function () {
code.src="/kaptchaServlet?"+new Date().getTime();
}
</script>
</body>
</html>
//zhuye.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>随便当个主页</title>
</head>
<body>
<h1>这是一个主页</h1>
<span>
${log}
</span>
</body>
</html>
<!-- 生成验证码的servlet,这里使用的是谷歌的验证码jar包 -->
<servlet>
<!-- 生成图片的servlet -->
<servlet-name>kaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<!-- 映射的url -->
<servlet-mapping>
<servlet-name>kaptchaServlet</servlet-name>
<url-pattern>/kaptchaServlet</url-pattern>
</servlet-mapping>