赞
踩
上次课学习了两个对象:
获取当前工程的资源文件
ServletContext的方法 | 功能 |
---|---|
InputStream getResourceAsStream(String path) | 获取web目录下资源,转成一个输入流 |
String getRealPath(String path) | 获取真实的路径 |
String getInitParameter(String name) | 获取web.xml中全局的配置参数 <context-param> |
获取作用域对象的值
ServeltContext的方法 | 作用 |
---|---|
Object getAttribute(String name) | 获取上下文域中值 |
void setAttribute(String name, Object value) | 向上下文域中添加键和值 |
void removeAttribute(String name) | 通过键删除上下文域中键和值 |
response设置响应行的方法
状态码的方法 | 描述 |
---|---|
setStatus(int status) | 作用: 设置状态码 常见状态码: 404:找不到资源 500:服务器代码异常 304:静态资源使用了缓存 302:页面进行了跳转 405:没有重写doGet或doPost方法 200:服务器正常响应 |
response设置响应头的方法
响应头的方法 | 描述 |
---|---|
void setHeader(String name, String value) | 设置响应头的键和值 |
void setContentType(String type) | 专门设置content-type响应头 1. 告诉浏览器,服务器使用的编码 2. 设置响应的编码,相当于setCharacterEncoding() 3. 设置响应的内容类型,如:text/html |
输出响应的两种方式
响应体的方法 | 描述 |
---|---|
OutputStream getOutputStream() 处理字节 | 响应的字节输出流 |
PrintWriter getWriter() 处理字符 | 响应的字符输出流 |
什么是会话
会话有哪两种技术
生活中的会话
概念:两个人一次交流的活动
BS结构的会话
概念:浏览器与服务器的多次请求和响应的过程。一个会话包含了多次请求和响应
为什么有会话技术:
因为HTTP协议(超文本传输协议,传输HTML),是一个无状态的协议,不会记录用户的状态。服务器不能通过HTTP协议来知道用户是同一个用户还是不同的用户发送的请求。通过会话技术来识别不同的用户。
会话的两种技术:
HttpSession需要使用到Cookie才能实现会话的跟踪技术
什么是会话?
一个用户的多次请求和响应的过程
会话有哪两种技术?
如何在不同的浏览器中查看Cookie的信息
如何实现自动登录?
把用户名和密码保存在本地,可以被浏览器读取,再发送给服务器实现自动登录。
使用Cookie技术将数据保存在本地。
Cookie就是用来保存数据,格式是:键值对,键和值都是文本内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ugX6zlp9-1598876513901)(assets/image-20200831091304334.png)]
点Cookie查看本地信息
按F12打开开发者模式
点下面的存储
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0zxvoIJk-1598876513963)(assets/image-20200831091723940.png)]
扩展:可以安装浏览器的插件,让浏览器的功能更加强大
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThzhnHEB-1598876513975)(assets/image-20200831091946001.png)]
问:不同浏览器之间的Cookie数据能不能共享?
因为不同的浏览器之间Cookie的数据不能共享,所以在服务器看来是不同的用户。
什么是Cookie
Cookie的执行原理
特点:本质上就是一个键值对,每个Cookie只能保存一个键和值
大小:最大不能超过4K,内容就是文本的内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkRCT5fH-1598876514027)(assets/image-20200831094141910.png)]
服务器代码要做的事情
如何创建Cookie
如何将创建的Cookie写入到浏览器端
Cookie类的方法 | 作用 |
---|---|
Cookie(String name,String value) | 指定键和值,创建一个Cookie对象,注:它没有无参的构造方法 |
HttpServletResponse对象的方法 | 作用 |
---|---|
addCookie(Cookie cookie) | 响应对象的方法,将服务器端创建好的Cookie对象发送给浏览器 |
在Servlet中创建一个Cookie(“user”,“NewBoy”),并且写到浏览器端去。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVPZPKSN-1598876514031)(assets/image-20200831094943676.png)]
package com.itheima.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; import java.io.PrintWriter; /** * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。 */ @WebServlet("/demo1") public class Demo1CreateCookieServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建一个Cookie对象 Cookie man = new Cookie("user", "NewBoy"); //2.使用响应对象发送给浏览器 response.addCookie(man); //3.输出提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("向浏览器发送了一个Cookie信息"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-brCtgsC9-1598876514037)(assets/image-20200831094931257.png)]
如何创建Cookie:
new Cookie("键","值") 键和值都是String类型
如何写入Cookie:
response.addCookie(Cookie对象)
如何设置Cookie的过期时间
在默认的情况下,只要浏览器关闭,Cookie会失效,不会永久保存下来
Cookie的方法 | 说明 |
---|---|
void setMaxAge(int expiry) | 设置Cookie保存的时间,单位是秒。 正整数:以秒为单位设置Cookie过期的时间 零:表示删除Cookie 负整数:无效,与没有设置的效果一样,浏览器关闭就失效 |
在写入Cookie之前先设置Cookie过期的时间,设置为10分钟以后过期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BhGnjn4E-1598876514041)(assets/image-20200831095741950.png)]
package com.itheima.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; import java.io.PrintWriter; /** * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。 */ @WebServlet("/demo1") public class Demo1CreateCookieServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建一个Cookie对象 Cookie man = new Cookie("user", "NewBoy"); //1.5 在要发送给浏览器之前设置过期时间 man.setMaxAge(60 * 10); //设置为10分钟 //2.使用响应对象发送给浏览器 response.addCookie(man); //3.输出提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("向浏览器发送了一个Cookie信息"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KwzbBsqf-1598876514045)(assets/image-20200831095822549.png)]
如何设置Cookie过期的时间?
setMaxAge()
参数是正,负,0分别表示什么意思?
如何从浏览器读取Cookie的信息到服务器
HttpServletRequest对象 | 作用 |
---|---|
Cookie[] getCookies() | 获取浏览器发送过来的所有的Cookie对象,返回Cookie数组 |
Cookie的方法 | 作用 |
---|---|
String getName() | 获取Cookie的键 |
String getValue() | 获取Cookie的值 |
写入
package com.itheima.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; import java.io.PrintWriter; /** * 在Servlet中创建一个user=NewBoy,并且写到浏览器端去。 */ @WebServlet("/demo1") public class Demo1CreateCookieServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建一个Cookie对象 Cookie man = new Cookie("user", "NewBoy"); //1.5 在要发送给浏览器之前设置过期时间 man.setMaxAge(60 * 10); //设置为10分钟 //2.使用响应对象发送给浏览器 response.addCookie(man); //再创建一个Cookie对象 Cookie age = new Cookie("age", "22"); age.setMaxAge(60 * 5); //设置为5分钟 response.addCookie(age); //3.输出提示信息 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("向浏览器发送了两个Cookie信息"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
读取
package com.itheima.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; import java.io.PrintWriter; /** * 读取所有的Cookie信息并且显示 */ @WebServlet("/demo2") public class Demo2ReadCookiesServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //1.通过请求对象的方法读取所有的Cookie数组 Cookie[] cookies = request.getCookies(); //2.要判断一个数组是否为空,如果浏览器端没有Cookie,会返回空 if (cookies == null) { out.print("浏览器端没有Cookie信息"); } else { //遍历每个Cookie对象 for (Cookie cookie : cookies) { //获取cookie的键和值 String name = cookie.getName(); String value = cookie.getValue(); out.print("Cookie的名字:" + name + ",值:" + value + "<hr/>"); } } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
响应头
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QJvMElZe-1598876514049)(assets/image-20200831100817748.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7SqlBWQk-1598876514052)(assets/image-20200831101439608.png)]
HttpServletRequest对象 | 作用 |
---|---|
Cookie[ ] getCookies() | 获取浏览器端所有的Cookie对象,返回Cookie的数组 |
Cookie类的方法 | 作用 |
---|---|
String getName() | 获取Cookie的名字 |
String getValue() | 获取Cookie的值 |
Cookie设置路径的方法 | 功能 |
---|---|
void setPath(路径) | 只有访问这个路径或它的子路径,浏览器才会发送Cookie的信息给服务器。 如果没有设置,默认是当前项目的访问地址 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39XMJ6Zj-1598876514053)(assets/image-20200831102133255.png)]
创建一个Cookie,设置过期时间,设置Cookie的访问路径
响应头
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8oQOJHxl-1598876514055)(assets/image-20200831102603105.png)]
package com.itheima.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; import java.io.PrintWriter; @WebServlet("/demo3") public class Demo3PathServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("保存了用户名在Cookie中"); Cookie username = new Cookie("username", "Rose"); username.setMaxAge(60 * 60 * 24 * 7); //设置过期的时间是一周 //设置它的访问路径, getContextPath()当前项目的访问地址 username.setPath(request.getContextPath() + "/login.html"); response.addCookie(username); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
只在访问login.html浏览器才会将Cookie的数据发送给服务器
如果访问路径是setPath("/day-cookie"),以下路径浏览器会发送Cookie给服务器?
访问地址 | 会不会发送Cookie给服务器 |
---|---|
http://localhost:8080/day-cookie/ | 会,因为路径匹配 |
http://localhost:8080/day-cookie/aa/bb | 会,因为访问的是子路径 |
http://localhost:8080/day/ | 不会,路径不匹配 |
http://localhost:8080/ | 不会,访问父路径 |
学习删除Cookie的方法
Cookie的删除 | 说明 |
---|---|
setMaxAge(0) | 删除一个Cookie |
删除指定的Cookie信息,注意Cookie的访问路径要相同
package com.itheima.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; import java.io.PrintWriter; @WebServlet("/demo4") public class Demo4DeleteServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建一个同名的Cookie Cookie cookie = new Cookie("user", null); //2.设置过期的时间为0,表示删除Cookie cookie.setMaxAge(0); //注:访问地址也要一样 cookie.setPath(request.getContextPath()); //默认是这个 //3.发送到浏览器端 response.addCookie(cookie); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("Cookie被删除"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
删除Cookie使用哪个方法?setMaxAge(0)
编写一个工具类,用于读取Cookie指定键的值。如果键不存在,则返回null。如果存在就返回值
工具类
package com.itheima.utils; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; /** * 工具类 * 用于读取Cookie指定键的值 * 如果键不存在,则返回null * 如果存在就返回值 */ public class CookieUtils { /** * 通过Cookie的键,获取值 * @param request 请求对象 * @param name cookie的键 * @return cookie的值,如果没有返回null */ public static String getCookieValue(HttpServletRequest request, String name) { //1.通过请求对象的方法读取所有的Cookie数组 Cookie[] cookies = request.getCookies(); //2.要判断一个数组是否为空,如果浏览器端没有Cookie,会返回空 if (cookies != null) { //遍历每个Cookie对象 for (Cookie cookie : cookies) { //获取cookie的键和值 String key = cookie.getName(); String value = cookie.getValue(); //比较name和key是否相等 if (key.equals(name)) { return value; } } } //没有找到返回null return null; } }
工具类的使用
package com.itheima.servlet; import com.itheima.utils.CookieUtils; 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; import java.io.PrintWriter; @WebServlet("/demo5") public class Demo5UseUtilsServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用工具类获取一个Cookie的值 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //调用工具类 String age = CookieUtils.getCookieValue(request, "age"); out.print("Cookie中age的值是:" + age); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
能够使用Cookie保存用户名和密码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fIvwRd41-1598876514057)(assets/1568899204362.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcu6CpCX-1598876514059)(assets/image-20200831112951460.png)]
LoginServlet
package com.itheima.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("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 得到用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //2. 判断是否登录成功 if ("admin".equals(username) && "123".equals(password)) { //3. 如果登录成功,判断是否勾了记住我 String remember = request.getParameter("remember"); //4. 如果勾了 if (remember != null) { //创建Cookie保存用户名和密码 Cookie cname = new Cookie("username", username); cname.setMaxAge(60 * 60 * 24 * 30); //保存1个月 cname.setPath(request.getContextPath() + "/login.html"); //设置访问路径 //5. 发送Cookie到浏览器端 response.addCookie(cname); Cookie cpass = new Cookie("password", password); cpass.setMaxAge(60 * 60 * 24 * 30); //保存1个月 cpass.setPath(request.getContextPath() + "/login.html"); //设置访问路径 response.addCookie(cpass); } //跳转到登录成功的页面 response.sendRedirect("success.html"); } else { //登录失败 response.sendRedirect("failure.html"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
浏览器端代码的实现
/** 工具方法,通过名字得到值,如果没有这个键就返回null */ function getCookieValue(name) { //这个属性可以读取浏览器端所有的cookies let cookies = document.cookie; //username=admin; password=123 密码前面有空格 //按;和空格拆分 let strings = cookies.split("; "); //遍历数组 for (let string of strings) { //username=admin //按等号进行拆分 let arr = string.split("="); //arr[0]=username键 arr[1]=admin值 let key = arr[0]; //键 let value = arr[1]; //值 //如果key与name相等表示找到 if (key == name) { return value; } } //最后返回null return null; }
login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>用户登录</title> <!--导入js文件--> <script src="js/commons.js"></script> </head> <body> <h2>用户登录</h2> <form action="login" method="post" id="loginForm"> <table> <tr> <td width="60">用户名</td> <td><input type="text" name="username" id="username"/></td> </tr> <tr> <td>密码</td> <td><input type="password" name="password" id="password"/></td> </tr> <tr> <td>记住我</td> <!--没有value属性的前提下,点中它的值是on,如果没有选中是没有值的 --> <td><input type="checkbox" name="remember"/></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="登录"/></td> </tr> </table> </form> <script type="text/javascript"> //当前页面加载完毕,从cookie中读取用户名和密码的信息 window.onload = function () { let username = getCookieValue("username"); let password = getCookieValue("password"); //用户名和密码都不能为空才提交数据给服务器 if (username!=null && password!=null) { //把用户名和密码赋值给两个文本框 document.getElementById("username").value = username; document.getElementById("password").value = password; //提交表单 document.getElementById("loginForm").submit(); } } </script> </body> </html>
实现自动登录的思路
创建Cookie对象: new Cookie("键","值")
发送给浏览器:response.addCookie(Cookie对象)
获取浏览器发送回来的cookie: Cookie[] request.getCookies()
设置Cookie的过期时间:setMaxAge(秒),如果设置为0,表示删除
设置Cookie的访问路径:setPath(/路径)
获取Cookie的名字和值:getName() getValue()
如何得到会话对象
学习HttpSession接口中常用的方法
在服务器端用的最多的就是会话域对象
HttpServletRequest创建会话的方法 | 描述 |
---|---|
HttpSession request.getSession() | 通过请求对象获取一个会话对象 |
用户第一次访问,并且调用上面的getSession()方法就创建一个会话对象,并且会分配会话ID给这个用户。
如果第二次以后访问,就会返回第一次创建的同一个会话。每个用户只对应一个会话对象。
org.apache.catalina.session.StandardSessionFacade@4105c137
public class StandardSessionFacade implements HttpSession
会话对象由Tomcat实现,并且由Tomcat实例化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FtsDZwz2-1598876514125)(assets/image-20200831145040455.png)]
package com.itheima.servlet; 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; import java.io.PrintWriter; import java.sql.Timestamp; @WebServlet("/demo1") public class Demo1SessionServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //创建一个会话对象 HttpSession session = request.getSession(); out.print("会话对象是:" + session + "<br/>"); //每个用户都有一个唯一的会话ID,格式是:32位的十六进制数 out.print("会话的ID是:" + session.getId() + "<hr/>"); //时间戳:java.sql.Timestamp(毫秒数) 构造方法传递的参数就是一个毫秒数 //获取会话创建的时间,返回的是一个long类型,1970年1月1日到这个时间之间相差的毫秒数 out.print("会话创建的时间:" + new Timestamp(session.getCreationTime()) + "<br/>"); //判断当前会话是否是新的会话 out.print("是否新的会话:" + session.isNew() + "<hr/>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
如何创建或获取一个会话对象? request.getSession(),第一次访问是创建会话,以后是获取会话。
HttpSession接口方法 | 作用 |
---|---|
String getId() | 获取会话的ID |
long getCreationTime() | 获取会话创建的时间,返回毫秒数 |
boolean isNew() | 判断是否是一个新的会话,第一次返回true,以后返回false |
与会话域有关的操作方法
请求域 < 会话域 < 上下文域
会话域用于:购物车,用户的权限验证
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHmNxF7d-1598876514126)(assets/1552450034543.png)]
通过1个案例学习上面方法的使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B8abt2Xv-1598876514128)(assets/1552450585063.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8sjqvow-1598876514130)(assets/1552450653128.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-91xXAgIU-1598876514131)(assets/1552450684828.png)]
package com.itheima.servlet; 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; import java.io.PrintWriter; @WebServlet("/demo2") public class Demo2SetServlet extends HttpServlet { //向会话域中添加键和值 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取会话对象 HttpSession session = request.getSession(); //2.调用方法向会话域中添加键和值 session.setAttribute("product", "娃娃"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("向会话域中添加了键和值"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
package com.itheima.servlet; 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; import java.io.PrintWriter; @WebServlet("/demo3") public class Demo3GetServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //1.获取会话对象,取的与demo2中是同一个会话对象 HttpSession session = request.getSession(); //2.从会话域中取出值 String product = (String) session.getAttribute("product"); //3.输出到页面 out.print("商品名字:" + product); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
为什么另一个浏览器得不到放在会话域中的值?
关键点是他们的会话ID不同
会话ID通过Cookie发送给浏览器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-khsapLLN-1598876514133)(assets/image-20200831151050787.png)]
浏览器将会话ID通过Cookie发送给服务器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHqjUcsl-1598876514134)(assets/image-20200831151134300.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w4nxfjhf-1598876514136)(assets/image-20200831150901798.png)]
如果浏览器关闭,服务器上的会话信息是否还存在?
还在,直到服务器上会话过期,默认是30分钟。
浏览器关闭以后,还能不能得到之前会话域中的信息?
正常是不能的
有没有可能让浏览器关闭还可以再访问服务器上没有过期的信息?
可以,手动将会话ID保存,并且设置过期时间
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/demo2") public class Demo2SetServlet extends HttpServlet { //向会话域中添加键和值 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取会话对象 HttpSession session = request.getSession(); //2.调用方法向会话域中添加键和值 session.setAttribute("product", "娃娃"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("向会话域中添加了键和值"); //手动创建一个Cookie的数据,键是JSESSIONID,值是会话的ID,并且设置过期的时间 Cookie cookie = new Cookie("JSESSIONID", session.getId()); //设置过期的时间 cookie.setMaxAge(60 * 30); //添加到浏览器端 response.addCookie(cookie); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59yginKr-1598876514138)(assets/image-20200831152155424.png)]
服务器与浏览器之间是如何将会话ID发送给对方的
通过Cookie发送
学习设置会话过期的三种方式
session.setMaxInactiveInterval(秒);
package com.itheima.servlet; 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; import java.io.PrintWriter; /** * 获取会话过期的时间间隔 */ @WebServlet("/demo4") public class Demo4IntervalServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //1.获取会话对象 HttpSession session = request.getSession(); //设置过期的时间是10秒 //session.setMaxInactiveInterval(10); //2.获取会话过期的时间间隔,单位是秒。非活动:没有新的请求 //如果设置为10秒,第9秒的时候有一次请求,服务器就会重新计时10秒 int interval = session.getMaxInactiveInterval(); out.print("会话过期的时间是:" + interval + "<hr/>"); out.print("会话ID是:" + session.getId() + "<br/>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
<!--会话的配置-->
<session-config>
<!--过期的时间: 单位是分-->
<session-timeout>5</session-timeout>
</session-config>
疑问:如果同时使用代码和配置的方式以哪个为准?
以代码为准,后面的代码会覆盖前面的配置
应用场景:用于用户退出或注销,让会话马上过期。会释放当前用户会话域中所有资源
session.invalidate();
修改会话过期的时间有哪三种方式?
session.setMaxInactiveInterval(秒)
在web.xml中配置
<session-config>
<session-timeout>分钟</session-timeout>
</session-config>
马上失效:session.invalidate()
浏览器不会把会话ID再发送给服务器,导致服务器上会话数据读取不出来。
不能通过Cookie来发送会话ID,在地址栏上发送会话id
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hWCcSKPM-1598876514141)(assets/image-20200831155832231.png)]
什么是URL重写:
响应对象的方法 | 说明 |
---|---|
response.encodeRedirectURL(path) | 在要跳转过去的地址栏后面加上会话id |
重写前的URL:
demo3
重写后的URL:
demo3;jsessionid=5933A9F542C0938DDE196E3DF80C0C82
//URL重写:在地址后面加上会话的ID,使用分号隔开
String url = response.encodeRedirectURL("demo3");
//输出到浏览器上
out.println("<a href='" + url + "'>跳转到demo3</a>");
使用URL重写以后,不同的浏览器可不可以访问其它浏览器的会话数据?
理论上是可以访问的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OkrSf0Lo-1598876514145)(assets/image-20200831160506165.png)]
方法 | 说明 |
---|---|
response.encodeRedirectURL(path) | 将会话ID添加到URL的后面,使用分号隔开 |
登录验证码环境的搭建
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2OGzsFOe-1598876514148)(assets/image-20200831161318298.png)]
登录成功后将用户信息保存到会话域中,并且跳转到WelcomeServlet,然后在WeclcomeServlet中读取用户信息,显示欢迎信息。在WelcomeServlet上显示退出的链接,点退出,注销会话信息。
<div class="col-sm-3">
<!--指定为servlet,鼠标移上去变成手-->
<img src="code" style="cursor: pointer" title="看不清换一张" id="picCode"/>
<script type="text/javascript">
//编写图片的点击事件
document.getElementById("picCode").onclick = function () {
//修改图片的src,并且指定一个变化的参数
this.src = "code?n=" + new Date().getTime();
};
</script>
</div>
package com.itheima.servlet; import javax.imageio.ImageIO; 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.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/code") public class PicCodeServlet extends HttpServlet { //随机类 private Random random = new Random(); /** * 随机获取一种颜色 */ private Color getRandomColor() { //随机得到r,g,b的取值,范围是0~255 int r = random.nextInt(256); int g = random.nextInt(256); int b = random.nextInt(256); return new Color(r, g, b); //red红 green绿 blue蓝 } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置MIME类型 response.setContentType("image/jpeg"); //定义宽和高的值 int width = 90; int height = 30; //1. 创建一张图片,参数:宽,高,图片模式 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //获取画笔对象 Graphics graphics = image.getGraphics(); //整个图片填充白色 graphics.setColor(Color.WHITE); graphics.fillRect(0,0,width,height); //2. 随机绘制4个验证码 char[] arr = { 'A', 'B', 'C', 'D', 'N', 'E', 'W', 'b', 'o', 'y', '1', '2', '3', '4','5','6','7','8' }; //设置字体,字体对象有三个参数:字体名字,字体样式(加粗,斜体), 大小 graphics.setFont(new Font(Font.DIALOG_INPUT, Font.BOLD + Font.ITALIC, 19)); //创建一个StringBuilder StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { //随机获取1个索引号 int index = random.nextInt(arr.length); //随机获取字符数组的一个字符 char c = arr[index]; sb.append(c); //每个字符的颜色不同 graphics.setColor(getRandomColor()); //写字符,参数:文字内容,x,y坐标 (把字符转成字符串) graphics.drawString(String.valueOf(c),10+(i*20), 20); } //把验证码放在会话域中 HttpSession session = request.getSession(); //转成字符串以后放到会话域中 session.setAttribute("code", sb.toString()); System.out.println("生成的验证码是:" + sb); //3. 绘制8条干扰线 for (int i = 0; i < 8; i++) { //指定颜色 graphics.setColor(getRandomColor()); int x1 = random.nextInt(width); int y1 = random.nextInt(height); int x2 = random.nextInt(width); int y2 = random.nextInt(height); //画线,起点和终点 graphics.drawLine(x1,y1,x2,y2); } //4. 把图片输出到浏览器,参数:输出的图片对象,图片格式,响应输出流 ImageIO.write(image,"jpg", response.getOutputStream()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
实现登录的Servlet
package com.itheima.servlet; 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; import java.io.PrintWriter; @WebServlet("/login") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //1.判断验证码,验证码放在会话域中 HttpSession session = request.getSession(); //获取会话对象 String code = (String) session.getAttribute("code"); //从会话域中取出验证码 //获取用户提交的验证码 String vcode = request.getParameter("vcode"); //判断验证码是否正确,忽略大小写比较 if (vcode.equalsIgnoreCase(code)) { //2.判断用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); if ("admin".equals(username) && "123".equals(password)) { //把用户的信息保存在会话域中,这是一个标记,表示用户已经登录成功 session.setAttribute("username", username); //3.如果成功跳转到welcome response.sendRedirect("welcome"); } //用户名密码错误 else { out.print("<script>"); out.print("alert('用户名或密码错误');"); out.print("location.href='login.html';"); out.print("</script>"); } } //验证码错误 else { //使用脚本跳转,可以看到错误信息 out.print("<script>"); out.print("alert('验证码错误');"); out.print("location.href='login.html';"); out.print("</script>"); //4.如果失败跳转到login.html //response.sendRedirect("login.html"); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
package com.itheima.servlet; 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; import java.io.PrintWriter; /* 这个页面必须进行权限验证 原理:只要登录成功的用户,会话域中是有数据的,没有登录的用户,会话域中用户信息是空的 */ @WebServlet("/welcome") public class WelcomeServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); //获取会话域 HttpSession session = request.getSession(); //从会话域中取出用户的信息 String username = (String) session.getAttribute("username"); //表示没有登录 if (username == null) { //getRemoteAddr() 获取客户端的IP地址 System.out.println("拦截到了非法的用户:" + request.getRemoteAddr()); response.sendRedirect("login.html"); //后面的代码还会继续运行的 return; } //输出用户的信息 out.print("<h1>登录成功,欢迎您!" + username + "</h1>"); out.print("<a href='logout'>退出</a>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
package com.itheima.servlet; 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("/logout") public class LogoutServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.销毁会话 request.getSession().invalidate(); //2.重定向到登录页面 response.sendRedirect("login.html"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
能够说出会话的概念
创建:浏览器第一次访问,由服务器创建会话。
过程:浏览器与服务器之间的多次请求和响应
结束:浏览器关闭或服务器会话过期
能够说出cookie的概念
保存在: 浏览器端的硬盘中
键和值都是: 字符串类型,每个Cookie保存一个键值对
默认浏览器关闭: Cookie失效
能够创建、发送、接收、删除cookie
方法名 | 作用 |
---|---|
new Cookie(名字,值) | 创建一个Cookie对象 |
response.addCookie(Cookie cookie) | 把Cookie发送到浏览器写入 |
Cookie[] request.getCookies() | 获取浏览器端所有的Cookie对象数组 |
setMaxAge(0) | 删除Cookie |
能够说出cookie执行原理
能够说出session的概念
保存在: 服务器的内存中
键和值:键是字符串类型,值是Object类型
默认过期:30分钟
修改过期的时间:
能够获取session对象、添加、删除、获取session中的数据
方法名 | 作用 |
---|---|
request.getSession() | 第一次访问创建会话,以后是获取会话对象 |
session.setAttribute(“键”, 值) | 向会话域中添加键和值 |
session.getAttribute(“键”) | 从会话域中取出值 |
session.removeAttribute(“键”) | 删除键和值 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。