# 第一章 基礎
## 1.1 執行請求
HttpClient最重要的功能是執行HTTP方法。一個HTTP方法的執行包含一個或多個HTTP請求/HTTP響應交換,通常由HttpClient的內部來處理。而期望用戶提供一個要執行的請求對象,而HttpClient期望傳輸請求到目標服務器并返回對應的響應對象,或者當執行不成功時拋出異常。
很自然地,HttpClient API的主要切入點就是定義描述上述規約的HttpClient接口。
這里有一個很簡單的請求執行過程的示例:
```
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int l;
byte[] tmp = new byte[2048];
while ((l = instream.read(tmp)) != -1) {
}
}
```
### 1.1.1 HTTP請求
所有HTTP請求有一個組合了方法名,請求URI和HTTP協議版本的請求行。
HttpClient支持所有定義在HTTP/1.1版本中的HTTP方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。對于每個方法類型都有一個特殊的類:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace和HttpOptions。
請求的URI是統一資源定位符,它標識了應用于哪個請求之上的資源。HTTP請求URI包含一個協議模式,主機名稱,可選的端口,資源路徑,可選的查詢和可選的片段。
```
HttpGet httpget = new HttpGet(
"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
```
HttpClient提供很多工具方法來簡化創建和修改執行URI。 URI也可以編程來拼裝:
```
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
"q=httpclient&btnG=Google+Search&aq=f&oq=", null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
```
輸出內容為:
```
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
```
查詢字符串也可以從獨立的參數中來生成:
```
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("q", "httpclient"));
qparams.add(new BasicNameValuePair("btnG", "Google Search"));
qparams.add(new BasicNameValuePair("aq", "f"));
qparams.add(new BasicNameValuePair("oq", null));
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
URLEncodedUtils.format(qparams, "UTF-8"), null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
```
輸出內容為:
```
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
```
### 1.1.2 HTTP響應
HTTP響應是由服務器在接收和解釋請求報文之后返回發送給客戶端的報文。響應報文的第一行包含了協議版本,之后是數字狀態碼和相關聯的文本段。
```
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());
```
輸出內容為:
```
HTTP/1.1
200
OK
HTTP/1.1 200 OK
```
### 1.1.3 處理報文頭部
一個HTTP報文可以包含很多描述如內容長度,內容類型等信息屬性的頭部信息。
HttpClient提供獲取,添加,移除和枚舉頭部信息的方法。
```
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie",
"c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie",
"c2=b; path=\"/\", c3=c; domain=\"localhost\"");
Header h1 = response.getFirstHeader("Set-Cookie");
System.out.println(h1);
Header h2 = response.getLastHeader("Set-Cookie");
System.out.println(h2);
Header[] hs = response.getHeaders("Set-Cookie");
System.out.println(hs.length);
```
輸出內容為:
```
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
```
獲得給定類型的所有頭部信息最有效的方式是使用HeaderIterator接口。
```
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie",
"c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie",
"c2=b; path=\"/\", c3=c; domain=\"localhost\"");
HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
System.out.println(it.next());
}
```
輸出內容為:
```
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
```
它也提供解析HTTP報文到獨立頭部信息元素的方法方法。
```
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie",
"c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie",
"c2=b; path=\"/\", c3=c; domain=\"localhost\"");
HeaderElementIterator it = new BasicHeaderElementIterator(
response.headerIterator("Set-Cookie"));
while (it.hasNext()) {
HeaderElement elem = it.nextElement();
System.out.println(elem.getName() + " = " + elem.getValue());
NameValuePair[] params = elem.getParameters();
for (int i = 0; i < params.length; i++) {
System.out.println(" " + params[i]);
}
}
```
輸出內容為:
```
c1 = a
path=/
domain=localhost
c2 = b
path=/
c3 = c
domain=localhost
```
### 1.1.4 HTTP實體
HTTP報文可以攜帶和請求或響應相關的內容實體。實體可以在一些請求和響應中找到,因為它們也是可選的。使用了實體的請求被稱為封閉實體請求。HTTP規范定義了兩種封閉實體的方法:POST和PUT。響應通常期望包含一個內容實體。這個規則也有特例,比如HEAD方法的響應和204 No Content,304 Not Modified和205 Reset Content響應。
HttpClient根據其內容出自何處區分三種類型的實體:
* streamed流式:內容從流中獲得,或者在運行中產生。特別是這種分類包含從HTTP響應中獲取的實體。流式實體是不可重復生成的。
* self-contained自我包含式:內容在內存中或通過獨立的連接或其它實體中獲得。自我包含式的實體是可以重復生成的。這種類型的實體會經常用于封閉HTTP請求的實體。
* wrapping包裝式:內容從另外一個實體中獲得。
當從一個HTTP響應中獲取流式內容時,這個區別對于連接管理很重要。對于由應用程序創建而且只使用HttpClient發送的請求實體,流式和自我包含式的不同就不那么重要了。這種情況下,建議考慮如流式這種不能重復的實體,和可以重復的自我包含式實體。
##### 1.1.4.1 重復實體
實體可以重復,意味著它的內容可以被多次讀取。這就僅僅是自我包含式的實體了(像ByteArrayEntity或StringEntity)。
##### 1.1.4.2 使用HTTP實體
因為一個實體既可以代表二進制內容又可以代表字符內容,它也支持字符編碼(支持后者也就是字符內容)。
實體是當使用封閉內容執行請求,或當請求已經成功執行,或當響應體結果發功到客戶端時創建的。
要從實體中讀取內容,可以通過HttpEntity#getContent()方法從輸入流中獲取,這會返回一個java.io.InputStream對象,或者提供一個輸出流到HttpEntity#writeTo(OutputStream)方法中,這會一次返回所有寫入到給定流中的內容。
當實體通過一個收到的報文獲取時,HttpEntity#getContentType()方法和HttpEntity#getContentLength()方法可以用來讀取通用的元數據,如Content-Type和Content-Length頭部信息(如果它們是可用的)。因為頭部信息Content-Type可以包含對文本MIME類型的字符編碼,比如text/plain或text/html,HttpEntity#getContentEncoding()方法用來讀取這個信息。如果頭部信息不可用,那么就返回長度-1,而對于內容類型返回NULL。如果頭部信息Content-Type是可用的,那么就會返回一個Header對象。
當為一個傳出報文創建實體時,這個元數據不得不通過實體創建器來提供。
```
StringEntity myEntity = new StringEntity("important message",
"UTF-8");
System.out.println(myEntity.getContentType());
System.out.println(myEntity.getContentLength());
System.out.println(EntityUtils.getContentCharSet(myEntity));
System.out.println(EntityUtils.toString(myEntity));
System.out.println(EntityUtils.toByteArray(myEntity).length);
```
輸出內容為
Content-Type: text/plain; charset=UTF-8 17 UTF-8 important message 17
### 1.1.5 確保低級別資源釋放
當完成一個響應實體,那么保證所有實體內容已經被完全消耗是很重要的,所以連接可以安全的放回到連接池中,而且可以通過連接管理器對后續的請求重用連接。處理這個操作的最方便的方法是調用HttpEntity#consumeContent()方法來消耗流中的任意可用內容。HttpClient探測到內容流尾部已經到達后,會立即會自動釋放低層連接,并放回到連接管理器。HttpEntity#consumeContent()方法調用多次也是安全的。
也可能會有特殊情況,當整個響應內容的一小部分需要獲取,消耗剩余內容而損失性能,還有重用連接的代價太高,則可以僅僅通過調用HttpUriRequest#abort()方法來中止請求。
```
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int byteOne = instream.read();
int byteTwo = instream.read();
// Do not need the rest
httpget.abort();
}
```
連接不會被重用,但是由它持有的所有級別的資源將會被正確釋放。
### 1.1.6 消耗實體內容
推薦消耗實體內容的方式是使用它的HttpEntity#getContent()或HttpEntity#writeTo(OutputStream)方法。HttpClient也自帶EntityUtils類,這會暴露出一些靜態方法,這些方法可以更加容易地從實體中讀取內容或信息。代替直接讀取java.io.InputStream,也可以使用這個類中的方法以字符串/字節數組的形式獲取整個內容體。然而,EntityUtils的使用是強烈不鼓勵的,除非響應實體源自可靠的HTTP服務器和已知的長度限制。
```
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
System.out.println(EntityUtils.toString(entity));
} else {
// Stream content out
}
}
```
在一些情況下可能會不止一次的讀取實體。此時實體內容必須以某種方式在內存或磁盤上被緩沖起來。最簡單的方法是通過使用BufferedHttpEntity類來包裝源實體完成。這會引起源實體內容被讀取到內存的緩沖區中。在其它所有方式中,實體包裝器將會得到源實體。
```
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
}
```
### 1.1.7 生成實體內容
HttpClient提供一些類,它們可以用于生成通過HTTP連接獲得內容的有效輸出流。為了封閉實體從HTTP請求中獲得的輸出內容,那些類的實例可以和封閉如POST和PUT請求的實體相關聯。HttpClient為很多公用的數據容器,比如字符串,字節數組,輸入流和文件提供了一些類:StringEntity,ByteArrayEntity,InputStreamEntity和FileEntity。
```
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file, "text/plain; charset=\"UTF-8\"");
HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);
```
請注意InputStreamEntity是不可重復的,因為它僅僅能從低層數據流中讀取一次內容。通常來說,我們推薦實現一個定制的HttpEntity類,這是自我包含式的,用來代替使用通用的InputStreamEntity。FileEntity也是一個很好的起點。
##### 1.1.7.1 動態內容實體
通常來說,HTTP實體需要基于特定的執行上下文來動態地生成。通過使用EntityTemplate實體類和ContentProducer接口,HttpClient提供了動態實體的支持。內容生成器是按照需求生成它們內容的對象,將它們寫入到一個輸出流中。它們是每次被請求時來生成內容。所以用EntityTemplate創建的實體通常是自我包含而且可以重復的。
```
ContentProducer cp = new ContentProducer() {
public void writeTo(OutputStream outstream) throws IOException {
Writer writer = new OutputStreamWriter(outstream, "UTF-8");
writer.write("<response>");
writer.write(" <content>");
writer.write(" important stuff");
writer.write(" </content>");
writer.write("</response>");
writer.flush();
}
};
HttpEntity entity = new EntityTemplate(cp);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);
```
##### 1.1.7.2 HTML表單
許多應用程序需要頻繁模擬提交一個HTML表單的過程,比如,為了來記錄一個Web應用程序或提交輸出數據。HttpClient提供了特殊的實體類UrlEncodedFormEntity來這個滿足過程。
```
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("param2", "value2"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);
```
UrlEncodedFormEntity實例將會使用URL編碼來編碼參數,生成如下的內容:
```
param1=value1¶m2=value2
```
##### 1.1.7.3 內容分塊
通常,我們推薦讓HttpClient選擇基于被傳遞的HTTP報文屬性的最適合的編碼轉換。這是可能的,但是,設置HttpEntity#setChunked()方法為true是通知HttpClient分塊編碼的首選。請注意HttpClient將會使用標識作為提示。當使用的HTTP協議版本,如HTTP/1.0版本,不支持分塊編碼時,這個值會被忽略。
```
StringEntity entity = new StringEntity("important message",
"text/plain; charset=\"UTF-8\"");
entity.setChunked(true);
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");
httppost.setEntity(entity);
```
### 1.1.8 響應控制器
控制響應的最簡便和最方便的方式是使用ResponseHandler接口。這個放完完全減輕了用戶關于連接管理的擔心。當使用ResponseHandler時,HttpClient將會自動關注并保證釋放連接到連接管理器中去,而不管請求執行是否成功或引發了異常。
```
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://localhost/");
ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {
public byte[] handleResponse(
HttpResponse response) throws ClientProtocolException, IOException {
HttpEntity entity = response.getEntity();
if (entity != null) {
return EntityUtils.toByteArray(entity);
} else {
return null;
}
}
};
byte[] response = httpclient.execute(httpget, handler);
```
## 1.2 HTTP執行的環境
最初,HTTP是被設計成無狀態的,面向請求-響應的協議。然而,真實的應用程序經常需要通過一些邏輯相關的請求-響應交換來持久狀態信息。為了開啟應用程序來維持一個過程狀態,HttpClient允許HTTP請求在一個特定的執行環境中來執行,簡稱為HTTP上下文。如果相同的環境在連續請求之間重用,那么多種邏輯相關的請求可以參與到一個邏輯會話中。HTTP上下文功能和java.util.Map<String,Object>很相似。它僅僅是任意命名參數值的集合。應用程序可以在請求之前或在檢查上下文執行完成之后來填充上下文屬性。
在HTTP請求執行的這一過程中,HttpClient添加了下列屬性到執行上下文中:
* `http.connection`:HttpConnection實例代表了連接到目標服務器的真實連接。
* `http.target_host`:HttpHost實例代表了連接目標。
* `http.proxy_host`:如果使用了,HttpHost實例代表了代理連接。
* `http.request`:HttpRequest實例代表了真實的HTTP請求。
* `http.response`:HttpResponse實例代表了真實的HTTP響應。
* `http.request_sent`:java.lang.Boolean對象代表了暗示真實請求是否被完全傳送到目標連接的標識。
比如,為了決定最終的重定向目標,在請求執行之后,可以檢查http.target_host屬性的值:
```
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("http://www.google.com/");
HttpResponse response = httpclient.execute(httpget, localContext);
HttpHost target = (HttpHost) localContext.getAttribute(
ExecutionContext.HTTP_TARGET_HOST);
System.out.println("Final target: " + target);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
```
輸出內容為:
```
Final target: http://www.google.ch
```
## 1.3 異常處理
HttpClient能夠拋出兩種類型的異常:在I/O失敗時,如套接字連接超時或被重置的java.io.IOException異常,還有標志HTTP請求失敗的信號,如違反HTTP協議的HttpException異常。通常I/O錯誤被認為是非致命的和可以恢復的,而HTTP協議錯誤則被認為是致命的而且是不能自動恢復的。
### 1.3.1 HTTP運輸安全
要理解HTTP協議并不是對所有類型的應用程序都適合的,這一點很重要。HTTP是一個簡單的面向請求/響應的協議,最初被設計用來支持取回靜態或動態生成的內容。它從未向支持事務性操作方向發展。比如,如果成功收到和處理請求,HTTP服務器將會考慮它的其中一部分是否完成,生成一個響應并發送一個狀態碼到客戶端。如果客戶端因為讀取超時,請求取消或系統崩潰導致接收響應實體失敗時,服務器不會試圖回滾事務。如果客戶端決定重新這個請求,那么服務器將不可避免地不止一次執行這個相同的事務。在一些情況下,這會導致應用數據損壞或者不一致的應用程序狀態。
盡管HTTP從來都沒有被設計來支持事務性處理,但它也能被用作于一個傳輸協議對關鍵的任務應用提供被滿足的確定狀態。要保證HTTP傳輸層的安全,系統必須保證HTTP方法在應用層的冪等性。
### 1.3.2 冪等的方法
HTTP/1.1 明確地定義了冪等的方法,描述如下
> 方法也可以有“冪等”屬性在那些(除了錯誤或過期問題)N的副作用>0的相同請求和獨立的請求是相同的
換句話說,應用程序應該保證準備著來處理多個相同方法執行的實現。這是可以達到的,比如,通過提供一個獨立的事務ID和其它避免執行相同邏輯操作的方法。
請注意這個問題對于HttpClient是不具體的。基于應用的瀏覽器特別受和非冪等的HTTP方法相關的相同問題的限制。
HttpClient假設沒有實體包含方法,比如GET和HEAD是冪等的,而實體包含方法,比如POST和PUT則不是。
### 1.3.3 異常自動恢復
默認情況下,HttpClient會試圖自動從I/O異常中恢復。默認的自動恢復機制是受很少一部分已知的異常是安全的這個限制。
* HttpClient不會從任意邏輯或HTTP協議錯誤(那些是從HttpException類中派生出的)中恢復的。
* HttpClient將會自動重新執行那么假設是冪等的方法。
* HttpClient將會自動重新執行那些由于運輸異常失敗,而HTTP請求仍然被傳送到目標服務器(也就是請求沒有完全被送到服務器)失敗的方法。
* HttpClient將會自動重新執行那些已經完全被送到服務器,但是服務器使用HTTP狀態碼(服務器僅僅丟掉連接而不會發回任何東西)響應時失敗的方法。在這種情況下,假設請求沒有被服務器處理,而應用程序的狀態也沒有改變。如果這個假設可能對于你應用程序的目標Web服務器來說不正確,那么就強烈建議提供一個自定義的異常處理器。
### 1.3.4 請求重試處理
為了開啟自定義異常恢復機制,應該提供一個HttpRequestRetryHandler接口的實現。
```
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(IOException exception,
int executionCount,HttpContext context) {
if (executionCount >= 5) {
// 如果超過最大重試次數,那么就不要繼續了
return false;
}
if (exception instanceof NoHttpResponseException) {
// 如果服務器丟掉了連接,那么就重試
return true;
}
if (exception instanceof SSLHandshakeException) {
// 不要重試SSL握手異常
return false;
}
HttpRequest request = (HttpRequest) context.getAttribute(
ExecutionContext.HTTP_REQUEST);
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// 如果請求被認為是冪等的,那么就重試
return true;
}
return false;
}
};
httpclient.setHttpRequestRetryHandler(myRetryHandler);
```
## 1.4 中止請求
在一些情況下,由于目標服務器的高負載或客戶端有很多活動的請求,那么HTTP請求執行會在預期的時間框內而失敗。這時,就可能不得不過早地中止請求,解除封鎖在I/O執行中的線程封鎖。被HttpClient執行的HTTP請求可以在執行的任意階段通過調用HttpUriRequest#abort()方法而中止。這個方法是線程安全的,而且可以從任意線程中調用。當一個HTTP請求被中止時,它的執行線程就封鎖在I/O操作中了,而且保證通過拋出InterruptedIOException異常來解鎖。
## 1.5 HTTP協議攔截器
HTTP協議攔截器是一個實現了特定HTPP協議方面的慣例。通常協議攔截器希望作用于一個特定頭部信息上,或者一族收到報文的相關頭部信息,或使用一個特定的頭部或一族相關的頭部信息填充發出的報文。協議攔截器也可以操縱包含在報文中的內容實體,透明的內容壓縮/解壓就是一個很好的示例。通常情況下這是由包裝器實體類使用了“裝飾者”模式來裝飾原始的實體完成的。一些協議攔截器可以從一個邏輯單元中來結合。
協議攔截器也可以通過共享信息來共同合作-比如處理狀態-通過HTTP執行上下文。協議攔截器可以使用HTTP內容來為一個或多個連續的請求存儲一個處理狀態。
通常攔截器執行的順序不應該和它們基于的特定執行上下文狀態有關。如果協議攔截器有相互依存關系,那么它們必須按特定順序來執行,正如它們希望執行的順序一樣,它們應該在相同的序列中被加到協議處理器。
協議攔截器必須實現為線程安全的。和Servlet相似,協議攔截器不應該使用實例變量,除非訪問的那些變量是同步的。
這個示例給出了本地內容在連續的請求中怎么被用于持久一個處理狀態的:
```
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
AtomicInteger count = new AtomicInteger(1);
localContext.setAttribute("count", count);
httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
public void process(final HttpRequest request,
final HttpContext context) throws HttpException, IOException {
AtomicInteger count = (AtomicInteger) context.getAttribute("count");
request.addHeader("Count", Integer.toString(count.getAndIncrement()));
}
});
HttpGet httpget = new HttpGet("http://localhost/");
for (int i = 0; i < 10; i++) {
HttpResponse response = httpclient.execute(httpget, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity.consumeContent();
}
}
```
## 1.6 HTTP參數
HttpParams接口代表了定義組件運行時行為的一個不變的值的集合。很多情況下,HttpParams和HttpContext相似。二者之間的主要區別是它們在運行時使用的不同。這兩個接口表示了對象的集合,它們被視作為訪問對象值的鍵的Map,但是服務于不同的目的:
* HttpParams旨在包含簡單對象:整型,浮點型,字符串,集合,還有運行時不變的對象。
* HttpParams希望被用在“一次寫入-多處準備”模式下。HttpContext旨在包含很可能在HTTP報文處理這一過程中發生改變的復雜對象
* HttpParams的目標是定義其它組件的行為。通常每一個復雜的組件都有它自己的HttpParams對象。HttpContext的目標是來表示一個HTTP處理的執行狀態。通常相同的執行上下文在很多合作的對象中共享。
### 1.6.1 參數層次
在HTTP請求執行過程中,HttpRequest對象的HttpParams是和用于執行請求的HttpClient實例的HttpParams聯系在一起的。這使得設置在HTTP請求級別的參數優先于設置在HTTP客戶端級別的HttpParams。推薦的做法是設置普通參數對所有的在HTTP客戶端級別的HTTP請求共享,而且可以選擇性重寫具體在HTTP請求級別的參數。
```
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_0);
httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,"UTF-8");
HttpGet httpget = new HttpGet("http://www.google.com/");
httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);
httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,Boolean.FALSE);
httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
public void process(final HttpRequest request,
final HttpContext context) throws HttpException, IOException {
System.out.println(request.getParams().getParameter(
CoreProtocolPNames.PROTOCOL_VERSION));
System.out.println(request.getParams().getParameter(
CoreProtocolPNames.HTTP_CONTENT_CHARSET));
System.out.println(request.getParams().getParameter(
CoreProtocolPNames.USE_EXPECT_CONTINUE));
System.out.println(request.getParams().getParameter(
CoreProtocolPNames.STRICT_TRANSFER_ENCODING));
}
});
```
輸出內容為:
```
HTTP/1.1
UTF-8
false
null
```
### 1.6.2 HTTP參數bean
HttpParams接口允許在處理組件的配置上很大的靈活性。很重要的是,新的參數可以被引入而不會影響老版本的二進制兼容性。然而,和常規的Java bean相比,HttpParams也有一個缺點:HttpParams不能使用DI框架來組合。為了緩解這個限制,HttpClient包含了一些bean類,它們可以用來按順序使用標準的Java eban慣例初始化HttpParams對象。
```
HttpParams params = new BasicHttpParams();
HttpProtocolParamBean paramsBean = new HttpProtocolParamBean(params);
paramsBean.setVersion(HttpVersion.HTTP_1_1);
paramsBean.setContentCharset("UTF-8");
paramsBean.setUseExpectContinue(true);
System.out.println(params.getParameter(
CoreProtocolPNames.PROTOCOL_VERSION));
System.out.println(params.getParameter(
CoreProtocolPNames.HTTP_CONTENT_CHARSET));
System.out.println(params.getParameter(
CoreProtocolPNames.USE_EXPECT_CONTINUE));
System.out.println(params.getParameter(
CoreProtocolPNames.USER_AGENT));
```
輸出內容為:
```
HTTP/1.1
UTF-8
false
null
```
## 1.7 HTTP請求執行參數
這些參數會影響到請求執行的過程:
* `http.protocol.version`:如果沒有在請求對象中設置明確的版本信息,它就定義了使用的HTTP協議版本。這個參數期望得到一個ProtocolVersion類型的值。如果這個參數沒有被設置,那么就使用HTTP/1.1。
* `http.protocol.element-charset`:定義了編碼HTTP協議元素的字符集。這個參數期望得到一個java.lang.String類型的值。如果這個參數沒有被設置,那么就使用US-ASCII。
* `http.protocol.eontent-charset`:定義了為每個內容主體編碼的默認字符集。這個參數期望得到一個java.lang.String類型的值。如果這個參數沒有被設置,那么就使用ISO-8859-1。
* `http.useragent`:定義了頭部信息User-Agent的內容。這個參數期望得到一個java.lang.String類型的值。如果這個參數沒有被設置,那么HttpClient將會為它自動生成一個值。
* `http.protocol.strict-transfer-encoding`:定義了響應頭部信息中是否含有一個非法的Transfer-Encoding,都要拒絕掉。
* `http.protocol.expect-continue`:為包含方法的實體激活Expect: 100-Continue握手。Expect: 100-Continue握手的目的是允許客戶端使用請求體發送一個請求信息來決定源服務器是否希望在客戶端發送請求體之前得到這個請求(基于請求頭部信息)。Expect: 100-Continue握手的使用可以對需要目標服務器認證的包含請求的實體(比如POST和PUT)導致明顯的性能改善。Expect: 100-Continue握手應該謹慎使用,因為它和HTTP服務器,不支持HTTP/1.1協議的代理使用會引起問題。這個參數期望得到一個java.lang.Boolean類型的值。如果這個參數沒有被設置,那么HttpClient將會試圖使用握手。
* `http.protocol.wait-for-continue`:定義了客戶端應該等待100-Continue響應最大的毫秒級時間間隔。這個參數期望得到一個java.lang.Integer類型的值。如果這個參數沒有被設置,那么HttpClient將會在恢復請求體傳輸之前為確認等待3秒。
- Spring 中文文檔 3.1
- 第一部分 Spring framework 概述
- 第 1 章 Spring Framework 介紹
- 1.1 依賴注入和控制反轉
- 1.2 模塊
- 1.3 使用方案
- 第二部分 Spring 3 的新特性
- 第 2 章 Spring 3.0 的新特性和增強
- 2.1 Java 5
- 2.2 改進的文檔
- 2.3 新的文章和教程
- 2.4 新的模塊組織方式和系統構建方式
- 2.5 新特性概述
- 第 3 章 Spring 3.1 的新特性和增強
- 3.1 新特性概述
- 第三部分 核心技術
- 第 4 章 IoC 容器
- 4.1 Spring IoC 容器和 bean 的介紹
- 4.2 容器概述
- 4.3 Bean 概述
- 4.4 依賴
- 4.5 Bean 的范圍
- 4.6 自定義 bean 的性質
- 4.7 Bean 定義的繼承
- 4.8 容器擴展點
- 4.9 基于注解的容器配置
- 4.10 類路徑掃描和管理的組件
- 4.11 使用 JSR 330 標準注解
- 4.12 基于 Java 的容器配置
- Hibernate 中文文檔 3.2
- 前言
- 1. 翻譯說明
- 2. 版權聲明
- 第 1 章 Hibernate入門
- 1.1. 前言
- 1.2. 第一部分 - 第一個Hibernate應用程序
- 1.2.1. 第一個class
- 1.2.2. 映射文件
- 1.2.3. Hibernate配置
- 1.2.4. 用Ant構建
- 1.2.5. 啟動和輔助類
- 1.2.6. 加載并存儲對象
- 1.3. 第二部分 - 關聯映射
- 1.3.1. 映射Person類
- 1.3.2. 單向Set-based的關聯
- 1.3.3. 使關聯工作
- 1.3.4. 值類型的集合
- 1.3.5. 雙向關聯
- 1.3.6. 使雙向連起來
- 1.4. 第三部分 - EventManager web應用程序
- 1.4.1. 編寫基本的servlet
- 1.4.2. 處理與渲染
- 1.4.3. 部署與測試
- 1.5. 總結
- 第 2 章 體系結構(Architecture)
- 2.1. 概況(Overview)
- 2.2. 實例狀態
- 2.3. JMX整合
- 2.4. 對JCA的支持
- 2.5. 上下文相關的(Contextual)Session
- 第 3 章 配置
- 3.1. 可編程的配置方式
- 3.2. 獲得SessionFactory
- 3.3. JDBC連接
- 3.4. 可選的配置屬性
- 3.4.1. SQL方言
- 3.4.2. 外連接抓取(Outer Join Fetching)
- 3.4.3. 二進制流 (Binary Streams)
- 3.4.4. 二級緩存與查詢緩存
- 3.4.5. 查詢語言中的替換
- 3.4.6. Hibernate的統計(statistics)機制
- 3.5. 日志
- 3.6. 實現NamingStrategy
- 3.7. XML配置文件
- 3.8. J2EE應用程序服務器的集成
- 3.8.1. 事務策略配置
- 3.8.2. JNDI綁定的SessionFactory
- 3.8.3. 在JTA環境下使用Current Session context (當前session上下文)管理
- 3.8.4. JMX部署
- 第 4 章 持久化類(Persistent Classes)
- 4.1. 一個簡單的POJO例子
- 4.1.1. 實現一個默認的(即無參數的)構造方法(constructor)
- 4.1.2. 提供一個標識屬性(identifier property)(可選)
- 4.1.3. 使用非final的類 (可選)
- 4.1.4. 為持久化字段聲明訪問器(accessors)和是否可變的標志(mutators)(可選)
- 4.2. 實現繼承(Inheritance)
- 4.3. 實現equals()和hashCode()
- 4.4. 動態模型(Dynamic models)
- 4.5. 元組片斷映射(Tuplizers)
- 第 5 章 對象/關系數據庫映射基礎(Basic O/R Mapping)
- 5.1. 映射定義(Mapping declaration)
- 5.1.1. Doctype
- 5.1.1.1. EntityResolver
- 5.1.2. hibernate-mapping
- 5.1.3. class
- 5.1.4. id
- 5.1.4.1. Generator
- 5.1.4.2. 高/低位算法(Hi/Lo Algorithm)
- 5.1.4.3. UUID算法(UUID Algorithm )
- 5.1.4.4. 標識字段和序列(Identity columns and Sequences)
- 5.1.4.5. 程序分配的標識符(Assigned Identifiers)
- 5.1.4.6. 觸發器實現的主鍵生成器(Primary keys assigned by triggers)
- 5.1.5. composite-id
- 5.1.6. 鑒別器(discriminator)
- 5.1.7. 版本(version)(可選)
- 5.1.8. timestamp (可選)
- 5.1.9. property
- 5.1.10. 多對一(many-to-one)
- 5.1.11. 一對一
- 5.1.12. 自然ID(natural-id)
- 5.1.13. 組件(component), 動態組件(dynamic-component)
- 5.1.14. properties
- 5.1.15. 子類(subclass)
- 5.1.16. 連接的子類(joined-subclass)
- 5.1.17. 聯合子類(union-subclass)
- 5.1.18. 連接(join)
- 5.1.19. 鍵(key)
- 5.1.20. 字段和規則元素(column and formula elements)
- 5.1.21. 引用(import)
- 5.1.22. any
- 5.2. Hibernate 的類型
- 5.2.1. 實體(Entities)和值(values)
- 5.2.2. 基本值類型
- 5.2.3. 自定義值類型
- 5.3. 多次映射同一個類
- 5.4. SQL中引號包圍的標識符
- 5.5. 其他元數據(Metadata)
- 5.5.1. 使用 XDoclet 標記
- 5.5.2. 使用 JDK 5.0 的注解(Annotation)
- 5.6. 數據庫生成屬性(Generated Properties)
- 5.7. 輔助數據庫對象(Auxiliary Database Objects)
- 第 6 章 集合類(Collections)映射
- 6.1. 持久化集合類(Persistent collections)
- 6.2. 集合映射( Collection mappings )
- 6.2.1. 集合外鍵(Collection foreign keys)
- 6.2.2. 集合元素(Collection elements)
- 6.2.3. 索引集合類(Indexed collections)
- 6.2.4. 值集合于多對多關聯(Collections of values and many-to-many associations)
- 6.2.5. 一對多關聯(One-to-many Associations)
- 6.3. 高級集合映射(Advanced collection mappings)
- 6.3.1. 有序集合(Sorted collections)
- 6.3.2. 雙向關聯(Bidirectional associations)
- 6.3.3. 雙向關聯,涉及有序集合類
- 6.3.4. 三重關聯(Ternary associations)
- 6.3.5. 使用&amp;lt;idbag&amp;gt;
- 6.4. 集合例子(Collection example)
- 第 7 章 關聯關系映射
- 7.1. 介紹
- 7.2. 單向關聯(Unidirectional associations)
- 7.2.1. 多對一(many to one)
- 7.2.2. 一對一(one to one)
- 7.2.3. 一對多(one to many)
- 7.3. 使用連接表的單向關聯(Unidirectional associations with join tables)
- 7.3.1. 一對多(one to many)
- 7.3.2. 多對一(many to one)
- 7.3.3. 一對一(one to one)
- 7.3.4. 多對多(many to many)
- 7.4. 雙向關聯(Bidirectional associations)
- 7.4.1. 一對多(one to many) / 多對一(many to one)
- 7.4.2. 一對一(one to one)
- 7.5. 使用連接表的雙向關聯(Bidirectional associations with join tables)
- 7.5.1. 一對多(one to many) /多對一( many to one)
- 7.5.2. 一對一(one to one)
- 7.5.3. 多對多(many to many)
- 7.6. 更復雜的關聯映射
- 第 8 章 組件(Component)映射
- 8.1. 依賴對象(Dependent objects)
- 8.2. 在集合中出現的依賴對象 (Collections of dependent objects)
- 8.3. 組件作為Map的索引(Components as Map indices )
- 8.4. 組件作為聯合標識符(Components as composite identifiers)
- 8.5. 動態組件 (Dynamic components)
- 第 9 章 繼承映射(Inheritance Mappings)
- 9.1. 三種策略
- 9.1.1. 每個類分層結構一張表(Table per class hierarchy)
- 9.1.2. 每個子類一張表(Table per subclass)
- 9.1.3. 每個子類一張表(Table per subclass),使用辨別標志(Discriminator)
- 9.1.4. 混合使用“每個類分層結構一張表”和“每個子類一張表”
- 9.1.5. 每個具體類一張表(Table per concrete class)
- 9.1.6. Table per concrete class, using implicit polymorphism
- 9.1.7. 隱式多態和其他繼承映射混合使用
- 9.2. 限制
- 第 10 章 與對象共事
- 10.1. Hibernate對象狀態(object states)
- 10.2. 使對象持久化
- 10.3. 裝載對象
- 10.4. 查詢
- 10.4.1. 執行查詢
- 10.4.1.1. 迭代式獲取結果(Iterating results)
- 10.4.1.2. 返回元組(tuples)的查詢
- 10.4.1.3. 標量(Scalar)結果
- 10.4.1.4. 綁定參數
- 10.4.1.5. 分頁
- 10.4.1.6. 可滾動遍歷(Scrollable iteration)
- 10.4.1.7. 外置命名查詢(Externalizing named queries)
- 10.4.2. 過濾集合
- 10.4.3. 條件查詢(Criteria queries)
- 10.4.4. 使用原生SQL的查詢
- 10.5. 修改持久對象
- 10.6. 修改脫管(Detached)對象
- 10.7. 自動狀態檢測
- 10.8. 刪除持久對象
- 10.9. 在兩個不同數據庫間復制對象
- 10.10. Session刷出(flush)
- 10.11. 傳播性持久化(transitive persistence)
- 10.12. 使用元數據
- 第 11 章 事務和并發
- 11.1. Session和事務范圍(transaction scope)
- 11.1.1. 操作單元(Unit of work)
- 11.1.2. 長對話
- 11.1.3. 關注對象標識(Considering object identity)
- 11.1.4. 常見問題
- 11.2. 數據庫事務聲明
- 11.2.1. 非托管環境
- 11.2.2. 使用JTA
- 11.2.3. 異常處理
- 11.2.4. 事務超時
- 11.3. 樂觀并發控制(Optimistic concurrency control)
- 11.3.1. 應用程序級別的版本檢查(Application version checking)
- 11.3.2. 擴展周期的session和自動版本化
- 11.3.3. 脫管對象(deatched object)和自動版本化
- 11.3.4. 定制自動版本化行為
- 11.4. 悲觀鎖定(Pessimistic Locking)
- 11.5. 連接釋放模式(Connection Release Modes)
- 第 12 章 攔截器與事件(Interceptors and events)
- 12.1. 攔截器(Interceptors)
- 12.2. 事件系統(Event system)
- 12.3. Hibernate的聲明式安全機制
- 第 13 章 批量處理(Batch processing)
- 13.1. 批量插入(Batch inserts)
- 13.2. 批量更新(Batch updates)
- 13.3. StatelessSession (無狀態session)接口
- 13.4. DML(數據操作語言)風格的操作(DML-style operations)
- 第 14 章 HQL: Hibernate查詢語言
- 14.1. 大小寫敏感性問題
- 14.2. from子句
- 14.3. 關聯(Association)與連接(Join)
- 14.4. join 語法的形式
- 14.5. select子句
- 14.6. 聚集函數
- 14.7. 多態查詢
- 14.8. where子句
- 14.9. 表達式
- 14.10. order by子句
- 14.11. group by子句
- 14.12. 子查詢
- 14.13. HQL示例
- 14.14. 批量的UPDATE和DELETE
- 14.15. 小技巧 & 小竅門
- 第 15 章 條件查詢(Criteria Queries)
- 15.1. 創建一個Criteria 實例
- 15.2. 限制結果集內容
- 15.3. 結果集排序
- 15.4. 關聯
- 15.5. 動態關聯抓取
- 15.6. 查詢示例
- 15.7. 投影(Projections)、聚合(aggregation)和分組(grouping)
- 15.8. 離線(detached)查詢和子查詢
- 15.9. 根據自然標識查詢(Queries by natural identifier)
- 第 16 章 Native SQL查詢
- 16.1. 使用SQLQuery
- 16.1.1. 標量查詢(Scalar queries)
- 16.1.2. 實體查詢(Entity queries)
- 16.1.3. 處理關聯和集合類(Handling associations and collections)
- 16.1.4. 返回多個實體(Returning multiple entities)
- 16.1.4.1. 別名和屬性引用(Alias and property references)
- 16.1.5. 返回非受管實體(Returning non-managed entities)
- 16.1.6. 處理繼承(Handling inheritance)
- 16.1.7. 參數(Parameters)
- 16.2. 命名SQL查詢
- 16.2.1. 使用return-property來明確地指定字段/別名
- 16.2.2. 使用存儲過程來查詢
- 16.2.2.1. 使用存儲過程的規則和限制
- 16.3. 定制SQL用來create,update和delete
- 16.4. 定制裝載SQL
- 第 17 章 過濾數據
- 17.1. Hibernate 過濾器(filters)
- 第 18 章 XML映射
- 18.1. 用XML數據進行工作
- 18.1.1. 指定同時映射XML和類
- 18.1.2. 只定義XML映射
- 18.2. XML映射元數據
- 18.3. 操作XML數據
- 第 19 章 提升性能
- 19.1. 抓取策略(Fetching strategies)
- 19.1.1. 操作延遲加載的關聯
- 19.1.2. 調整抓取策略(Tuning fetch strategies)
- 19.1.3. 單端關聯代理(Single-ended association proxies)
- 19.1.4. 實例化集合和代理(Initializing collections and proxies)
- 19.1.5. 使用批量抓取(Using batch fetching)
- 19.1.6. 使用子查詢抓取(Using subselect fetching)
- 19.1.7. 使用延遲屬性抓取(Using lazy property fetching)
- 19.2. 二級緩存(The Second Level Cache)
- 19.2.1. 緩存映射(Cache mappings)
- 19.2.2. 策略:只讀緩存(Strategy: read only)
- 19.2.3. 策略:讀/寫緩存(Strategy: read/write)
- 19.2.4. 策略:非嚴格讀/寫緩存(Strategy: nonstrict read/write)
- 19.2.5. 策略:事務緩存(transactional)
- 19.3. 管理緩存(Managing the caches)
- 19.4. 查詢緩存(The Query Cache)
- 19.5. 理解集合性能(Understanding Collection performance)
- 19.5.1. 分類(Taxonomy)
- 19.5.2. Lists, maps 和sets用于更新效率最高
- 19.5.3. Bag和list是反向集合類中效率最高的
- 19.5.4. 一次性刪除(One shot delete)
- 19.6. 監測性能(Monitoring performance)
- 19.6.1. 監測SessionFactory
- 19.6.2. 數據記錄(Metrics)
- 第 20 章 工具箱指南
- 20.1. Schema自動生成(Automatic schema generation)
- 20.1.1. 對schema定制化(Customizing the schema)
- 20.1.2. 運行該工具
- 20.1.3. 屬性(Properties)
- 20.1.4. 使用Ant(Using Ant)
- 20.1.5. 對schema的增量更新(Incremental schema updates)
- 20.1.6. 用Ant來增量更新schema(Using Ant for incremental schema updates)
- 20.1.7. Schema 校驗
- 20.1.8. 使用Ant進行schema校驗
- 第 21 章 示例:父子關系(Parent Child Relationships)
- 21.1. 關于collections需要注意的一點
- 21.2. 雙向的一對多關系(Bidirectional one-to-many)
- 21.3. 級聯生命周期(Cascading lifecycle)
- 21.4. 級聯與未保存值(Cascades and unsaved-value)
- 21.5. 結論
- 第 22 章 示例:Weblog 應用程序
- 22.1. 持久化類
- 22.2. Hibernate 映射
- 22.3. Hibernate 代碼
- 第 23 章 示例:復雜映射實例
- 23.1. Employer(雇主)/Employee(雇員)
- 23.2. Author(作家)/Work(作品)
- 23.3. Customer(客戶)/Order(訂單)/Product(產品)
- 23.4. 雜例
- 23.4.1. "Typed" one-to-one association
- 23.4.2. Composite key example
- 23.4.3. 共有組合鍵屬性的多對多(Many-to-many with shared composite key attribute)
- 23.4.4. Content based discrimination
- 23.4.5. Associations on alternate keys
- 第 24 章 最佳實踐(Best Practices)
- HttpClient 教程
- 前言
- 第一章 基礎
- 第二章 連接管理
- 第三章 HTTP狀態管理
- 第四章 HTTP認證
- 第五章 HTTP客戶端服務
- 第六章 高級主題
- Mybatis 中文文檔 3.4
- 參考文檔
- 簡介
- 入門
- XML 映射配置文件
- Mapper XML 文件
- 動態 SQL
- Java API
- SQL語句構建器類
- Logging
- 項目文檔
- 項目總體信息
- 訪問
- 提醒方法
- 項目依賴
- Dependency Information
- Overview
- 問題跟蹤
- 項目授權
- 項目郵件列表
- Project Plugin Management
- Project Build Plugins
- Project Report Plugins
- 團隊
- Web訪問
- 匿名訪問
- 開發者訪問
- 通過防火墻訪問
- 項目概要
- 生成報表
- MyBatis Generator 用戶手冊
- MyBatis Generator介紹
- MyBatis Generator新增功能
- MyBatis Generator 快速入門指南
- 運行 MyBatis Generator
- 從命令行運行 MyBatis Generator
- 使用Ant運行 MyBatis Generator
- 通過Maven運行 MyBatis Generator
- 使用Java運行 MyBatis Generator
- 運行 MyBatis Generator 后的任務
- Migrating from Ibator
- Migrating from Abator
- MyBatis Generator XML 配置參考
- &lt;classPathEntry&gt; 元素
- &lt;columnOverride&gt; 元素
- &lt;columnRenamingRule&gt; 元素
- &lt;commentGenerator&gt; 元素
- &lt;context&gt; 元素
- &lt;generatedKey&gt; 元素
- &lt;generatorConfiguration&gt; 元素
- &lt;ignoreColumn&gt; 元素
- &lt;javaClientGenerator&gt; 元素
- The &lt;javaModelGenerator&gt; Element
- The &lt;javaTypeResolver&gt; Element
- &lt;jdbcConnection&gt; 元素
- &lt;plugin&gt; 元素
- &lt;properties&gt; 元素
- &lt;property&gt; 元素
- &lt;sqlMapGenerator&gt; 元素
- &lt;table&gt; 元素
- 使用生成的對象
- JAVA實體對象
- SQL映射文件
- Java客戶端對象
- Example類使用說明
- 擴展Example類
- 使用注意事項
- DB2 使用注意事項
- MySql 使用注意事項
- Oracle 使用注意事項
- PostgreSQL 使用注意事項
- 參考資料
- 從源碼構建
- 擴展MyBatis Generator
- 開發插件
- 日志信息
- 提供的插件
- 設計理念
- Velocity 中文文檔
- 1. 關于
- 2. 什么是Velocity?
- 3. Velocity 可以做什么?
- 3.1. Mud Store 示例
- 4. Velocity模板語言(VTL): 介紹
- 5. Hello Velocity World!
- 6. 注釋
- 7. 引用
- 7.1. 變量Variables
- 7.2. 屬性
- 7.3. 方法
- 8. 形式引用符Formal Reference Notation
- 9. 安靜引用符Quiet Reference Notation
- 11. Case Substitution
- 12. 指令
- 12.1. #set
- 12.2. 字面字符串
- 12.3. 條件
- 12.3.1 If / ElseIf / Else
- 12.3.2 關系和邏輯操作符
- 12.4. 循環
- 12.4.1. Foreach 循環
- 12.5. 包含
- 12.6. 解析
- 12.7. 停止
- 12.10. 宏
- 12.10.1. Velocimacro 參數
- 12.10.2. Velocimacro 屬性
- 12.10.3. Velocimacro Trivia
- 13. Getting literal
- 13.1. 貨幣字符
- 13.2. 轉義 有效的 VTL 指令
- 13.3. 轉義 無效的 VTL 指令
- 14. VTL 格式化問題
- 15. 其它特征和雜項
- 15.1. 數學特征
- 15.2. 范圍操作符
- 15.3. 進階:轉義和!
- 15.4. Velocimacro 雜記
- 15.5. 字符串聯
- Google Guava官方教程(中文版)
- 1-基本工具
- 1.1-使用和避免null
- 1.2-前置條件
- 1.3-常見Object方法
- 1.4-排序: Guava強大的”流暢風格比較器”
- 1.5-Throwables:簡化異常和錯誤的傳播與檢查
- 2-集合
- 2.1-不可變集合
- 2.2-新集合類型
- 2.3-強大的集合工具類:java.util.Collections中未包含的集合工具
- 2.4-集合擴展工具類
- 3-緩存
- 4-函數式編程
- 5-并發
- 5.1-google Guava包的ListenableFuture解析
- 5.2-Google-Guava Concurrent包里的Service框架淺析
- 6-字符串處理:分割,連接,填充
- 7-原生類型
- 8-區間
- 9-I/O
- 10-散列
- 11-事件總線
- 12-數學運算
- 13-反射
- JFreeChart 開發者指南
- 1 簡介
- 1.1 什么是JFreeChart
- 1.2 使用文檔
- 1.3 感謝
- 1.4 建議
- 2 圖表實例
- 2.1 介紹
- 2.2 餅圖(Pie Charts)
- 2.3 直方條形圖(Bar Charts)
- 2.4 折線圖(Line Charts)
- 2.5 XY(散點圖)
- 2.6 時序圖
- 2.7 柱狀圖
- 2.8 面積圖
- 2.9 差異圖
- 2.10 梯形圖
- 2.11 甘特圖
- 2.12 多軸圖
- 2.13 復合/覆蓋圖
- 2.14 開發遠景
- 3 下載和安裝JFreeChart 1.0.6
- 3.1 簡介
- 3.2 下載
- 3.3 解包
- 3.4 運行演示實例
- 3.5 編譯源代碼
- 3.6 產生javadoc文檔
- 4 使用JFreeChart1.0.6
- 4.1 概述
- 4.2 創建第一個圖表
- 5 餅圖(Pie Charts)
- 5.1 簡介
- 5.2 創建一個簡單的餅圖(Pie Charts)
- 5.3 片區顏色
- 5.4 片區外廓
- 5.5 空置、零值和負值
- 5.6 片區和圖例標簽
- 5.7 “取出”某個片區
- 5.8 3D餅圖
- 5.9 多餅圖
- 5.10 實例講解
- 6 直方條形圖(Bar Charts)
- 6.1 簡介
- 6.2 創建一個直方條形圖
- 6.3 ChartFactory類
- 6.4 直方條形圖的簡單定制
- 6.5 定制外觀
- 6.6 示例代碼解讀
- 7 折線圖
- 7.1 簡介
- 7.2 使用categoryDataset數據集創建折線圖
- 7.3 使用XYDataset數據集創建折線圖
- 8 時序圖
- 8.1 簡介
- 8.2 創建時序圖
- 9 定制圖表(Customising Charts)
- 9.1 簡介
- 9.2 圖表屬性
- 9.3 圖區屬性
- 9.4 軸屬性
- 9.5 心得體會
- 10 動態圖(Dynamic Charts)
- 10.1 簡介
- 10.2 知識背景
- 10.3 實例應用
- 11 圖表工具條(Tooltips)
- 11.1 概述
- 11.2 創建圖表工具條
- 11.3 收集圖表工具條
- 11.4 顯示圖表工具條
- 11.5 隱藏圖表工具條
- 11.6 定制圖表工具條
- 12 圖表條目標簽(Item Label)
- 12.1 簡介
- 12.2 顯示條目標簽
- 12.3 條目標簽外觀
- 12.4 條目標簽位置
- 12.5 定制條目標簽文本
- 12.6 實例1
- 12.7 實例2
- 13 多軸和數據源圖表(Multi Axis and Dataset)
- 13.1 簡介
- 13.2 實例
- 13.3 建議和技巧
- 14 組合圖表(Combined Charts)
- 14.1 簡介
- 14.2 組合X種類圖區
- 14.3 組合Y種類圖區
- 14.4 組合X-XY圖區
- 14.5 組合Y-XY圖區
- 15 數據源和JDBC(Dataset And JDBC)
- 15.1 簡介
- 15.2 關于JDBC
- 15.3 樣本數據
- 15.4 PostgreSQL
- 15.5 JDBC驅動
- 15.6 應用演示
- 16 導出圖表為PDF格式
- 16.1 簡介
- 16.2 什么是Acrobat PDF
- 16.3 IText
- 16.4 Graphics2D
- 16.5 開始導出
- 16.6 實例應用
- 16.7 查看PDF 文件
- 16.8 Unicode字符問題
- 17 導出圖表為SVG格式
- 17.1 簡介
- 17.2 背景
- 17.3 實例代碼
- 18 Applet
- 18.1 簡介
- 18.2 問題
- 18.3 實例應用
- 19 Servlets
- 19.1 介紹
- 19.2 編寫一個簡單的Servlet應用
- 19.3 編譯實例Servlet
- 19.4 部署實例Servlet
- 19.5 在HMTL頁面種嵌入圖表
- 19.6 支持文件
- 19.7 部署Servlets
- 20 JFreeChart相關技術
- 20.1 簡介
- 20.2 X11/Headless Java
- 20.3 JSP
- 20.4 加載圖片
- 21 包
- 21.1 概述