Java中的cookie管理方案(3)-与J2ME结合

<script type="text/javascript"> google_ad_client = "pub-8800625213955058"; /* 336x280, 创建于 07-11-21 */ google_ad_slot = "0989131976"; google_ad_width = 336; google_ad_height = 280; // </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> jCookie结构 下面我将描述层及他们使用的不同的类。 层1 那些开发者多数都想进行透明cookie操作,这通常是使用层1的情形。在这个级别,你用Client类操作cookies。它有两个主要的方法: · public CookieJar getCookies(URLConnection urlConn): 这个方法从给出的URLConnection中析取cookies,将它们解析到Cookie对象,并作为一个CookieJar返回。 · public CookieJar setCookies(URLConnection urlConn, CookieJar cj): 这个方法从CookieJar中提取合适的Cookie对象并设置URLConnection的报头。 层0 这些开发者没有在使用层0的代码中深入就无法呼吸(包括我)。在这里,你可以通过使用cookie操作代码改变解析逻辑和安全规则。要这样做,首先实现CookieParser接口,它有以下四个方法: · public Header getCookieHeaders(CookieJar cj): 在CookieJar中转换Cookies为一报头以适合与一个HTTP请求一起发送。 · public boolean allowedCookie(Cookie c, URL url): 检查是否一个给出URL的请求能返回指定的Cookie。 · public CookieJar parseCookies(Header h, URL url): 在一个HTTP响应中将报头转换到一个Cookie对象的CookieJar中。 · public boolean sendCookieWithURL(Cookie c, URL url, boolean bRespectExpires): 检查是否给出的Cookie能被与给出URL的一个请求一起发送。 你能使用Client类的setCookieParser(CookieParser cp)方法去设置CookieParser实现。被库缺省使用的CookieParser是一个RFC 2965 cookie规范中的实现。 在层1,jCookie作为一个库;在层0,它成为一个API的基础。 jCookie用法 Client类在两个层都调用cookie操作逻辑。它提供了应用程序开发者的库架构。要使用jCookie库,按照下面这些步骤: · 从响应到请求检索cookies: 创建一个URLConnection对象并初始化。 连接URLConnection。 创建一个Client对象并设定一个定制的CookieParser。 通过调用Client实例的getCookies()方法得到一个Cookies的CookieJar,作为在URLConnection中的一个参数。 与HTTP响应一起作一些事情。 · 和一个请求(假定一个CookieJar已被检索)一起发送cookies: 创建一个URLConnection对象并初始化。 创建一个Client对象并设定一个定制的CookieParser。 通过调用Client实例的setCookies()方法设置cookie报头,作为URLConnection and CookieJar 中的参数。 连接URLConnection。 与HTTP响应一起作一些事情。 下面的摘录显示了普通jCookie的用法。这个jCookie代码十分突出:


import com.sonalb.net.http.cookie.*; 

import java.net.*; 

import java.io.*; 

... 

public class Example 

{ 

... 

public void someMethod() 

{ 

... 

URL url = new URL("http://www.site.com/"); 

HttpURLConnection huc = (HttpURLConnection) url.openConnection(); 

//在这里初始化HttpURLConnection. 

... 

huc.connect(); 

InputStream is = huc.getInputStream(); 

Client client = new Client(); 

CookieJar cj = client.getCookies(huc); 

//进行一些处理 

... 

huc.disconnect(); 

// 执行另一请求 

url = new URL("http://www.site.com/"); 

huc = (HttpURLConnection) url.openConnection(); 

client.setCookies(huc, cj); 

huc.connect(); 

... 

// 进行一些处理 

} 

} 



上面的代码描述了jCookie API的两个方面: · 本地java.net对象的使用(HttpURLConnection)。 · 轻易地回收和发送cookies(单个方法调用)。 在实践中,上述代码已经能成功地维护两个请求间的会话。现在我们转换层的基本结构,让我们将jCookie与一些真实代码连接。 Hotmail新邮件检测器 为了阐明jCookie库的使用方便,我将在一个显示一个Hotmail账号新消息的发件人、主题及日期字段的应用程序中使用它。为了简单起见,应用程序在控制台显示这些信息。为了在Hotmail收件箱接收新消息,应用程序需要完成以下步骤: · 在登录表单中执行一个HTTP POST操作登录Hotmail。 · 为了到达主页,操作重定向及cookies。 · 检索收件箱的HTML页。 · 提取新消息的相关字段。 多数站点要求用户第一次通过一个表单执行一个HTTP POST 操作以完成登录过程。为了成功鉴定身份,POST的响应通常是一个带一些cookie报头的HTTP重定向。当重定向页被请求时cookies返回给服务器。 jCookie库包括一个很有用的类叫HTTPRedirectHandler,它管理当完成客户端cookie操作时操作重定向的普通任务。要使用这个类,首先要在一个未连接的HttpURLConnection中创建一个HTTPRedirectHandler实例,然后调用HTTPRedirectHandler实例的connect()方法去操作重定向及cookie。句柄从HTTP响应代码中确定是否运行成功。一旦进程完成,调用的类就检索表明最后一次请求的HttpURLConnection对象。CookieJar包含所有在能被检索的重定向过程中接收的cookies。Cookie操作逻辑存在于HTTPRedirectHandler的connect()方法中。让我们来看一看这个方法的代码。Cookie操作部份进行了注释:


