1会话技术简介
1.1存储客户端的状态
例如网站的购物系统,因为Http协议是无状态的,也就是说每个客户访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端的状态。
会话技术是帮助服务器记住客户端状态(区分客户端)的。
1.2会话技术
从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话。
注意是关闭浏览器,不是只关闭浏览器的标签。
会话技术就是记录这次会话中客户端的状态与数据的。
会话技术分为Cookie和Session:
Cookie:数据存储在客户端本地,减少服务器端的存储压力,安全性不好(例如在公共电脑访问,容易泄露信息),客户端可以清除cookie。
Session:将数据存储到服务器端,安全性相对好,但会增加服务器的压力。
两者结合起来使用最好。
2 Cookie技术
以响应头的形式发送给客户端,键值对方式存,不能存储中文,setHeader
请求头把值传给服务器,用getHeader获取
关注点:
1)服务器怎样将一个cookie写给客户端
2)服务器怎样获取客户端携带的cookie
2.1服务器端向客户端发送一个Cookie
1)创建Cookie对象
2)将Cookie中存储的信息发送到客户端
例:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向客户端发送Cookie //1创建Cookie对象 Cookie cookie=new Cookie("goods","vivo"); //2将Cookie中存储的信息发送到客户端 response.addCookie(cookie); }
访问 http://localhost:8080/20190112WEB/SendCookieServlet,抓包
再访问一次,
再访问http://localhost:8080/20190112WEB/index.jsp,还在
重新开一个标签,访问http://localhost:8080/20190112WEB/index.jsp,数据还在
关闭浏览器,再开,没有了
3)设置Cookie在客户端的持久化时间
cookie.setMaxAge(int seconds); ----时间秒
如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭cookie信息销毁(会话级别的cookie),
如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里
过期浏览器自动删除该cookie信息
例:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向客户端发送Cookie //1创建Cookie对象 Cookie cookie=new Cookie("goods","vivo"); //设置Cookie持久化时间 cookie.setMaxAge(120); //2将Cookie中存储的信息发送到客户端 response.addCookie(cookie); }
访问 http://localhost:8080/20190112WEB/SendCookieServlet,
再访问 http://localhost:8080/20190112WEB/index.jsp
关闭浏览器,再开,再访问http://localhost:8080/20190112WEB/index.jsp
4)设置Cookie的携带路径
cookie.setPath(String path); 相对路径
例:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //向客户端发送Cookie //1创建Cookie对象 Cookie cookie=new Cookie("goods","vivo"); //设置Cookie的携带路径 cookie.setPath("/20190112WEB"); //2将Cookie中存储的信息发送到客户端 response.addCookie(cookie); }
结果:
http://localhost:8080/20190112WEB/SendCookieServlet (有)
http://localhost:8080/20190112WEB/index.jsp (没有)
Tips:
1)只写项目路径/20190112WEB,那么就是访问该项目下所有资源时都携带
2)如果写 / ,那么是访问服务器上所有资源时携带(服务器上可能有多个项目)
3)如果不设置携带路径,那么该cookie信息会在访问产生该cookie的web资源所在的路径都携带cookie信息
(产生该cookie的web资源:http://localhost:8080/20190112WEB/SendCookieServlet
所在的路径:http://localhost:8080/20190112WEB/ )
例:
把web.xml改为:
结果:
(产生cookie)
(没有)
(有)
5)删除客户端的cookie
如果想删除客户端的已经存储的cookie信息,那么就使用同名同路径的持久化时间为0的cookie进行覆盖即可
例:
SendCookieServlet:
removeCookieServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //删除客户端的cookie //创建Cookie对象 Cookie cookie=new Cookie("goods", "vivo"); //设置Cookie的携带路径 cookie.setPath("/20190112WEB"); //设置Cookie持久化时间 cookie.setMaxAge(0); response.addCookie(cookie); }
依次访问:
http://localhost:8080/20190112WEB/SendCookieServlet(产生)
http://localhost:8080/20190112WEB/index.jsp(有)
http://localhost:8080/20190112WEB/removeCookieServlet
http://localhost:8080/20190112WEB/index.jsp(没有了)
2.2服务器端怎么接受客户端携带的Cookie
cookie信息是以请求头的方式发送到服务器端的。
1)通过request获得所有的Cookie:
2)遍历Cookie数组,通过Cookie的名称获得我们想要的Cookie
例:
getCookieServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取客户端携带的所有cookie数据 Cookie[] cookies=request.getCookies(); //通过cookie名称得到相应的值 if(cookies!=null){ for(Cookie c:cookies){ String cookName=c.getName(); if(cookName.equals("goods")){ String cookValue=c.getValue(); System.out.println(cookValue); } } } }
访问:
http://localhost:8080/20190112WEB/SendCookieServlet
http://localhost:8080/20190112WEB/getCookieServlet
注意必须在cookie携带路径上才能获取到
2.3示例:记录上一次访问时间
判断cookie为空,则为第一次。存一个cookie记录时间
第二次,携带过来时间,再存一个时间
AccessServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取当前时间 Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currentTime=sdf.format(date);//日期对象转字符串 //创建cookie Cookie cookie=new Cookie("lastTime", currentTime); cookie.setMaxAge(60*10); //10分钟 //发送cookie response.addCookie(cookie); //获得客户端携带cookie---上次访问时间 Cookie[] cookies=request.getCookies(); String lastTime=null; //上次访问时间 if(cookies!=null){ for(Cookie c:cookies){ if(c.getName().equals("lastTime")){ lastTime=c.getValue(); //获取值 } } } //解决中文乱码 response.setContentType("text/html;charset=utf-8"); if(lastTime==null){ //第一次访问 response.getWriter().write("您是第一次访问"); }else{ response.getWriter().write("您上次访问的时间为"+lastTime); } }
3 Session技术
Session技术是将数据存储在服务器端的技术,会为每个客户端都创建一块内存空间存储客户的数据,
但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间。
所以Session的实现是基于Cookie的,Session需要借助Cookie存储客户的唯一性标识JSESSIONID。
关注三个问题:
1)怎样创建专属于客户端的session区域
2)怎样向session中存取数据
3)session生命周期
发送jsessionid和根据该编号找session域由客户端自己完成,不用关注
3.1获得Session对象
HttpSession session = request.getSession();
此方法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session 对象会创建一个新的Session返回;
如果已经有了属于该会话的Session直接将已有的Session返回(实质就是根据JSESSIONID判断该客户端是否在服务器上已经存在session了)
例:
Servlet01:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取session对象(开辟一块session区域) HttpSession session=request.getSession(); //获取Jsessionid String id=session.getId(); response.getWriter().write("Jsessionid:"+id); //写到前台 }
刷新,id也不变
关闭浏览器后,再开,则变化了,因为客户端的jsessionid随着会话结束而消失,所以又开辟了一块新的session。
3.2怎样向session中存取数据
session也是一个域对象。(域对象就是在服务器上的存储对象,所以cookie不是域对象。)
三个方法:
session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);
例:
Servlet01:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取session对象(开辟一块session区域) HttpSession session=request.getSession(); //存储数据 session.setAttribute("goods", "iphone"); //获取Jsessionid String id=session.getId(); response.getWriter().write("Jsessionid:"+id); //写到前台 }
Servlet02:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取session对象 HttpSession session=request.getSession(); //和Servlet01那里的是同一个对象 //取值 String value=(String) session.getAttribute("goods"); //强转 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("goods:"+value); }
先访问Servlet01,再Servlet02
换个浏览器(或关了重开),只访问Servlet02
3.3持久化存储jsessionid
利用cookie
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取session对象 HttpSession session=request.getSession(); session.setAttribute("name", "小野猪"); String id=session.getId(); //手动创建一个存储Jsessionid的cookie对象 Cookie cookie=new Cookie("JSESSIONID", id); cookie.setPath("/20190112WEB"); cookie.setMaxAge(60*3); //发送cookie对象 response.addCookie(cookie); response.getWriter().write("JSESSIONID:"+id); }
关闭浏览器重开,还在。
3.4 Session对象的生命周期
创建:第一次执行request.getSession()时创建
销毁:
1)服务器(正常/非正常)关闭时
2)session过期/失效(默认30分钟)
时间的起算点从不操作服务器端的资源开始计时
可以在web.xml中进行配置(以覆盖服务器上的时间)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
3)手动销毁session
session.invalidate();( 一般不会销毁)
作用范围:
默认在一次会话中(在一次会话中任何资源公用一个session对象)
4 验证码验证
(之前做的验证码例子和登录的例子)
//获取用户输入验证码String code=request.getParameter("code");//获取session中正确的验证码 String scode=(String) request.getSession().getAttribute("checkcode_session"); if(!code.equals(scode)){ request.setAttribute("loginInfo", "验证码输入错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); return; //结束方法,下方代码不再执行 }
重点总结:
1 Cookie
1)发送cookie
获得对象:Cookie cookie = new Cookie(name,value)
持久化时间:cookie.setMaxAge(秒)
携带路径:cookie.setPath()
发送:response.addCookie(cookie)
2)获得cookie
Cookie[] cookies = request.getCookies();
cookie.getName();
cookie.getValue();
2 Session
1)获得对象:HttpSession session = request.getSession();
获得JSESSIONID:session.getId();
2)存取数据:
setAttribute(name,value);
getAttribute(name);
3)生命周期
创建:第一次指定request.getSession();
销毁:服务器关闭、session失效/过期、手动session.invalidate();
作用范围:默认一次会话中
3两个实例:记录上一次访问时间和验证码验证