3.9、会话追踪技术
想象一个应用:我们打开一个购物网站,去将一件商品加入到购物车中,这就需要每个人都要有一个自己的购物车。但是HTTP是无状态的,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。也就是说我们将一个商品放入购物车后,再次访问的时候,系统就不知道是谁将商品放入了那个购物车了。
为了能跟踪用户的状态,在WEB中产生了会话技术,其中客户端和服务器各自给出了一个解决的方案。客户端:Cookie技术。服务端:Session技术。
它们是一种会话(用户打开浏览器访问一个项目的多个资源,直到关闭浏览器或超过一定时间为一次会话)追踪技术,作用是为了在一定的时限内用户和服务端可以一直处在交互的状态。
3.9.1 Cookie
Cookie是当用户通过 HTTP 协议访问一个服务器的时候,因为HTTP是无状态的,所以当服务器需要记录用户的状态时候,会将一些Key/Value 键值对返回给客户端浏览器,客户端在本地的文件将这些文本信息储存下来,当浏览器再次访问该服务器时,会把相应的cookie信息一起发给服务器,服务器根据cookie判断用户的状态信息。
一般有些页面会有记住密码的选项,当我们选中后,用户名和密码会为我们保存一定的时间,这种就是cookie技术。
来自javax.servlet.http.Cookie,cookie是一种客户端技术,它是为了解决HTTP无状态的问题,相当于给客户端一个通行证,当用户携带通行证访问服务器时,服务器就能根据通行证知道访问者是谁。它有以下特点:
- 它将一些数据保存到本地中,这也导致cookie保存的数据
安全性不高
,所以保存一些密码等重要数据时,尽可能使用加密技术(MD5加密等)。 - 一个cookie只能保存一个信息 (一个键对应一个值)
- cookie读取的是文件,它每次存储的数据量有限(4k),不能将过多的内容存储cookie中;
- 浏览器通常只允许一个站点最多存放20个cookie。
- 每个浏览器的cookie上限300个。
- Cookie具有不可跨域名性。不同浏览器有不同的cookie
Java中把Cookie封装 成了javax.servlet.http.Cookie类。每一个Cookie都是一个该类的对象。服务端通过此类操作客户端的Cookie。
-
Cookie对象
1、用request获取客户端的cookie:Cookie[] getCookies() 用于获取客户端提交的 Cookie。 2、构造方法创建新cookie:public Cookie(String name, String value) name 名,value为值 3、用response将新cookie响应给客户端:addCookie(Cookie cookie)
-
Cookie对象的常用方法
1、获取cookie的key:cookie.Name() 2、获取cookie的valie:cookie.getValue() 3、获取 cookie 有效期,以秒为单位,-1表明cookie会活到浏览器关闭为止,0为删除:cookie.getMaxAge() 4、设置 cookie 有效期:cookie.setMaxAge(int expiry) 5、设置cookie的value:cookie.setValue(String newValue) 6、获取cookie的域名:getDomain() 7、设置cookie域名:setDomain(String pattern) 8、设置cookie路径:setPath(String uri) 9、获取cookie路径:getPath() 10、是否要运用安全协议:setSecure(boolean flag) 11、浏览器只通过安全协议发送 Cookie,则返回 true,否则返回 false:getSecure() 12、设置注释描述 cookie 的目的 setComment(String) 13、返回描述 cookie 目的的注释:getComment() 14、获取 Cookie 遵守的协议版本: getVersion()
Cookie默认情况下是一个会话级别的 Cookie,用户退出浏览器就被删除。如果希望将 Cookie 存到磁盘上,则需要调用 setMaxAge(int maxAge) 方法设置最大有效时间,以秒为单位。
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//获取所有cookie
Cookie[] cookies = request.getCookies();
Cookie cookie = null;
//获取cookie,最后一次访问的时间
if(cookies != null){
for (Cookie c : cookies){
//获取cookie的名字和值
String name = "lastTime";
if(name.equals(c.getName())){
cookie = c;
}
}
}
//判断是否是第一次访问
if(cookie == null){
response.getWriter().write("这是第一次登录");
}else {
String value = cookie.getValue();
response.getWriter().write("上次登录时间:"+ URLDecoder.decode(value)
+"<br/><a href='/RemoveCookieServlet' > 清除COOKIE</a>");
}
// 记录当前的时间
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//设置Cookie
Cookie c = new Cookie("lastTime", URLEncoder.encode(sdf.format(date)));
// 设置有效时间为一天
c.setMaxAge(60 * 60 * 24);
// 设置此cookie的有效路径
c.setPath("/ReqAndResTestServlet");
// 写到浏览器中保存
response.addCookie(c);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取cookie
Cookie cookie = new Cookie("lastTime", "");
// 设置有效时间为0,删除cookie
cookie.setMaxAge(0);
// 设置有效路径,必须与要删除的Cookie的路径一致
cookie.setPath("/ReqAndResTestServlet");
// 回写
response.addCookie(cookie);
// 重定向
response.sendRedirect("/ReqAndResTestServlet");
}
3.9.2 Session
Session和Cookie一样是会话追踪技术,Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
HTTP是无状态协议,这意味着每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会记录下先前客户端请求的任何信息。这在实际应用中会产生很多不必要的操作,所以使用session来解决这一问题,JSP利用servlet提供的HttpSession接口来识别一个用户,存储这个用户的所有访问信息。
session是一个全局对象,服务器为每一个用户创建一个session对象,拥有唯一的sessionId,该用户访问站点内所有资源使用的都是同一个session对象,session里保存的数据默认的存在时间为30分钟。
Session最多的使用就是用户登录上,使用Seesion保存此次登录信息,在设定时间内,我们在访问网站内的任何资源时都会显示我们的用户已登录的状态,这就是把登陆的信息保存在了session中,在session数据的有效期内我们就不需要再登陆了。
- 当客户端第一次访问时,服务器会创建一个 Session 对象,并为该 Session 对象分配一个唯一的 SessionID(用来标识这个 Session 对象);
- 服务器将 SessionID 以 Cookie(Cookie 名称为:“JSESSIONID”,值为 SessionID 的值)的形式发送给客户端浏览器;
- 客户端浏览器再次发送 HTTP 请求时,会将携带 SessionID 的 Cookie 随请求一起发送给服务器;
- 服务器从请求中读取 SessionID,然后根据 SessionID 找到对应的 Session 对象。
//获取session对象
HttpSession session=request.getSession();
序号 | 方法 | 描述 |
---|---|---|
1 | Object getAttribute(String name) | 返回session对象中与指定名称绑定的值,如果不存在则返回null |
2 | Enumeration getAttributeNames() | 返回session对象中所有的对象名称 |
3 | long getCreationTime() | 返回session对象被创建的时间, 以毫秒为单位,从1970年1月1号凌晨开始算起 |
4 | String getId() | 返回session对象的ID |
5 | long getLastAccessedTime() | 返回客户端最后访问的时间,以毫秒为单位,从1970年1月1号凌晨开始算起 |
6 | int getMaxInactiveInterval() | 返回最大时间间隔,以秒为单位,servlet 容器将会在这段时间内保持会话打开 |
7 | void invalidate() | 将session无效化,解绑任何与该session绑定的对象 |
8 | boolean isNew() | 返回是否为一个新的客户端,或者客户端是否拒绝加入session |
9 | void removeAttribute(String name) | 移除session中指定名称的对象 |
10 | void setAttribute(String name, Object value) | 使用指定的名称和值来产生一个对象并绑定到session中 |
11 | void setMaxInactiveInterval(int interval) | 用来指定时间,以秒为单位,servlet容器将会在这段时间内保持会话有效 |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
//获取前端提交的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
Userinfo userinfo = new Userinfo(); //假设账号密码正确,我们获得一个用户的对象
userinfo.setUsername(username);
userinfo.setPassword(password);
//获取session对象
HttpSession session = request.getSession();
//将用户的对象保存到session中,每次访问页面时都可以从session中直接获取用户相关信息
session.setAttribute("userinfo",userinfo);
//获取session的ID
String id = session.getId();
//判断session是不是新创建的
boolean aNew = session.isNew();
//获取session保存的数据,object对象,强制类型转换
Userinfo userinfo1 = (Userinfo) session.getAttribute("userinfo");
//注销session,可以用在网页的退出登陆上使用
session.invalidate();
}
<!--xml设置session有效期限,单位分钟-->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
session和cookie的区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上
2、cookie保存载本地不是很安全
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie
4、单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的cookie不能3K。5、将登陆信息等重要信息存放为Session;其他信息如果需要保留,可以放在cookie中
不同 request Session ServletContext cookie 类型 HttpServletRequest HttpSession ServletContext javax.servlet.http.Cookie 创建 客户端向容器发送请求时创建。 容器第一次调用 getSession() 方法时创建。 Servlet 容器启动时创建。 在服务器创建Cookie 销毁 容器对请求做出响应后销毁 关闭服务器或应用被卸载。Session 超时过期 手动调用 session.invalidate() 方法进行销毁。 容器关闭或者 Web 应用被移除时销毁。 不设置过期时间,关闭浏览器后,Cookie就会消失。
设置过期时间,超时过期有效范围 一次请求中有效 在一次会话内有效 对整个 Web 应用内的所有 Servlet 有效。 不设置过期时间,在一次会话中有效。设置过期时间,在时间内有效 数量 Web 应用中的所有 Servlet 实例都可以有多个 request 对象。 每个用户浏览器创建一个 Session 对象 在整个 Web 应用中只有一个 Context 对象。 不同浏览器有不同的标准,20~50个 数据共享 每一次请求都是一个新的 request 对象。 通过和请求转发的配合使用可以实现一次请求中 Web 组件之间共享的数据。 每一次会话都是一个新的 Session 对象。 通过 Session 域对象可以实现一次会话中的多个请求之间共享数据。 在一个应用中有且只有一个 Context 对象,作用于整个 Web 应用,可以实现多次会话之间的数据共享。 同一个浏览器,同一个路径下cookie可以共享。