package com.sonalb.net.http; 

import com.sonalb.net.http.cookie.*; 

import java.net.*; 

import java.io.*; 

public class HTTPRedirectHandler 

{ 

... 

public HTTPRedirectHandler(HttpURLConnection huc) 

{ 

... 

} 

public void connect() throws IOException 

{ 

if(bConnected) 

{ 

throw new IllegalStateException("No can do. Already connected."); 

} 

int code; 

URL url; 

huc.setFollowRedirects(false); 

// 设置在Cookies中的检验 

if(!cj.isEmpty()) 

{ 

client.setCookies(huc,cj); 

} 

is = huc.getInputStream(); 

// 从HttpURLConnection中提取Cookies并加到CookieJar中去 

cj.addAll(Client.getCookies(huc)); 

while((code = huc.getResponseCode()) != successCode && maxRedirects > 0) 

{ 

if(code != 302) 

{ 

throw new IOException("Can't deal with this code ("   code   ")."); 

} 

is.close(); 

is = null; 

url = new URL(huc.getHeaderField("location")); 

huc.disconnect(); 

huc = null; 

huc = (HttpURLConnection) url.openConnection(); 

//和HTTP请求一起发送Cookies 

Client.setCookies(huc, cj); 

huc.setFollowRedirects(false); 

huc.connect(); 

is = huc.getInputStream(); 

//从响应中提取Cookies并加进jar中去 

cj.addAll(Client.getCookies(huc)); 

maxRedirects--; 

} 

if(maxRedirects <= 0 && code != successCode) 

{ 

throw new IOException("Max redirects exhausted."); 

} 

bConnected = true; 

} 

//其他方法在这里出现 

public void handleCookies(boolean b) 

{ 

... 

} 

public void setSuccessCode(int i) 

{ 

... 

} 

public void setCookieJar(CookieJar cj) 

{ 

... 

} 

public void addCookies(CookieJar cj) 

{ 

... 

} 

public CookieJar getCookieJar() 

{ 

... 

} 

public HttpURLConnection getConnection() 

{ 

... 

} 

public void setMaxRedirects(int i) 

{ 

... 

}  

} 



HotmailChecker应用程序使用HTTPRedirectHandler进行登录操作。应用程序从使用带有并发请求的HTTPRedirectHandler中检索CookieJar。HotmailChecker的相关部份显示如下。Hotmail细节和jCookie关联注释被突出显示:


public boolean doLogin() throws Exception 

{ 

//对于HTTPS初始化JSSE 

System.getProperties().put("java.protocol.handler.pkgs","com.sun.net.ssl.internal.www.protocol"); 

java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); 

//创建HttpURLConnection并初始化 

URL url = new URL("https://lc2.law13.hotmail.passport.com/cgi-bin/dologin"); 

HttpURLConnection huc = (HttpURLConnection) url.openConnection(); 

huc.setDoOutput(true); 

huc.setRequestMethod("POST"); 

huc.setRequestProperty("User-Agent","Mozilla/4.7 [en] (Win98; I)"); 

//发送登录表单字段 

StringBuffer sb = new StringBuffer(); 

sb.append("login="); sb.append(URLEncoder.encode(user)); 

... 

OutputStream os = huc.getOutputStream(); 

os.write(sb.toString().getBytes("US-ASCII")); 

os.close(); 

//创建句柄并进行处理 

HTTPRedirectHandler hrh = new HTTPRedirectHandler(huc); 

hrh.connect(); 

huc = hrh.getConnection(); 

//Microsoft有一个中间过渡页使用了一个刷新元标签以便于在HTTPS和HTTP间转换,这将防止安全 

//警告弹出 

//我们需要通过读取响应和解析URL手动取出URL 

BufferedReader br = new BufferedReader(new InputStreamReader(huc.getInputStream())); 

... 

//一旦我们有了主页的URL,我们就又使用HTTPRedirectHandler重定向并处理响应以校验正确的注 

//册 

url = new URL(homeUrl); 

huc = (HttpURLConnection) url.openConnection(); 

huc.setRequestProperty("User-Agent","Mozilla/4.7 [en] (Win98; I)"); 

