HttpClient 是 Apache Jakarta Common 下的子項目可以用來提供支持 HTTP 協議的客戶端編程工具包模擬浏覽器的行為它提供了很多的方法來簡化網絡的訪問雖然大部分的功能可以使用較底層的 HttpURLConnection 來實現例如
實現了所有 HTTP 的方法( GETPOST 等)
支持 HTTPS 協議
支持代理服務器
自動維護 Cookies 等
我們知道 http 協議是面向無連接的要維持會話現在基本上都是采用基於 Cookies 的方式( Session 機制也是通過 Cookies 實現的)所以 HttpClient 的自動維護 Cookies 的方式對我們的登錄發帖回復非常有用(一般網站都需要先登錄再發帖回復)
下面的 例子都是采用 commons 包來實現的(雖然 commons 已經發布但是代碼發生了較大的重構調用方式也發生了很大的改變)
下載 jar 包的路徑為
由於 httpclient 使用了 Apache Jakarta common 下的子項目 logging 和 codec 所以也需要在 下載這兩個包
commonsloggingjar
commonscodecjar
為了更好地理解代碼設計的 UML 類圖如下
方法調用的時序圖如下
其中 BrowserContext 類代表浏覽器上下文對象維護 HttpClient 鏈接和 Cookies KaixinSitePost 是負責實現開心網的具體登錄發帖回復邏輯的類
BrowserContext 的代碼如下
/** */ /**
* Copyright (C):
* @author 陳新漢
* Aug :: PM
*/
/** */ /**
* 浏覽器進程上下文
*/
public class BrowserContext
{
private HttpClient client; // 注意每個站點和每個用戶對應一個單獨的BrowserContext對象
private Cookie[] cookies = new Cookie[ ]; // 維護Cookies
private Proxyips proxyip = null ; // 當前的代理IP
private Siteusers user = null ; // 當前的登錄用戶
public Cookie[] getCookies() {
return cookies;
}
public void setCookies(Cookie[] cookies) {
okies = cookies;
}
public void addCookie(Cookie c) {
if (cookies != null && cookieslength > ) {
Cookie[] others = new Cookie[cookieslength + ];
Systemarraycopy(cookies others cookieslength);
others[otherslength ] = c;
cookies = others;
} else {
cookies = new Cookie[ ];
cookies[ ] = c;
}
}
public Proxyips getProxyip() {
return proxyip;
}
public void setProxyip(Proxyips proxyip) {
this proxyip = proxyip;
if ( this proxyip != null ) {
clientgetHostConfiguration()setProxy(proxyipgetIp()proxyipgetPort());
clientgetParams()setAuthenticationPreemptive( true );
// 如果代理需要密碼驗證這裡設置用戶名密碼
// clientgetState()setProxyCredentials(AuthScopeANY new UsernamePasswordCredentials());
}
}
public HttpClient getClient() {
return client;
}
public Siteusers getUser() {
return user;
}
public void setUser(Siteusers user) {
this user = user;
}
private BrowserContext(Site site) {
super ();
Protocol myhttps = new Protocol( https new MySecureProtocolSocketFactory() );
ProtocolregisterProtocol( https myhttps);
client = new HttpClient();
clientgetParams()setCookiePolicy(CookiePolicyBROWSER_COMPATIBILITY);
HttpConnectionManagerParams managerParams = clientgetHttpConnectionManager()getParams();
// 設置連接超時時間(單位毫秒)
// managerParamssetConnectionTimeout();
// 設置讀數據超時時間(單位毫秒)
// managerParamssetSoTimeout();
initForSiteVisit(sitegetSite()sitegetPort()sitegetCharset());
}
public BrowserContext(Site siteProxyips proxyip) {
this (site);
this setProxyip(proxyip);
}
private void initForSiteVisit(String siteurl int portString charset) {
clientgetHostConfiguration()setHost(siteurl port http );
// 解決中文亂碼問題和指定網站的頁面編碼一致
clientgetParams()setParameter(HttpMethodParamsHTTP_CONTENT_CHARSET charset);
}
// 查看cookie信息
public void printCookies()
{
Systemoutprintln( Cookie );
if (cookies != null ) {
for (Cookie c:cookies) {
Systemoutprintln(cgetName() + : + cgetValue());
}
} else {
Systemoutprintln( 沒有設置Cookies );
}
Systemoutprintln( Cookie );
}
public void setCommonMethodRequestHeaders(HttpMethodBase method)
{
methodsetRequestHeader( Accept */* );
// methodsetRequestHeader(AcceptLanguage zhcn);
// methodsetRequestHeader(AcceptEncoding gzipdeflate);
methodsetRequestHeader( UserAgent Mozilla/ (compatible; MSIE ; Windows NT ;) );
// 設置非常重要
methodsetRequestHeader( Connection KeepAlive );
}
public String redirectToURL(String url) throws IOException
{
if (url != null ) {
try {
Systemoutprintln( 頁面重定向到 + url);
String responseString = this doCommonVisitWithURL(url);
// Systemoutprintln(responseString);
return responseString;
} catch (IOException e) {
Systemoutprintln( 重定向 + url + 出錯 );
}
} else {
Systemoutprintln( redirect url is null );
}
return null ;
}
public String doCommonVisitWithURL(String url) throws IOException {
GetMethod get = new GetMethod(url);
return this doGet(get);
}
public String doPost(ExpectContinueMethod post) throws IOException
{
if (post == null )
return null ;
try
{
if (getCookies() != null ) {
// printCookies();
clientgetState()addCookies(cookies);
postaddRequestHeader( Cookie getCookies()toString());
// Systemoutprintln(postgetRequestHeader(Cookie)getValue());
}
setCommonMethodRequestHeaders(post);
int statusCode = clientexecuteMethod(post);
cookies = clientgetState()getCookies();
Systemoutprintln(statusCode);
// Systemoutprintln(postgetResponseHeader(Location));
String responseString = postgetResponseBodyAsString();
Systemoutprintln(responseString);
printCookies();
postreleaseConnection();
if (statusCode == || statusCode == ) {
redirectToURL(postgetResponseHeader( Location )getValue());
}
return responseString;
}
finally {
if (post != null )
postreleaseConnection();
}
}
public String doGet(GetMethod get) throws IOException
{
if (get == null )
return null ;
if (cookies != null ) {
// printCookies();
clientgetState()addCookies(cookies);
getaddRequestHeader( Cookie cookiestoString());
}
try {
setCommonMethodRequestHeaders(get);
int statusCode = clientexecuteMethod(get);
cookies = clientgetState()getCookies(); // 重新保存Cookies
printCookies();
Systemoutprintln(statusCode);
if (statusCode == || statusCode == ) {
redirectToURL(getgetResponseHeader( Location )getValue());
}
String responseString = getgetResponseBodyAsString();
// Systemoutprintln(responseString);
return responseString;
}
finally {
if (get != null )
getreleaseConnection();
}
}
public String getRedirectURL(String content)
{
if (content != null && contentindexOf( windowlocation=\ )!=){
int begin = contentindexOf( windowlocation=\ );
int end = contentindexOf( \ begin+);
return contentsubstring(begin + end);
}
return null ;
}
}
KaixinSitePost類的代碼
/** *//**
* Copyright (C):
* @author 陳新漢
* Aug :: AM
*/
/** *//**
* 模擬測試網站(不需要驗證碼)
* 開心網()
*/
public class KaixinSitePost implements ISitePost
{
private static final String LOGON_SITE = ;
private static final int LOGON_PORT = ;
private static final String CHARSET=UTF;
private BrowserContext context=null;
//單個用戶登錄
public String login(Siteusers userinfo Proxyips ip)
{
if(userinfo!=null)
{
SiteLogin login=new SiteLogin(context);
if(ip!=null)
logingetContext()setProxyip(ip);
Map<StringString> params=new HashMap<StringString>();
paramsput(ss );
paramsput(loginregFrom index);
paramsput(origURL );
paramsput(email userinfogetUsername());
paramsput(password userinfogetUserpwd());
loginaddRequestParameters(params);
return loginlogin(userinfo);
}
return null;
}
public List<Siteboards> parseBoard(Siteboards data) {
return null;
}
public String post(Postinfos postinfoList<Siteboards> siteboards)
{
if(postinfo!=null && siteboards!=null){
SitePost sport=new SitePost(context);
contextgetClient()getHostConfiguration()setHost();
Map<StringString> params=new HashMap<StringString>();
paramsput(categoryId );
paramsput(blogControl );
paramsput(title postinfogetTitle());
paramsput(bodypostinfogetContent());
sportaddRequestParameters(params);
for(Siteboards sb:siteboards){
sbsetPostUrl();
try{
sportpost(postinfo sb);
}catch(IOException e){
eprintStackTrace();
}
}
}
return null;
}
public String reply(Postinfos postinfoList<Articleinfos> arts)
{
return null;
}
/** *//**
* @param args
*/
public static void main(String[] args)
{
try
{
Siteusers userinfo=new Siteusers();
userinfosetUsername(xxxx);
userinfosetUserpwd(xxxx);
Proxyips ips = new Proxyips();
ipssetIp();
ipssetPort();
KaixinSitePost sp=new KaixinSitePost();
splogin(userinfoips);
Postinfos post=new Postinfos();
postsetContent(<p>lllllllllllllllllllllll</p>);
postsetTitle(中文測試);
List<Siteboards> siteboards=new ArrayList<Siteboards>();
siteboardsadd(new Siteboards());
siteboardsadd(new Siteboards());
sppost(postsiteboards);
}
catch(Exception e){
eprintStackTrace();
}
}
}
封裝登錄的類SiteLogin
/** *//**
* Copyright (C):
* @author 陳新漢
* Aug :: PM
*/
/** *//**
* 站點登錄
*/
public class SiteLogin extends AbstractMethodAdapter
{
private HttpMethodBase method;
private boolean ispost=true;
protected BrowserContext context; //當前的浏覽器進程上下文
public BrowserContext getContext() {
return context;
}
/** *//**
* 構造函數
* @param context
* @param url
* @param ispost 設置是否POST方式提交默認為POST
*/
public SiteLogin(BrowserContext contextString urlboolean ispost) {
super();
ntext = context;
thisispost=ispost;
method = thisispost?new PostMethod(url):new GetMethod(url);
}
public SiteLogin(BrowserContext contextString url) {
this(contexturltrue);
}
public String login(Siteusers user)
{
int statusCode=;
if(thisispost && thishasRequestParameters()){
((PostMethod)method)setRequestBody(thisgetRequestParams());
}
if(thishasExtraRequestHeaders()){
thisaddExtraRequestHeaders(methodthisgetExtraRequestHeaders());
}
contextsetCommonMethodRequestHeaders(method);
try
{
if(contextgetCookies()!=null){
//printCookies();
contextgetClient()getState()addCookies(contextgetCookies());
methodaddRequestHeader(Cookie contextgetCookies()toString());
}
statusCode = contextgetClient()executeMethod(method);
contextsetCookies(contextgetClient()getState()getCookies());
String responseString = methodgetResponseBodyAsString();
//Systemoutprintln(responseString);
methodreleaseConnection();
if(statusCode==HttpStatusSC_OK){
Systemoutprintln(登錄成功);
return responseString;
}
else if(statusCode== ||statusCode==){
Systemoutprintln(登錄成功頁面重定向);
String url=methodgetResponseHeader(Location)getValue();
return contextredirectToURL(url);
}
else{
Systemoutprintln(登錄失敗狀態碼+statusCode);
}
}catch(Exception e){
eprintStackTrace();
}finally{
if(method!=null)
methodreleaseConnection();
}
return null;
}
}
封裝站點發帖的類SitePost
/** *//**
* Copyright (C):
* @author 陳新漢
* Aug :: PM
*/
/** *//**
* 站點發帖新帖
*/
public class SitePost extends CommonSitePost
{
public SitePost(BrowserContext context) {
super();
ntext=context;
}
public String post(Postinfos postinfoSiteboards siteboard) throws IOException
{
if (postinfo != null && siteboard != null) {
if (StringUtilsisNotEmpty(siteboardgetPostUrl())) {
PostMethod post = new PostMethod(siteboardgetPostUrl());
if(thishasRequestParameters()){
postsetRequestBody(thisgetRequestParams());
}
if(thishasExtraRequestHeaders()){
thisaddExtraRequestHeaders(postthisgetExtraRequestHeaders());
}
contextsetCommonMethodRequestHeaders(post);
ntextdoPost(post);
}else{
Systemoutprintln(版面的新帖提交地址不能為空!);
}
}else{
Systemoutprintln(帖子或者版面信息輸入都不能為空);
}
return null;
}
}
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25911.html