- 浏览: 308953 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
suxiaojack:
15题,就是拿杨辉三角填充空格,答案应该是C(38,19)吧? ...
Project Euler解题汇总 013 ~ 022 -
songhaikang:
这篇文章挺好的,跟着你的步骤很快就可以入门了。非常感谢。
[转贴]Derby入门 —— (1) -
Eastsun:
呵呵,我没有Android的机器,所以兴趣不大
使用Java写的GVmaker虚拟机(开源) -
crapricorn:
那个版本的用不了虚拟键盘啊 呵呵 我们的手机没有实体键盘呀 所 ...
使用Java写的GVmaker虚拟机(开源) -
Eastsun:
crapricorn 写道希望sun侠能做出个android平 ...
使用Java写的GVmaker虚拟机(开源)
前言 : 因为只学过J2SE部分,对JAVA网络编程也不甚了解,所以学习在JAVA操作HTTP协议时碰到很多问题.翻译这篇文章只是为了加深理解,如有不当,还望指出.
原文地址: http://java.sun.com/developer/JDCTechTips/2005/tt0913.html
在JAVA平台,访问URL资源是通过一系列协议处理器(protocol handler)来实现的.URL的起始部分指定了URL使用的协议.比如某个URL是以file:开头的,这表明这个URL资源是保存在本地文件系统的.J2SE5.0定义了几个必须实现的协议:http,https,file,jar.
作为http协议处理器实现的一部分,J2SE5.0增加了一个CookieHandler.这个类提供了一些用于管理cookies的接口.Cookie是保存在浏览器缓存中的一小块数据.当你访问一个网站然后再次访问的时候,这个cookie数据用于鉴别你的身份.Cookies能够用于保存信息,譬如一个在线商店用于保存以购商品信息.Cookie可以是短期的,为一个单独的web事务保存数据,直到关闭浏览器;也可以是长期的,保存数据一个星期或一年.
在J2SE5中并没有设置默认的CookieHandler.不过你可以注册一个Handler以便程序能够保存cookies并且在http连接的时候得到这些cookies.
回到CookieHandler这个类,这是个具有两组相关联方法的抽象类.第一组方法让你能得到当前已经设置的Handler或设置你自己的Handler:
* getDefault()
* setDefault(CookieHandler)
对于安装了安全管理器的应用来说,得到或设置handler需要特别的权限.通过设置handler为null可以清除当前设置的handler.正如之前提到的,没有设置默认的handler.
第二组方法允许你从一个你维持的cookie缓存得到cookies,或将cookies保存到这个cookie缓存.
* get(URI uri,Map<String,List<String>>requestHeaders)
* put(URI uri,Map<String,List<String>>responseHeaders)
get()方法从cookie缓存中的到之前保存的cookie并保存到requestHeaders中.put()方法从response headers 中提取cookies并保存到cookie缓存.
这看起来很简单,事实创建一个handler确实如此.但定义cookie缓存需要做更多的事情.作为示范,我们写一个自己的CookieHandler,cookie缓存以及一个测试程序.这里是测试程序的雏形:[注 1]
- import java.io.*;
- import java.net.*;
- import java.util.*;
- public class Fetch {
- public static void main(String args[]) throws Exception {
- if (args.length == 0 ) {
- System.err.println("URL missing" );
- System.exit(-1 );
- }
- String urlString = args[0 ];
- CookieHandler.setDefault(new ListCookieHandler());
- URL url = new URL(urlString);
- URLConnection connection = url.openConnection();
- Object obj = connection.getContent();
- url = new URL(urlString);
- connection = url.openConnection();
- obj = connection.getContent();
- }
- }
这个程序首先建立并安装了一个ListCookieHandler类(这个类的定义将在后面给出).然后打开了一个到URL(由命令行参数给出)的连接,并且读取其内容.再次打开另一个到URL的连接,并读取相同的内容.当第一次读取连接内容时,响应中包含的cookies将会被保存,第二次连接请求中就会包含这些保存的cookies.
下面我们来看这些是如何通过URLConnection类实现的.在建立了一个表示网络资源的URL后,我们可以用URLConnection来得到与该网站通信的输入流与输出流.
String urlString = ...;
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
// .. read content from stream
这个连接中的信息可能有一部分是属于报文头,这与所用的协议有关.我们可以通过URLConnection来得到这些报文头消息,这个类提供了一些能提取报文头信息的方法,包括:
* getHeaderFields() - Gets a Map of available fields.
* getHeaderField(String name) - Gets header fields by name.
* getHeaderFieldDate(String name, long default) - Gets the header field as a date.
* getHeaderFieldInt(String name, int default) - Gets the header field as a number.
* getHeaderFieldKey(int n) or getHeaderField(int n) - Gets the header field by position.
作为一个示例,下面的程序将指定URL的所有报文头消息列出:
- import java.net.*;
- import java.util.*;
- public class ListHeaders {
- public static void main(String args[]) throws Exception {
- if (args.length == 0 ) {
- System.err.println("URL missing" );
- }
- String urlString = args[0 ];
- URL url = new URL(urlString);
- URLConnection connection = url.openConnection();
- Map<String,List<String>> headerFields =
- connection.getHeaderFields();
- Set<String> set = headerFields.keySet();
- Iterator itor = set.iterator();
- while (itor.hasNext()) {
- String key = itor.next();
- System.out.println("Key: " + key + " / " +
- headerFields.get(key));
- }
- }
- }
这个程序用一个URL作为参数(比如:http://java.sun.com),然后将从该网站返回的所有报文头消息列出,每一个报头用如下格式显示:
Key: <key> / [<value>]
如果你输入:
>> java ListHeaders http://java.sun.com
你将会看到与下面类似的输出:
Key: Set-Cookie / [SUN_ID=192.168.0.1:269421125489956; EXPIRES=Wednesday, 31- Dec-2025 23:59:59 GMT; DOMAIN=.sun.com; PATH=/]
Key: Set-cookie / [JSESSIONID=688047FA45065E07D8792CF650B8F0EA;Path=/]
Key: null / [HTTP/1.1 200 OK]
Key: Transfer-encoding / [chunked]
Key: Date / [Wed, 31 Aug 2005 12:05:56 GMT]
Key: Server / [Sun-ONE-Web-Server/6.1]
Key: Content-type / [text/html;charset=ISO-8859-1]
这些输出只包含URL的报头,并没有包括这个URL指向的HTML页面.你可能注意到这些输出信息里面包含了这个URL站点所用的web服务器以及其日期时间.同意可以看到里面包含了两行Set-Cookie,这就是报头里面携带的cookies.这些cookie能够保存下来,然后在下一次请求的时候被发送.
下面我们来建立一个CookieHandler,我们得实现CookieHandler的两个抽象方法:get()与put():
* public void put( URI uri, Map<String, List<String>> responseHeaders) throws IOException
* public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException
其中put()方法将所有报头中的cookies保存到一个缓存中.为了实现put()方法,首先要从responseHeaders中得到"Set-Cookie"对应的List.
List<String> setCookieList =
responseHeaders.get("Set-Cookie");
当你得到cookies对应的List,将List中所有的值保存下来.如果这个cookie已经存在,就将已保存的替换掉:
- if (setCookieList != null ) {
- for (String item : setCookieList) {
- Cookie cookie = new Cookie(uri, item);
- // Remove cookie if it already exists in cache
- // New one will replace it
- for (Cookie existingCookie : cache) {
- ...
- }
- System.out.println("Adding to cache: " + cookie);
- cache.add(cookie);
- }
- }
这里的"cache"可以是一个数据库或者是一个Collections Framework中的List.其中的Cookie类将在下面定义.从本质上说,这些就是put()方法所要做的事:对于响应报头中每一个cookie,这个方法将cookie保存到缓存中.
而get()方法做的是相反的事情:将缓存中所有与URI匹配cookie添加到请求报头中,如果存在多个cookie,则建立一个用','分隔的列表.方法get()返回一个Map,而且用一个包含已有报文头的map作为参数,你应该将cookie缓存与之相匹配的cookie添加这个map里面去,但是这个Map是只读的,所以你应该首先新建另一个map,并将参数map中的内容复制过去,然后再将cookie添加进去,最后返回一个只读的map.[注 2]
为了实现get()方法,首先要从cookie缓存中查找与URI相匹配的cookie,然后删除那些已经过期的cookie:
- // Retrieve all the cookies for matching URI
- // Put in comma-separated list
- StringBuilder cookies = new StringBuilder();
- for (Cookie cookie : cache) {
- // Remove cookies that have expired
- if (cookie.hasExpired()) {
- cache.remove(cookie);
- } else if (cookie.matches(uri)) {
- if (cookies.length() > 0 ) {
- cookies.append(", " );
- }
- cookies.append(cookie.toString());
- }
- }
这里简单说明一下Cookie类,上面代码中用到了Coookie类的两个方法:hasExpired()和matches().hasExpired()方法用于表明这个cookie是否已经过期;而matches()方法用于检验这个cookie与某个URI是否匹配.
get()方法余下部分将上面的StringBuilder中的文本添加到一个Map中,与之对应的key为"Cookie"
- // Map to return
- Map<String, List<String>> cookieMap =
- new HashMap<String, List<String>>(requestHeaders);
- // Convert StringBuilder to List, store in map
- if (cookies.length() > 0 ) {
- List<String> list =
- Collections.singletonList(cookies.toString());
- cookieMap.put("Cookie" , list);
- }
- return Collections.unmodifiableMap(cookieMap);
下面是CookieHandler的完整实现,里面添加了一些输出语句用于观察运行时刻的信息:
- import java.io.*;
- import java.net.*;
- import java.util.*;
- public class ListCookieHandler extends CookieHandler {
- // "Long" term storage for cookies, not serialized so only
- // for current JVM instance
- private List<Cookie> cache = new LinkedList<Cookie>();
- /**
- * Saves all applicable cookies present in the response
- * headers into cache.
- * @param uri URI source of cookies
- * @param responseHeaders Immutable map from field names to
- * lists of field
- * values representing the response header fields returned
- */
- public void put(
- URI uri,
- Map<String, List<String>> responseHeaders)
- throws IOException {
- System.out.println("Cache: " + cache);
- List<String> setCookieList =
- responseHeaders.get("Set-Cookie" );
- if (setCookieList != null ) {
- for (String item : setCookieList) {
- Cookie cookie = new Cookie(uri, item);
- // Remove cookie if it already exists
- // New one will replace
- for (Cookie existingCookie : cache) {
- if ((cookie.getURI().equals(
- existingCookie.getURI())) &&
- (cookie.getName().equals(
- existingCookie.getName()))) {
- cache.remove(existingCookie);
- break ;
- }
- }
- System.out.println("Adding to cache: " + cookie);
- cache.add(cookie);
- }
- }
- }
- /**
- * Gets all the applicable cookies from a cookie cache for
- * the specified uri in the request header.
- *
- * @param uri URI to send cookies to in a request
- * @param requestHeaders Map from request header field names
- * to lists of field values representing the current request
- * headers
- * @return Immutable map, with field name "Cookie" to a list
- * of cookies
- */
- public Map<String, List<String>> get(
- URI uri,
- Map<String, List<String>> requestHeaders)
- throws IOException {
- // Retrieve all the cookies for matching URI
- // Put in comma-separated list
- StringBuilder cookies = new StringBuilder();
- for (Cookie cookie : cache) {
- // Remove cookies that have expired
- if (cookie.hasExpired()) {
- cache.remove(cookie);
- } else if (cookie.matches(uri)) {
- if (cookies.length() > 0 ) {
- cookies.append(", " );
- }
- cookies.append(cookie.toString());
- }
- }
- // Map to return
- Map<String, List<String>> cookieMap =
- new HashMap<String, List<String>>(requestHeaders);
- // Convert StringBuilder to List, store in map
- if (cookies.length() > 0 ) {
- List<String> list =
- Collections.singletonList(cookies.toString());
- cookieMap.put("Cookie" , list);
- }
- System.out.println("Cookies: " + cookieMap);
- return Collections.unmodifiableMap(cookieMap);
- }
- }
到这里,我们的工作只剩下Cookie类的实现了.这个工作的重头戏在其构造函数部分,你需要从URI以及报文头里面解析出所需要的信息.其中的cookie有效日期信息的格式是确定的,但其它信息对不同的网站有不同的格式.不过这也没有什么困难的,只需要把cookie路径,有效日期,域名这些信息保存下来就是了.
- public Cookie(URI uri, String header) {
- String attributes[] = header.split(";" );
- String nameValue = attributes[0 ].trim();
- this .uri = uri;
- this .name = nameValue.substring( 0 , nameValue.indexOf('='));
- this .value = nameValue.substring(nameValue.indexOf('=')+ 1 );
- this .path = "/" ;
- this .domain = uri.getHost();
- for ( int i= 1 ; i < attributes.length; i++) {
- nameValue = attributes[i].trim();
- int equals = nameValue.indexOf('=');
- if (equals == - 1 ) {
- continue ;
- }
- String name = nameValue.substring(0 , equals);
- String value = nameValue.substring(equals+1 );
- if (name.equalsIgnoreCase( "domain" )) {
- String uriDomain = uri.getHost();
- if (uriDomain.equals(value)) {
- this .domain = value;
- } else {
- if (!value.startsWith( "." )) {
- value = "." + value;
- }
- uriDomain =
- uriDomain.substring(uriDomain.indexOf('.' ));
- if (!uriDomain.equals(value)) {
- throw new IllegalArgumentException(
- "Trying to set foreign cookie" );
- }
- this .domain = value;
- }
- } else if (name.equalsIgnoreCase( "path" )) {
- this .path = value;
- } else if (name.equalsIgnoreCase( "expires" )) {
- try {
- this .expires = expiresFormat1.parse(value);
- } catch (ParseException e) {
- try {
- this .expires = expiresFormat2.parse(value);
- } catch (ParseException e2) {
- throw new IllegalArgumentException(
- "Bad date format in header: " + value);
- }
- }
- }
- }
Cookie类的其它方法只需要返回这些信息,或者检查有效日期就OK了:
- public boolean hasExpired() {
- if (expires == null ) {
- return false ;
- }
- Date now = new Date();
- return now.after(expires);
- }
- public String toString() {
- StringBuilder result = new StringBuilder(name);
- result.append("=" );
- result.append(value);
- return result.toString();
- }
对于一个已经过期的cookie,其matchs方法总是返回false:
public boolean matches(URI uri) {
if (hasExpired()) {
return false;
}
String path = uri.getPath();
if (path == null) {
path = "/";
}
return path.startsWith(this.path);
}
注意:Cookie规范中要求同时检查域名以及路径,为了简单起见,我们这里只检查了路径.
这里是Cookie的完整定义:
- import java.net.*;
- import java.text.*;
- import java.util.*;
- public class Cookie {
- String name;
- String value;
- URI uri;
- String domain;
- Date expires;
- String path;
- private static DateFormat expiresFormat1
- = new SimpleDateFormat( "E, dd MMM yyyy k:m:s 'GMT'" , Locale.US);
- private static DateFormat expiresFormat2
- = new SimpleDateFormat( "E, dd-MMM-yyyy k:m:s 'GMT'" , Locale.US);
- /**
- * Construct a cookie from the URI and header fields
- *
- * @param uri URI for cookie
- * @param header Set of attributes in header
- */
- public Cookie(URI uri, String header) {
- String attributes[] = header.split(";" );
- String nameValue = attributes[0 ].trim();
- this .uri = uri;
- this .name =
- nameValue.substring(0 , nameValue.indexOf('='));
- this .value =
- nameValue.substring(nameValue.indexOf('=')+1 );
- this .path = "/" ;
- this .domain = uri.getHost();
- for ( int i= 1 ; i < attributes.length; i++) {
- nameValue = attributes[i].trim();
- int equals = nameValue.indexOf('=');
- if (equals == - 1 ) {
- continue ;
- }
- String name = nameValue.substring(0 , equals);
- String value = nameValue.substring(equals+1 );
- if (name.equalsIgnoreCase( "domain" )) {
- String uriDomain = uri.getHost();
- if (uriDomain.equals(value)) {
- this .domain = value;
- } else {
- if (!value.startsWith( "." )) {
- value = "." + value;
- }
- uriDomain = uriDomain.substring(
- uriDomain.indexOf('.' ));
- if (!uriDomain.equals(value)) {
- throw new IllegalArgumentException(
- "Trying to set foreign cookie" );
- }
发表评论
-
JavaFX1.2的性能貌似有了很大的提升
2009-06-03 09:36 1988Osvaldo Pinali Doederlein's B ... -
Java.next:第二部分——与Java互操作
2008-09-19 23:05 1885原文地址:Java.next #2: Java Inter ... -
Java.next:第一部分——共同点
2008-09-19 13:31 1556原文地址:Java.next: Common Ground ... -
隐式转换:比动态类型更强大?
2008-09-16 18:37 1675本文内容主要来自Implicit Conversions: ... -
澄清:Java中只有按值传递,没有按引用传递!
2008-07-13 22:23 3997前言:在JAVA面试题解惑系列(五)——传了值还是传了引用 ... -
Ruby,Python不能威胁到Java的13个理由
2008-05-28 22:50 1486最近,danielstoner发表了一篇题为13 reas ... -
Java:进化的尽头
2008-05-28 17:45 1310原文地址:http://blog. ... -
《Effective Java》: Joshua Bloch访谈
2008-05-23 00:52 2620原文地址:Effective ... -
JSR 308:Java语言复杂度在恣意增长?
2008-05-20 13:54 1766原帖地址:http://www ... -
Sun能否让Java重振雄风?
2008-05-13 14:42 0原文地址:Can Sun rejuvenate Java? ... -
Groovy, JRuby, Jython, Scala:谁是胜利者?
2008-05-13 00:04 6561原文地址:Groovy, JRuby, Jython, Sca ... -
JAVA比C++更快?
2008-04-08 15:03 2054首先:我必须承认,我取JA ... -
在J2ME中模拟C语言中的文件操作
2008-02-27 00:09 1629最近在写一个模拟器(OR虚拟机),用于运行文曲星(一种 ... -
使用StAX解析XML:使用定制事件和编写 XML
2007-10-12 23:01 2109除了提供一个低层的基 ... -
使用StAX解析XML: 拉式解析和事件
2007-10-08 20:53 33122007 年 7 月 05 日 Streaming API ... -
[转载]Streaming API for XML (StAX) 简介
2007-10-07 13:35 2311Streaming API for XML (StAX) 是用 ... -
浅谈HTTP的无状态性
2007-05-30 01:26 2040HTTP是Hyper Text Transf ... -
用动态代理进行修饰
2007-04-11 16:26 1862动态代理为实 ... -
一种得到代码所在行号的方法
2007-04-02 20:03 3930RT,今天在论坛上看到有人提出这个问题,马上联想 ... -
网络词汇表
2007-04-01 13:33 2002【协议 】--- protocol,指通信双方通信时遵守的一 ...
相关推荐
本文将深入探讨如何使用JavaScript来操作Cookie,包括获取Cookie数据、获取Cookie数据的key名称以及清除站点所有Cookie数据的方法。 首先,我们要了解Cookie的基本概念。Cookie是由服务器端设置并在客户端存储的一...
本篇将深入探讨.NET中的Cookie操作,以及如何读取存储在Cookie中的数据。 一、Cookie的基本概念 Cookie由服务器端创建并发送到客户端(浏览器),客户端会在后续的请求中自动携带这些Cookie回服务器。每个Cookie都...
3. 应用收到响应后,使用CookieHandler或Interceptor解析并保存Cookie到本地,例如使用SharedPreferences或SQLite数据库。 4. 在后续的列表请求中,读取本地存储的Cookie,将其添加到请求头中发送给服务器。 5. ...
因为cookie在跨域的情况下,浏览器根本不允许互相访问的限制,为了突破这个限制,所以有了以下这个实现方案,使用postmessage和localstorage进行数据跨域共享。 原理比较简单,但是遇到的坑也不少,这里梳理一下,做...
本教程将深入探讨如何在Eclipse平台上使用OkHttp进行简单的请求封装和Cookie管理,以实现更加便捷、高效的应用程序网络通信。 首先,我们了解下OkHttp的基本用法。OkHttp通过构建Request对象来定义网络请求,然后...
在使用南方数据新闻发布管理系统 V7.0时,管理员应当关注这些安全措施,并定期检查和修复任何潜在的安全漏洞。同时,选择支持最新Web标准的操作系统,如Windows 10,以确保更好的兼容性和安全性。 对于建站过程中的...
Cookie Pal的出现,使得用户能够更好地理解和管理这些数据,提升在线隐私保护和浏览体验。 Cookie Pal的主要功能包括: 1. **查看和管理Cookie**:用户可以清楚地看到各个网站在他们设备上设置的Cookie,选择性地...
在Web开发中,用户登录是常见的功能之一,而使用Cookie技术可以有效地简化这一过程,提供更流畅的用户体验。本练习将探讨如何利用Cookie来管理用户的登录状态,从而避免频繁地发送登录请求。以下是对这个主题的详细...
2. 初始化AsyncHttpClient:创建AsyncHttpClient实例,如果需要自定义Cookie管理,可以设置CookieHandler。 ```java AsyncHttpClient client = new AsyncHttpClient(); client.setCookieHandler(new ...
其次,Cookie数据以Cookie文件格式存储在浏览者计算机的cache目录里,其中就包含有关网页、密码和其他用户行为的信息,那么只要进入硬盘就能打开Cookie文件。图1是一个Cookie文件的内容: 如果你未曾留意你的...
Cookie是Web应用程序中常用的一种数据存储机制,它可以用来存储用户偏好、会话信息等。jQuery的Cookie插件(如:jquery.cookie.js)提供了一种简单的方式来创建、读取和删除cookie。以下是一些主要功能: 1. **创建...
尽管给定的代码片段没有直接展示加密的具体实现,但在实际应用中,可以使用.NET Framework提供的加密算法(如AES、RSA等)来加密Cookie数据。例如,可以使用`System.Security.Cryptography`命名空间中的类来实现。 ...
因此,对于大量数据的存储,更推荐使用Session或者基于数据库的会话管理方式。而Cookie更适合存储少量、重要的识别信息,如会话ID。 总结来说,“使用Cookie记录用户名和密码”是Web开发中的一种常见实践,涉及了...
3. **数据分析**:分析Cookie数据有助于进行用户行为分析,为市场营销策略提供数据支持。 **总结** Cookie分析工具如IECookiesView v1.73是网络技术的重要辅助工具,它既有助于个人管理自己的隐私,也有助于网站...
"源码使用说明.txt"文件很可能是对如何使用提供的Cookie管理代码的详细解释,包括导入库、调用函数、设置和读取Cookie的步骤,以及可能遇到的问题和解决办法。这份文档将帮助开发者了解易语言中处理Cookie的基本流程...
Cookie是Web开发中的一种技术,用于在客户端存储和管理数据,解决了HTTP协议无状态的问题。它们是由服务器端生成,发送到客户端(浏览器),并由浏览器保存。当用户再次访问同一网站时,浏览器会将Cookie回传给...
总结来说,Cookie适合存储少量、短期、需要在服务器端访问的数据,而localStorage则适用于存储大量、长期、仅客户端使用的数据。在实际应用中,开发者可以根据需求选择合适的存储方案。对于学习和实践,"CookieTest...
在iOS应用开发中,使用Swift语言进行Web内容展示时,我们常常会遇到WKWebView与cookie管理的问题。WKWebView是Apple推荐用来替代UIWebView的新一代网页视图组件,它提供了更好的性能和安全性。然而,与传统的...
该资源主要利用Cookie是由服务器端生成并储存在浏览器客户端上的...我们还可以使用特殊的方法,将Cookie保存在客户端的硬盘上,永久性保存,这样关闭浏览器Cookie还是存在的,不会消失。所以可以用来实现十天免登录功能
本教程将探讨如何利用动态IP池和cookie来爬取豆瓣网站上的影评数据,以实现更高效、稳定的数据抓取。 首先,我们需要了解动态IP池的概念。动态IP池是一个能够提供大量不同IP地址的系统,它在爬虫工作时可以频繁更换...