当用户通过浏览器访问web应用时,通常情况下,服务器需要对用户的状态进行跟踪。例如,用户在网站结算商品时,Web服务器必须根据请求用户的身份,找到该用户所购买的商品。在Web开发中,服务器跟踪用户信息的技术称为会话技术
从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话
会话技术分为Cookie和Session
Cookie:数据存储在客户端本地,减少服务器端的存储的压力,安全性不好,客户端可以清除cookie
Session:将数据存储到服务器端,安全性相对好,但是会增加服务器的压力
Cookie技术是将用户的数据存储到客户端的技术,其存储格式是一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。
我们主要学习的是:
- 1.服务器端怎样将一个Cookie发送到客户端
- 2.服务器端怎样接受客户端携带的Cookie
为了封装 Cookie 信息,在 Servlet API 中提供了一个 Javax. servlet.http. Cookie类,该类包含生成 Cookie信息和提取 Cookie 信息各个属性的方法
Cookie类只有一个构造方法
public Cookie(String name, String value)
参数name指定Cookie名称,value指定Cookie的值
注意:名称不能更改,值可以为任何值。
方法 | 描述 |
---|---|
String getName() | 获取Cookie名称 |
void setValue(String newValue) | |
String getValue() | 设置/获取Cookie的值 |
void setMaxAge(int expiry) | |
int getMaxAge() | 设置/获取Cookie存活时间,单位为秒 |
void setPath(String uri) | |
String getPath() | 设置/获取该Cookie项的有效目录路径 |
void setDomain(String patten) | |
String getDomain() | 设置/获取该Cookie的有效域 |
void setVersion(int v) | |
int setVersion() | 设置 Cookie 采用的协议版本 |
Cookie大小上限为4KB;
上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等
注意,不同浏览器之间是不共享Cookie的。
Cookie是通过HTTP请求和响应头在客户端和服务器端传递的
Cookie:请求头,客户端发送给服务器端
格式:
Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;
Set-Cookie:响应头,服务器端发送给客户端;一个Cookie对象一个Set-Cookie:
格式:
Set-Cookie: a=A
Set-Cookie: b=B
Set-Cookie: c=C
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,
例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie:a=AA,那么客户端只留下一个Cookie,即:a=AA。
1.创建Cookie:
Cookie cookie = new Cookie(String cookieName,String cookieValue);
示例:
Cookie cookie = new Cookie("username", "lisi");
浏览器收到的格式为:
注意:Cookie存储中文会乱码,需要专门对其编码和解码操作
cookie.setMaxAge(int seconds);
注意:如果不设置持久化时间,Cookie会存储在浏览器的内存中,浏览器关闭 Cookie信息销毁(会话级别的Cookie),如果设置持久化时间,Cookie信息会被持久化到浏览器的磁盘文件里
示例:
cookie.setMaxAge(10*60);
设置cookie信息在浏览器的磁盘文件中存储的时间是10分钟,过期后浏览器自动删除该cookie信息
cookie.setPath(String path);
注意:如果不设置携带路径,那么该cookie信息会在访问产生该cookie的web资源所在的路径都携带cookie信息
示例:
cookie.setPath("/Cookie");
表示访问Cookie应用中的任何资源都携带cookie
cookie.setPath("/Cookie/helloCookieServlet");
表示访问Cookie中的helloCookieServlet时才携带cookie信息
response.addCookie(Cookie cookie);
如果想删除客户端的已经存储的cookie信息,那么就使用同名同路径的持久化时间为0的cookie进行覆盖即可
cookie信息是以请求头的方式发送到服务器端的:
1.通过request获得所有的Cookie
Cookie[] cookies = request.getCookies();
2.遍历Cookie数组,通过Cookie的名称获得我们想要的Cookie
for (Cookie cookie : cookies) { System.out.println(cookie.getValue()); }
3.案例-显示上次访问时间
第一次访问显示:第一次访问
之后每次访问显示对应的时间
public class LastAccessTimeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
// 获得当前时间
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-hh:mm:ss");
String currentTime = format.format(date);
// 1、创建Cookie 记录当前的最新的访问时间
Cookie cookie = new Cookie("lastAccessTime", currentTime);
cookie.setMaxAge(60 * 10 * 500);
response.addCookie(cookie);
// 2、获得客户端携带cookie ---- lastAccessTime
String lastAccessTime = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie coo : cookies) {
if ("lastAccessTime".equals(coo.getName())) {
lastAccessTime = coo.getValue();
}
}
}
response.setContentType("text/html;charset=UTF-8");
if (lastAccessTime == null) {
response.getWriter().write("您是第一次访问");
} else {
response.getWriter().write("您上次的访问的时间是:" + lastAccessTime);
}
}
}
Cookie技术可以将用户的信息保存在各自的浏览器中,并且可以在多次请求下实现数据的共享。但是,如果传递的信息比较多,使用 Cookie技术显然会增大服务器端程序处理的难度,这时,可以使用 Session 实现, Session 是一种将会话数据保存到服务器端的技术。
为了区分不同用户的Session数据,客户端每次向服务器请求时都会带着一个SessionID的标记,通常情况下,SessionID是借助Cookie技术来传递值的。
Session是与每一个请求消息紧密相关的,为此,HttpServletRequest定义了用于获取Session对象的getSession()方法,有两个重载
public HttpSession getSession(boolean create);
public HttpSession getSession();
区别是根据传入的参数来判断是否创建新的HttpSession对象,如果为true,则在相关的HttpSession对象不存在时创建并返回新的HttpSession对象,否则不创建新的 HttpSession 对象
常用方法
方法 | 描述 |
---|---|
String getId() | 返回HttpSession id |
long getCreationTime() | 返回创建时间 |
long getLastAccessedTime() | 返回最后一次发送与Session相关请求时间 |
void setMaxInactiveInterval(int interval); | 设置当前HttpSession对象可空闲的以秒为单位的最长时间。 |
boolean isNew() | 判断当前HttpSession对象是否新建的 |
void invalidate() | 用于强制使Session对象无效 |
ServletContext getServletContext() | 返回当前HttpSession对象所属的Web应用程序对象 |
void setAttribute(String name, Object value) | 将一个对象与一个名称关联后存储到当前的HttpSession对象中 |
String getAttribute(String name) | 返回指定名称的属性对象 |
void removeAttribute(String name) | 删除指定名称的属性 |
- 1.获得Session对象
HttpSession session = request.getSession();
此方法会获得专属于当前会话的Session对象,如果服务器端没有该会话的Session 对象会创建一个新的Session返回,如果已经有了属于该会话的 Session 直接将已有的 Session 返回(实质就是根据 JSESSIONID 判断该客户端是否在服务器上已经存在 session 了)
- 2.向session中存取数据(session也是一个域对象)
session.setAttribute(“username”, “wangwu”);
示例代码
/**
* 往Session中存入数据
* @author weidong
*/
public class AddSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//创建Session对象
HttpSession session = request.getSession();
//存入数据
session.setAttribute("username", "wangwu");
String id = session.getId();// 获取session对象的id
// 手动创建一个存储JSESSIONID的Cookie 为该cookie设置持久化时间
Cookie cookie = new Cookie("JSESSIONID", id);
cookie.setPath("/Session/");
cookie.setMaxAge(60 * 10);
response.addCookie(cookie);
//输出
response.getWriter().write("JSESSIONID:" + id);
}
}
public class GetSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
// 从session中获得存储的数据
HttpSession session = request.getSession();
Object attribute = session.getAttribute("username");
response.getWriter().write(attribute + "");
}
}
1.Session对象的生命周期(面试题/笔试题)
创建:第一次执行request.getSession()时创建
销毁:
- 1.服务器(非正常)关闭时
- 2.session过期/失效(默认30分钟)
- 3.手动销毁session
session.invalidate();
2.时间的起算点,从何时开始计算30分钟?
从不操作服务器端的资源开始计时
也可以在工程的web.xml中进行配置
<session-config>
<session-timeout>30session-timeout>
session-config>
3.Session作用范围
默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象
一次会话:用户打开浏览器,点击多个多个超链接,然后关闭浏览器,这个过程称为一次会话
使用 Session实现了用户登录的功能。但在实际开发中,为了保证用户信息的安全,都会在网站登录的界面中添加一次性验证码,从而限制人们使用软件来暴力猜测密码。一次性验证码的功能同样可以使用 Session来实现。
在ImgServlet(Response课程中有用过)中,将验证码的数据存入session中,后在LoginServlet中,将请求中提交过来的验证码与session中的进行对比,如果正确,则验证成功,并且将session中的验证码删除,因为需要保证session中的数据只能被用一次,防止重复提交数据,如果不正确,就使用request将错误信息显示,如果发现session中的数据为null,说明重复提交了数据。
代码结构
public class LoginServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String re = request.getParameter("verifycode");
String answer = (String) request.getSession().getAttribute("verifycode");
PrintWriter out = response.getWriter();
if(answer == null){
out.printf("请不要重复提交");
return;
}
if (re.equals(answer)) {
request.getSession().removeAttribute("verifycode");
out.printf("验证成功");
} else {
out.printf("验证失败");
}
out.flush();
out.close();
}
}