HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程式需要直接通過 HTTP 協議來訪問網路資源。
http的主要功能包括:
1. 實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
2. 支援自動轉向
3. 支援 HTTPS 協議
4. 支援Proxy 伺服器等
使用 HttpClient 需要以下 6 個步驟:
1. 建立 HttpClient 的執行個體
2. 建立某種串連方法的執行個體,在這裡是 GetMethod。在 GetMethod 的建構函式中傳入待串連的地址
3. 調用第一步中建立好的執行個體的 execute 方法來執行第二步中建立好的 method 執行個體
4. 讀 response
5. 釋放串連。無論執行方法是否成功,都必須釋放串連
6. 對得到後的內容進行處理
根據以上步驟,我們來編寫用GET方法來取得某網頁內容的代碼。
大部分情況下 HttpClient 預設的建構函式已經足夠使用。
HttpClient httpClient = new HttpClient();
建立GET方法的執行個體。在GET方法的建構函式中傳入待串連的地址即可。用GetMethod將會自動處理轉寄過程,如果想要把自動處理轉寄過程去掉的話,可以調用方法setFollowRedirects(false)。
GetMethod getMethod = new GetMethod(http://www.ibm.com/);
調用執行個體httpClient的executeMethod方法來執行getMethod。由於是執行在網路上的程式,在運行executeMethod方法的時候,需要處理兩個異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是在構造getMethod的時候傳入的協議不對,比如不小心將"http"寫成"htp",或者伺服器端返回的內容不正常等,並且該異常發生是不可恢複的;第二種異常一般是由於網路原因引起的異常,對於這種異常 (IOException),HttpClient會根據你指定的恢複策略自動試著重新執行executeMethod方法。HttpClient的恢複策略可以自訂(通過實現介面HttpMethodRetryHandler來實現)。通過httpClient的方法setParameter設定你實現的恢複策略,本文中使用的是系統提供的預設恢複策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod傳回值是一個整數,表示了執行該方法後伺服器返回的狀態代碼,該狀態代碼能表示出該方法執行是否成功、需要認證或者頁面發生了跳轉(預設狀態下GetMethod的執行個體是自動處理跳轉的)等。
Java代碼
//設定成了預設的恢複策略,在發生異常時候將自動重試3次,在這裡你也可以設定成自訂的恢複策略
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
//執行getMethod
int statusCode = client.executeMethod(getMethod);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + getMethod.getStatusLine());
}
//設定成了預設的恢複策略,在發生異常時候將自動重試3次,在這裡你也可以設定成自訂的恢複策略
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
//執行getMethod
int statusCode = client.executeMethod(getMethod);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + getMethod.getStatusLine());
}
在返回的狀態代碼正確後,即可取得內容。取得目標地址的內容有三種方法:第一種,getResponseBody,該方法返回的是目標的二進位的byte流;第二種,getResponseBodyAsString,這個方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據系統預設的編碼方式,所以返回的String值可能編碼類別型有誤,在本文的"字元編碼"部分中將對此做詳細介紹;第三種,getResponseBodyAsStream,這個方法對於目標地址中有大量資料需要傳輸是最佳的。在這裡我們使用了最簡單的getResponseBody方法。
釋放串連。無論執行方法是否成功,都必須釋放串連。
method.releaseConnection();
處理內容。在這一步中根據你的需要處理內容,在例子中只是簡單的將內容列印到控制台。
System.out.println(new String(responseBody));
完整的程式碼範例
Java代碼
public class FeedBackServiceImpl implements FeedBackService, InitializingBean {
private static final Logger log = LoggerFactory.getLogger(FeedBackServiceImpl.class);
private static final int CONNECTION_TIME_OUT = 1000;
private static final int TIME_OUT = 2000;
/**
* 參數
*/
private static final String PARAM_ID = "id";
private static final String PARAM_QUESTION_ID = "questionId";
private static final String PARAM_ANSWER = "answer";
private static final String PARAM_COOKIE_ID = "cookieId";
/**
* 蓋婭系統擷取調查問卷的url
*/
private String feedBackQuestionaireUrl;
/**
* 蓋婭系統儲存使用者反饋資訊的url
*/
private String feedBackAnswerUrl;
/**
* 問卷類型與問卷id的映射
*
* <pre>
* 問卷類型,從前台傳遞過來。目前有兩個取值:"1"表示進貨單頁面的問卷;"2"表示確認訂單頁面的問卷
* 問卷id,作為從蓋婭系統中擷取調查問卷的參數
* </pre>
*/
private Map<String, String> questionTypeToQuestionId = new HashMap<String, String>();
private HttpClient httpClient;
public boolean addFeedBack(FeedBackModel feedBackModel) {
if (feedBackModel == null) {
return false;
}
boolean res = false;
// 調用蓋婭系統的介面,提交反饋
PostMethod postMethod = new PostMethod(feedBackAnswerUrl);
postMethod.addParameter(PARAM_QUESTION_ID, feedBackModel.getQuestionId());
postMethod.addParameter(PARAM_ANSWER, feedBackModel.getAnswer());
postMethod.addParameter(PARAM_COOKIE_ID, feedBackModel.getCookieId());
try {
int statusCode = httpClient.executeMethod(postMethod);
if (statusCode != HttpStatus.SC_OK) {
StringBuilder sb = new StringBuilder("fail to add feedback, requestUrl=");
sb.append(feedBackAnswerUrl).append(", parameter: ").append(feedBackModel.toString()).append(", HTTP StatusCode=").append(statusCode);
log.error(sb.toString());
res = false;
} else {
res = true;
}
} catch (HttpException e) {
log.error("HttpException occured when addFeedBack, requestUrl=" + feedBackAnswerUrl + ", parameter: " + feedBackModel.toString(), e);
res = false;
} catch (IOException e) {
log.error("IOException occured when addFeedBack, requestUrl=" + feedBackAnswerUrl + ", parameter: " + feedBackModel.toString(), e);
res = false;
} finally {
postMethod.releaseConnection();
postMethod = null;
}
return res;
}
public JSONObject getQuestionaire(String questionType) {
String id = questionTypeToQuestionId.get(questionType);
if (StringUtil.isBlank(id)) {
return null;
}
// 調用蓋婭系統的介面,擷取調查問卷
GetMethod getMethod = new GetMethod(feedBackQuestionaireUrl);
NameValuePair param = new NameValuePair(PARAM_ID, id);
getMethod.setQueryString(new NameValuePair[]{param});
String responseText = null;
try {
// 執行getMethod
int statusCode = httpClient.executeMethod(getMethod);
if (statusCode != HttpStatus.SC_OK) {
StringBuilder sb = new StringBuilder("fail to getQuestionaire, requestUrl=");
sb.append(feedBackQuestionaireUrl).append("?id=").append(id).append(", HTTP StatusCode=").append(statusCode);
log.error(sb.toString());
return null;
}
// 讀取內容
responseText = getMethod.getResponseBodyAsString();
} catch (HttpException e) {
StringBuilder sb = new StringBuilder("HttpException occured when getQuestionaire, requestUrl=");
sb.append(feedBackQuestionaireUrl).append("?id=").append(id);
log.error(sb.toString(), e);
return null;
} catch (IOException e) {
StringBuilder sb = new StringBuilder("IOException occured when getQuestionaire, requestUrl=");
sb.append(feedBackQuestionaireUrl).append("?id=").append(id);
log.error(sb.toString(), e);
return null;
} finally {
getMethod.releaseConnection();
getMethod = null;
}
if (StringUtil.isBlank(responseText)) {
return null;
}
// 從查詢結果中解析出包含問卷的json字串
int index = responseText.indexOf("=");
if (index >= 0) {
responseText = responseText.substring(index + 1);
}
try {
JSONObject json = JSONObject.fromObject(responseText);
return json;
} catch (Exception e) {
log.error("fail to change from String to JSONObject, string=" + responseText, e);
return null;
}
}
public void afterPropertiesSet() throws Exception {
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
httpClient = new HttpClient(connectionManager);
httpClient.setConnectionTimeout(CONNECTION_TIME_OUT);
httpClient.setTimeout(TIME_OUT);
}
作者“hwy584624785”