1.Cookie
1.1 什么是Cookie
- 服务器通知客户端保存键值对的一种技术,是由
servlet
发送到Web浏览器的少量信息,然后发送回服务器- 客户端有了Cookie 后,每次请求都发送给服务器
- 每个 Cookie 的大小不能超过
4kb
tips:
- 为了下面章节的展现,基本页面和代码如下:
// BaseServlet类 public abstract class BaseServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 解决相应中文乱码问题 resp.setContentType("text/html; charset=UTF-8"); String action = req.getParameter("action"); try { // 获取action业务鉴别字符串,获取相应的业务方法反射对象 Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class); // 调用目标业务方法 method.invoke(this, req, resp); } catch (Exception e) { e.printStackTrace(); } } }
// cookie.html // 加上了<base href="http://localhost:8080/book/"> <ul> // 这里发送给cookieServlet是get请求,所以在BaseServlet中实现的是doGet方法 // 请求已发送就会去调用cookieServlet的父类BaseServlet的doGet方法,然后通过反射进行action中相应方法的调用 <li><a href="cookieServlet?action=createCookie" target="target">Cookie的创建</a></li> <li><a href="cookieServlet?action=getCookie" target="target">Cookie的获取</a></li> <li><a href="cookieServlet?action=updateCookie" target="target">Cookie值的修改</a></li> <li>Cookie的存活周期</li> <li> <ul> <li><a href="cookieServlet?action=defaultLife" target="target">Cookie的默认存活时间(会话) </a> </li> <li><a href="cookieServlet?action=deleteNow" target="target">Cookie立即删除</a></li> <li><a href="cookieServlet?action=life3600" target="target">Cookie存活3600秒(1小时)</a> </li> </ul> </li> <li><a href="cookieServlet?action=testPath" target="target">Cookie的路径设置</a></li> <li><a href="" target="target">Cookie的用户免登录练习</a></li> </ul>
1.2 服务器创建cookie
- 创建cookie的过程:
public class cookieServlet extends BaseServlet { protected void createCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.创建cookie对象 Cookie cookie = new Cookie("key1", "value1"); // 2. 通知客户端保存cookie resp.addCookie(cookie); resp.getWriter().write("cookie创建成功"); // cookie.html的框中显示cookie创建成功 } }
1.3 服务器获取cookie
- 获取cookie过程:
protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie[] cookies = req.getCookies(); for (Cookie cookie : cookies) { // 返回cookie的名称和值 // cookie.html的框中显示所有cookie的信息 resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "]"); } }
1.4 服务器修改Cookie值
protected void updateCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1.先创建一个要修改的同名的Cookie对象,然后赋予新的值 Cookie cookie = new Cookie("key1", "newValue"); // 2.通知客户端保存修改 resp.addCookie(cookie); // cookie.html的框中显示该输出 resp.getWriter().write("cookie修改成功"); // 也可以先根据key先找到要修改的cookie,然后调用setValue()方法赋于新的Cookie值 }
1.5 Cookie的生命控制
- 生命控制:如何管理Cookie 什么时候被销毁(删除),使用
setMaxAge()
方法进行控制,不同参数表示不同含义:
- 正数:表示在指定的秒数后过期
- 负数:表示浏览器一关,Cookie 就会被删除(默认值是-1)
- 零:表示马上删除Cookie
protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("defalutLife", "defaultLife"); cookie.setMaxAge(-1); //设置存活时间 resp.addCookie(cookie); } protected void life3600(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("life3600", "life3600"); cookie.setMaxAge(60 * 60); // 设置 Cookie 一小时之后被删除 resp.addCookie(cookie); resp.getWriter().write("已经创建了一个存活一小时的 Cookie"); } protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 先找到你要删除的 Cookie 对象 Cookie cookie = CookieUtils.findCookie("key4", req.getCookies()); if (cookie != null) { // 调用 setMaxAge(0); cookie.setMaxAge(0); // 表示马上删除,都不需要等待浏览器关闭 // 调用 response.addCookie(cookie); resp.addCookie(cookie); resp.getWriter().write("key4 的 Cookie 已经被删除"); } }
1.6 设置Cookie有效路径
- Cookie的
path
属性可以有效的过滤哪些Cookie可以发送给服务器,哪些不发。该属性是通过请求的地址来进行有效的过滤:
protected void testPath(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("path1", "path1"); // getContextPath() ===>>>> 得到工程路径 cookie.setPath( req.getContextPath() + "/abc" ); // ===>>>> /工程路径/abc resp.addCookie(cookie); resp.getWriter().write("创建了一个带有Path路径的 Cookie"); }
此时输入http://localhost:8080/book/cookie.html点击
cookie的路径设置
后,再按F12查看Application
的内容时是没有path1
这个cookie的,但是可以在检查Network
发送给服务器的cookie时可以看见该cookie:
当输入http://localhost:8080/book/abc/cookie.html时便可以查询到返回给客户端的该cookie:
1.7 Cookie实践
- 实现免输入用户名登录:
// login.html <body> <form action="http://localhost:8080/book/loginServletCookie" method="get"> // value用于显示保存在客户端的cookie的值(保存在客户端的cookie用于显示,而在请求头中的cookie用于发送给服务器) 用户名:<input type="text" name="username" value="${cookie.username.value}"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="登录"> </form> </body>
public class LoginServletCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); if ("psj".equals(username) && "123456".equals(password)) { // 登录 成功 Cookie cookie = new Cookie("username", username); cookie.setMaxAge(60 * 60 * 24 * 7);//当前Cookie一周内有效 resp.addCookie(cookie); System.out.println("登录成功"); } else { // 登录 失败 System.out.println("登录失败"); } } }
第一次输入http://localhost:8080/book/login.jsp后,键入用户名和密码,此时输出相应的登录信息。第二次输入相同网址时,显示在页面的表单中的用户名会自动显示上一次输入的
psj
。因为第二次输入网址后,客户端发送给服务器的请求头中会有第一次请求服务器返回的cookie:
2.Session
2.1 什么是 Session
- Session是一个接口(HttpSession)
- 一个会话,它是用来维护一个客户端和服务器之间关联的一种技术
- 每个客户端都有自己的一个Session会话
- 经常被用来保存用户登录之后的信息
- Cookie保存在客户端,而Session保存在服务器端
tips:
- 为了下面章节的展现,基本页面和代码如下:
// session.html // 加上了<base href="http://localhost:8080/book/"> <body> <iframe name="target" width="500" height="500" style="float: left;"></iframe> <div style="float: left;"> <ul> <li><a href="sessionServlet?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li> <li><a href="sessionServlet?action=setAttribute" target="target">Session域数据的存储</a></li> <li><a href="sessionServlet?action=getAttribute" target="target">Session域数据的获取</a></li> <li>Session的存活</li> <li> <ul> <li><a href="sessionServlet?action=defaultLife" target="target">Session的默认超时及配置</a></li> <li><a href="sessionServlet?action=life3" target="target">Session3秒超时销毁</a></li> <li><a href="sessionServlet?action=deleteNow" target="target">Session马上销毁</a></li> </ul> </li> <li><a href="" target="target">浏览器和Session绑定的原理</a></li> </ul> </div> </body>
// BaseServlet类 public abstract class BaseServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 和Cookie章节一致 }
2.2 Session创建和获取
- 创建和获取使用的API都是
request.getSession()
:
- 第一次调用时是创建Session
- 再次调用时是获取前面创建好的Session
- 要区分是刚创建的还是之前创建的,可以使用
isNew()
方法判断- 每个会话都有一个身份证号(ID值),该ID是唯一的,可以通过
getId()
方法查看protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 创建和获取Session会话对象 HttpSession session = req.getSession(); // 判断当前Session会话,是否是新创建出来的 boolean isNew = session.isNew(); // 获取Session会话的唯一标识id String id = session.getId(); resp.getWriter().write("得到的Session,它的id是:" + id + " <br /> "); // 点击Session的创建和获取(id号、是否为新创建)打印true,再次点击时打印false resp.getWriter().write("这个Session是否是新创建的:" + isNew + " <br /> "); }
2.3 Session域数据的存取
// 往Session中保存数据 protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 点击Session域数据的存储打印已经往Session中保存了数据 req.getSession().setAttribute("key1", "value1"); resp.getWriter().write("已经往Session中保存了数据"); } // 获取Session域中的数据 protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Object attribute = req.getSession().getAttribute("key1"); // 点击Session域数据的获取打印从Session中获取出key1的数据是value1 resp.getWriter().write("从Session中获取出key1的数据是:" + attribute); }
2.4 Session 生命周期控制
setMaxInactiveInterval(int interval)
:设置 Session 的超时时间(以秒为单位),超过指定的时长,Session就会被销毁
interval
为正数的时候,设定 Session 的超时时长。interval
为负数表示永不超时(极少使用)getMaxInactiveInterval()
:获取Session的超时时间invalidate()
:让当前Session会话马上超时无效protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取了Session的默认超时时长 int maxInactiveInterval = req.getSession().getMaxInactiveInterval(); // 点击Session的默认超时及配置后打印1800秒 resp.getWriter().write("Session的默认超时时长为:" + maxInactiveInterval + " 秒 "); } protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 先获取Session对象 HttpSession session = req.getSession(); // 设置当前Session3秒后超时 session.setMaxInactiveInterval(3); // 点击Session3秒超时销毁后当前Session已经设置为3秒后超时 resp.getWriter().write("当前Session已经设置为3秒后超时"); } protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 先获取Session对象 HttpSession session = req.getSession(); // 让Session会话马上超时 session.invalidate(); // 点击Session马上销毁后打印Session已经设置为超时(无效) resp.getWriter().write("Session已经设置为超时(无效)"); }
tips:
- 为在 Tomcat 服务器的配置文件
web.xml
中默认有以下的配置,在当前项目的web.xml
文件中可以添加该配置对该项目的所有Session进行修改:<session-config> <session-timeout>30</session-timeout> </session-config>
- Session的超时是指两次请求之间的最大间隔时长。假设调用
life3
方法设置了超时时长为3秒,意味着当前Session在3秒后会被销毁,即点击Session的创建和获取(id号、是否为新创建)
应该由false变为true(变true的原因是点击后调用了req.getSession()
创建了一个新Session),但实际上连续点击后还是显示false。因为连续点击时每次请求的时长小于3秒,并没有超时,所以原来的Session没有销毁,如果等一段时间后点击才会显示true
2.5 浏览器和Session之间的关联
- Session 技术的底层其实是基于 Cookie 技术来实现的。这也就解释了为什么即使给Session设置了很长的超时时长后,一关闭浏览器Session还是会被销毁,因为浏览器一关,Cookie 就会被删除(默认,可以使用
setMaxAge()
方法进行控制),没有了该Cookie意味着无法携带原来的SessionID
给服务器去查找,相当于被删除