一、Cookie
Cookie 数据是由客户端来保存和携带的,所以称之为客户端技术。
创建一个 cookie,cookie 是 servlet 发送到 Web 浏览器的少量信息。这些信息由浏览器保存,然后发送回服务器 cookie 的值可以唯一地标识客户端,因此 cookie 常用于会话管理。
一个 cookie 拥有一个名称、一个值和一些可选属性,比如注释、路径和域限定符、最大生存时间和版本号。一些 Web 浏览器在处理可选属性方面存在 bug,因此有节制地使用这些属性可提高 serviet 的互操作性。
servlet 通过使用 HttpServletResponse#addCookie
方法将 cookie 发送到浏览器:该方法将字段添加到 HTTP 响应头以便一次一个地将 cookie 发送到浏览器。浏览器应该支持每台 Web 服务器有 20 个 cookie,总共有 300 个 cookie,并且可能将每个 cookie 的大小限定为 4 KB。
浏览器通过向 HTTP 请求头添加字段将 cookie 返回给 serlet 可使用 HttpServletRequest#getCookies
方法从请求中获取 cookie。一些 cookie 可能有相同的名称,但却有不同的路径属性。
cookie 影响使用它们的 Web 页面的缓存。HTTP 1.0 不会缓存那些使用通过此类创建的 cookie 的页面。此类不支持 HTTP 1.1 中定义的缓存控件。
此类支持版本0(遵守Netscape协议)和版本1(遵守RFC 2109协议) cookie 规范。默认情况下, cookie 是使用版本0创建的,以确保最佳互操作性。
cookie 容量
:一个浏览器最多保存 300 个 cookie。每个站点做多保存 20 个 cookie,每个 cookie 的大小限制是 4kb。
cookie 默认存活时间
:浏览器关闭的时候结束。
cookie 持久化
:若希望浏览器将 cookie 存储到磁盘上就需要用到 maxAge(),以秒为单位的时间。
cookie 删除
:删除 cookie 时,path 必须一致,否则不会被删除。
属性:
1、name
:名称不能唯一确定一个 Cookie。路径可能不同。
2、value
:不能存中文。
3、path
:默认值是写 Cookie 的那个程序的访问路径。
比如:http://localhost:8080/day10_00_cookie/servlet/login
写的 Cookie path 就是:/day10_00_cookie 看当前创建 cookie 的资源(servlet)文件路径 也可以是 reuest.getContextPath(); 获取当前应用的路径。
客户端在访问服务器另外资源时,根据访问的路径来决定是否带着 Cookie 到服务器。
当前访问的路径如果是以 cookie 的 path 开头的路径,浏览器就带。否则不带。
4、maxAge(有效存活时间)
:cookie 的缓存时间。默认是 -1(默认存在浏览器的内存中)。单位是秒。
负数:cookie的数据存在浏览器缓存中。
0:删除。路径要保持一致,否则可能删错人。
正数:缓存(持久化到磁盘上)的时间。
cookie 在磁盘上持久化的文本形式:
cookie 在磁盘上持久化的文本形式:
public class CookieDemo1 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter pw = resp.getWriter();
Cookie[] cookies = req.getCookies();
for (int i = 0;cookies!=null&& i < cookies.length; i++) {
if("lastAccessTime".equals(cookies[i].getName())) {
long l = Long.parseLong(cookies[i].getValue());
pw.write("您上次的登陆时间为:"+new Date(l).toLocaleString());
}
}
//删除cookie跳转的servlet
pw.print("<a href='"+req.getContextPath()+"/servlet/clear'>clear cookie</a>");
//创建cookie
Cookie ck = new Cookie("lastAccessTime", System.currentTimeMillis()+"");
//设置cookie的有效时间,单位是秒
// ck.setMaxAge(5*60);
//设置cookie的path
// ck.setPath("/day10_00_cookie/servlet");
// ck.setPath(req.getContextPath()); //建议这两种写法 表示当前的应用/day10_00_cookie
ck.setPath("/"); //表示 /day10_00_cookie ck.setPath("http://www.taobao.com");==>也可以将cookie带到该网站
resp.addCookie(ck); //需要将cookie添加给响应报文==>设置好了cookie的相关属性再进行添加
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
cookie 的取出:
public class CookieDemo2 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter pw = resp.getWriter();
Cookie[] cookies = req.getCookies();
for (int i = 0;cookies!=null&& i < cookies.length; i++) {
if("lastAccessTime".equals(cookies[i].getName())) {
long l = Long.parseLong(cookies[i].getValue());
pw.write("您上次的登陆时间为:"+new Date(l).toLocaleString());
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
cookie 的清除
public class ClearServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建一个cookie对象
Cookie ck = new Cookie("lastAccessTime", "");
//和创建cookie时候的路径path对应起来,不然可能会删除对象
ck.setPath("/");
ck.setMaxAge(0);
resp.addCookie(ck);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
二、Session
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个Session 对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在 Session 对象中。有关使用 Session 对象的详细信息,请参阅"ASP应用程序"部分的"管理会话”。注意 会话状态仅在支持 cookie 的浏览器中保留。
也是一个域对象: session(多servlet可以共享一个session数据) servletContext(整个应用的范围) request(servlet执行之前创建,结束的时候销毁。)
session 默认存活时间:30min。
同一个会话下,可以使一个应用的多个资源共享数据。
cookie 客户端技术,只能存字符串。HttpSession 服务器端的技术,可存储对象。
在 WEB 开发中,服务器为每一个客户端(请求你创建且没有 session 才创建)创建一个会话对象(session 对象)。注意一个浏览器独占一个 session 对象.
原理详解:
session 机制是一种服务器端的机制。
用来在无状态的 HTTP 协议下越过多个请求页面来维持和识别用户。
当程序需要为某个客户端的请求创建一个 session 的时候,
服务器首先检查这个客户端的请求里是是否包含一个 session id 标识。
如果包含一个 session id 则说明以前为此客户端创建过 session。
服务器就按照 session id 把这个 session 检索出来使用,若没有创建过,则创建一个新的 Session。
创建时机:
HttpSession session = request.getSession();
如果当前没有 session,则会立刻建立一个 session;
如果有 session 则返回当前 session。
这句话和 HttpSession session = request.getSession(true);的效果是一样的。
HttpSession session = request.getSession(false);
则不会自动建立 session。
若当前没有 session,你所得到的 seesion 只会是一个 null。
总结:
session 不是一打开网站就会立刻建立。
它的建立需要基于下面两个条件中的任意一个:
1、在 servlet 中手动调用
HttpSession session = request.getSession();
或者
HttpSession session = request.getSession(true);
2、jsp 中没有写 <%@ page session="false"%>
(默认情况下它是<%@ page session="true"%>的)
如果两个条件同时都不满足,那么你建立的只是一个无 seesion 的连接。
session 格式:
30min 后服务端的 session 和客户端的 JSESSIONID=xxx,才会被删除掉。重新调用HttpSession session = request.getSession();
重新创建此两个对象。
常用方法:
把数据保存在 HttpSession 对象中,该对象也是一个域对象。
void setAttribute(String name,Object value);
Object getAttribute(String name);
void removeAttribute(String name);
HttpSession.getId():
setMaxInactiveInterval(int interval) 设置session的存活时间 单位s
或者使用配置文件的方式
<session-config>
<!-- 设置session的有效时间,单位是分钟 -->
<session-timeout>10</session-timeout>
</session-config>
invalidate() 使此会话无效。
getSession():内部执行原理
1、获取名称为 JSESSIONID 的 cookie 的值。
2、没有这样的 cookie,服务端创建一个新的 HttpSession 对象,分配一个唯一的 SessionID。并且在浏览器中写一个名字为 JSESSIONID=sessionID(dbe22defb...) 的 cookie。
3、有这样的 Cookie,获取 cookie 的值(dbe22defb...),从服务器的内存中找到对应的 HttpSession 对象。
HttpSession request.getSession(boolean create):
true:和 getSession() 功能一样。
false:根据客户端 JSESSIONID 的 cookie 的值,找对应的 HttpSession 对象,找不到返回 null(不会创建新的,只是查询)。
客户端禁用 cookie 后的会话数据保存问题:
客户端禁用 cookie:浏览器永远不会向服务器发送 cookie 的请求消息头。
或者存在浏览器不支持 cookie 技术。==>看浏览器有没有发送 cookie 请求消息头,没有就重写 URL,有就不重写。
解决方案:
方案一:在主页上给出提示:请不要禁用您的 cookie。
方案二:URL 重写。必须对网站的所有地址都重写。
public String encodeURL(String url)
通过将会话ID 包含在指定 URL 中对该 URL进行编码,如果不需要编码,则返回未更改的 URL。此方法的实现包含可以确定会话 ID 是否需要在 URL 中编码的逻辑。例如,如果浏览器支持 cookie,或者关闭了会话跟踪,则 URL 编码就不是必需的。
对于健壮的会话跟踪,servlet 发出的所有 URL 都应该通过此方法运行。否则,URL 重写不能用于不支持 cookie 的浏览器。
url 要编码的 URL。
return 如果需要编码,则返回编码的 URL;否则返回未更改的 URL。
示例:
public class AddCart extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out =resp.getWriter();
String id = req.getParameter("id");
Book book = DBUtil.getBookById(id);
HttpSession session = req.getSession(); //这时候是带JSESSIONID来找session
ArrayList<Book> list = (ArrayList<Book>) session.getAttribute("cart");
if(null==list) {
list =new ArrayList<Book>();
}
list.add(book);
session.setAttribute("cart", list);
out.write("购买成功:"+book.getName());
String url = req.getContextPath()+"/servlet/showAll";
resp.setHeader("refresh", "2;url="+resp.encodeURL(url));
// resp.setHeader("refresh", "2;url="+req.getContextPath()+"/servlet/showAll");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
评论