探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
在之前学习HTTP时我们说:标准HTTP协议既有优点也有缺点,优点在于极大地减轻了服务器的压力,每一次请求不会造成不必要连接占用;缺点在于繁复地建立连接和断开连接,请求会传输大量重复的信息,所以随后出现了Keep-Alive、Cookie、HttpSession在某些程度上弥补了标准HTTP的缺点。从今天起,我们就开始学习Cookie和HttpSession
会话
在正式进入Cookie和HttpSession的学习之前,我们先来了解一个术语:会话。
简单地说:用户打开一个浏览器后点击网页中的多个超链接访问多个web资源,访问完毕后关闭浏览器。这个过程就称之为一个会话。在会话过程中会产生一些和用户操作密切相关的数据,所以客户端或者服务端需要为每个用户保存这些数据。例如:用户点击超链接通过一个Servlet购买了几件商品,客户端或者服务端应保存这些商品信息以便于用户点结帐Servlet时,结帐Servlet得到这些已购买的商品信息从而正确地结算。
那么客户端和服务端应该怎么样保存这些用户信息呢?通常地讲,有两种方式:Cookie和HttpSession
Cookie
Cookie属于客户端技术。服务端把每个用户的数据以cookie的形式返回到用户的浏览器的缓存中。当用户使用浏览器再去访问服务器里的web资源时,就会将这些Cookie携带给服务端
HttpSession
Session属于服务器端技术。服务端为每个用户创建一个其独享的HttpSession对象,用户在访问服务器的web资源时可把不同用户的数据放在各自对应的session中
嗯哼,在了解了关于会话的基础知识之后,我们开始进入Cookie的学习
Cookie简介
Cookie是Servlet发送浏览器的少量信息,这些信息由浏览器保存,当浏览器访问Web资源时再将其发送回服务器。一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和值(VALUE)并且名称和值都是String类型的;除此以外,它还有一些其它信息:比如注释、路径和域限定符、最大生存时间maxAge和版本号。Cookie的值可以唯一地标识客户端,因此Cookie常用于会话管理。
Servlet可通过httpServletResponse.addCookie()将字段添加到HTTP 响应头以便将Cookie发送到浏览器。浏览器支持每台Web服务器20个Cookie,合计300个,并且将每个Cookie的大小限定为4KB.
浏览器通过向HTTP请求头添加字段将Cookie返回给Servlet。服务端可用HttpServletRequest.getCookies()从请求中获取Cookie.
一个服务端可以给同一个WEB浏览器发送多个Cookie,此时,如果有两个Cookie的name一样那么后者会覆盖前者。同一个WEB浏览器也可以存储多个不同服务端提供的Cookie。请注意,发送到浏览器的Cookie在默认情况下它是一个会话级别的cookie(即Cookie被存储在浏览器的内存中)当用户退出浏览器之后即被删除。若希望浏览器将该Cookie存储在磁盘上,则需要设置Cookie的maxAge.
Cookie入门示例
请看如下示例:
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
package cn.com;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieTest1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
Cookie[] cookies = request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
Cookie cookie=cookies[i];
System.out.println(cookie.getName()+" "+cookie.getValue());
}
if (cookies == null) {
Cookie c1 = new Cookie("username", "tom");
Cookie c2 = new Cookie("password", "123456");
response.addCookie(c1);
response.addCookie(c2);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
代码解析如下:
- 生成两个Cookie,请参见代码第26-27行
- 利用response.addCookie()将Cookie返回给客户端,请参见代码第28-29行
- 利用request.getCookies()获取到浏览器携带至服务端的所有Cookie,请参见代码第20-24行
输出结果:
username tom
password 123456
我们再去浏览器中看看这些Cookie值,在此以谷歌浏览器为例
嗯哼,看到了吧,在此展示了Cookie的相关信息。
Cookie应用详解
cookie使用示例
在实际开发中Cookie有许多实用的地方,在此我们实现一个功能:利用Cookie记录上次访问时间
请看如下示例:
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
package cn.com;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieTest2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String LAST_ACCESS_TIME="time";
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
Cookie[] cookies = request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
Cookie cookie=cookies[i];
if(LAST_ACCESS_TIME.equals(cookie.getName())){
String time = cookie.getValue();
writer.println("<h4>"+"上次访问时间:"+time+"</h4>");
System.out.println("time="+time);
}
}
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int date = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
String time = year+"/"+(month+1)+"/"+date+" " +hour+":"+minute+":"+second;
Cookie cookie = new Cookie(LAST_ACCESS_TIME, time);
response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
代码解析如下:
- 得到所有Cookie,请参见代码第27行
- 从所有Cookie中筛选出上次访问的时间,请参见代码第28-35行
- 利用Cookie将最新的访问时间返回给浏览器
运行后效果如下图所示:
我们再去浏览器中看看这些Cookie值,在此以谷歌浏览器为例
cookie的maxAge
请注意,”过期时间:浏览会话结束时”,也就是说当我们结束了本次通话(关闭浏览器)之后这些Cookie就被删除了。这是为什么呢?之前我们也说过了:Cookie在默认情况下是一个会话级别的cookie,它存在于浏览器的内存中,当用户退出浏览器之后即被删除。现在,我们希望在关闭浏览器之后再次打开浏览器时依然可以显示上次登录的时间,这就需要设置Cookie的maxAge将该Cookie存储在磁盘上。打开API我们可以看到方法cookie.setMaxAge(int expiry),默认情况下expiry的值为-1,即关闭浏览器后Cookie被删除。如果设置expiry的值为0则表示立即删除Cookie;如果设置expiry的值为正数则表示将Cookie保存到硬盘中且在expiry秒后失效。
cookie的path
请注意,”路径:/TestCookie01”,这个路径是不是觉得有点眼熟呢?哇哈,它就是我们通过request.getContextPath();获取到的应用上下文路径!所以,默认情况下通过cookie.getPath()获取到Cookie的路径正是应用的上下文路径,当然你也可以cookie.setPath()为Cookie设置path。这个path有啥用呢?我们打开官方文档看看是怎么说这个path的:在为Cookie设置path(即目录)后,Cookie对于该指定目录中的所有页面及该目录子目录中的所有页面都是可见的。哇哈,看到这里可能还是有点懵;嗯哼,我再换个方式说:如果浏览器访问的资源路径(即URI而非URL)如果是以Cookie的path开头的那么浏览器就会将该Cookie携带至服务端;否则不会携带该Cookie。举个例子:比如Cookie的path是/TestCookie01/hello;浏览器访问的是xxxx/TestCookie01/hello/haha/test.html那么浏览器就会将该Cookie携带至服务端;假如浏览器访问的是xxxx/TestCookie01/abcde/ppha/test.html那么浏览器就不会将该Cookie携带至服务端