hrh = new HTTPRedirectHandler(huc); 

hrh.setCookieJar(cj); 

hrh.connect(); 

... 

//保存Cookies用于以后的请求 

cj.addAll(hrh.getCookieJar()); 

... 

return(bLoggedIn); 

} 



现在我们已经登录到Hotmail,我们请求收件箱页,在登录过程中已检索的Cookies中通过。一旦我们拥有了收件箱页,我们必须因为与新消息有关的信息而解析这个HTML。代替使用暴力的StringTokenizer检索这个信息,我们将用一个稍微文雅(既复杂的)方法调控XML。这种方法包括: · 将成形不好的HTML转换为well-formed HTML。 · 用DOM(文档对象模型)通过well-formed HTML去得到新消息的信息。 假如DOM、XML和well-formed 对你来说一窍不通,只要说我们把收件箱HTML转换成一个树状结构的对象并得到想要的信息就足够了。 要将成形不好的HTML转换成well-formed HTML,我们用一个可自由下载的组件JTidy工具和一个通用的处理器。ConvertBadHTMLToGood帮助类将成形不好的Hotmail HTML转换成well-formed HTML。相关代码显示如下:


import java.io.*; 

import org.w3c.tidy.*; 

public class ConvertBadHTMLToGood 

{ 

... 

public ConvertBadHTMLToGood(Reader r) 

{ 

if(r == null) 

{ 

throw new IllegalArgumentException(); 

} 

inReader = r; 

} 

public Reader doConvert() throws IOException 

{ 

//初始化JTidy对象 

Tidy tidy = new Tidy(); 

tidy.setXmlOut(true); 

tidy.setErrout(new PrintWriter(new StringWriter())); 

//JTidy解析器要求一个InputStream,对于我的知识来说这里没有直接的办法将一个Reader转换 

//成一个InputStream。这个工作区代码没有字符编码安全,但还可以混过。 

BufferedReader br = new BufferedReader(inReader); 

StringBuffer sb = new StringBuffer(); 

String line; 

while((line = br.readLine()) != null) 

{ 

sb.append(line); 

sb.append("/n"); 

} 

ByteArrayInputStream bais = new ByteArrayInputStream(sb.toString().getBytes("US-ASCII")); 

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

//作一个将HTML转换well-formed HTML 的预备。 

tidy.parse(bais, baos); 

//整理一些遗漏的JTidy得到能被“true-blue”XML解析器解析的输出。 

FixEntities fe = new FixEntities(baos.toString()); 

return(fe.getFixedReader()); 

} 



一旦我们拥有了well-formed HTML,我们就用XML解析的Java API(JAXP)去转换well-formed HTML 成一个DOM树并通过树得到新消息的表单、主题及日期字段。我将忽略一些代码而向你展示如何使用HotmailChecker:


import com.sonalb.net.http.cookie.*; 

... 

public class HotmailChecker 

{ 

public static void main(String args[]) throws Exception 

{ 

if(args.length != 2) 

{ 

usage(); 

System.exit(0); 

} 

String uname = args[0]; 

String pass = args[1]; 

HotmailChecker hmc = new HotmailChecker(uname,pass); 

if(!hmc.doLogin()) 

{ 

System.out.println("Could not login to Hotmail."); 

System.exit(0); 

} 

Vector newMessages = hmc.getNewMessages(); 

if(newMessages == null) 

{ 

System.out.println("No NEW Messages."); 

return; 

} 

System.out.println("You have "   newMessages.size()   " NEW Messages"); 

System.out.println("---------------------------------------------"); 

Iterator iter = newMessages.iterator(); 

//HMMessage封装了一个Hotmail消息 

HMMessage hm; 

while(iter.hasNext()) 

{ 

hm = (HMMessage) iter.next(); 

System.out.println(" From: "   hm.getFrom()); 

System.out.println(" Subject: "   hm.getSubject()); 

System.out.println("Sent Date: "   hm.getSentDate()); 

System.out.println("---------------------------------------------"); 

} 

} 

static void usage() 

{ 

System.out.println("/nUsage: java HotmailChecker 
      
       
       
       
        
        "); 

} 

//实例变量和方法从这里开始 

... 

public HotmailChecker(String username, String password) 

{ 

... 

} 

public boolean doLogin() throws Exception 

{ 

... 

} 

public Vector getNewMessages() throws Exception 

{ 

... 

} 

... 

} 




       
       
      
      
你可以从 Resources下载完全功能的HotmailChecker及相关类。 Java中的cookie管理方案(1)-与J2ME结合 Java中的cookie管理方案(2)-与J2ME结合 Java中的cookie管理方案(3)-与J2ME结合 Java中的cookie管理方案(4)-与J2ME结合
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值