JAX-RS 2.0 REST 客戶端

JAX-RS 2.0對客戶端API進行了標準化。客戶端API通過HTTP請求Web資源,同樣符合統一接口和REST架構風格。與Apache HTTP Client和HttpURLConnection相比,客戶端API具備對REST感知的高層API,可以和Providers集成,返回值直接對應高層的業務類實例。

1. 客戶端接口

REST客戶端主要包括三個接口:javax.ws.rs.client.Client、javax.ws.rs.client.WebTarget和javax.ws.rs.client.Invocation。

1.1 Client接口

Client內部要管理客戶端通信底層實現所需的各種對象,它是一個重量級的對象,應該儘量少地構造Client實例此外接口要求其實例要有關閉連接的保障,否則會造成內存泄露

Jersey對Client接口的實現類是JerseyClient。通常使用構造模式,使用ClientBuilder創建實例。示例如下:

ClientConfig clientConfig = new ClientConfig();
//註冊Provider
clientConfig.register(MyProvider.class);
//註冊Feature
clientConfig.register(MyFeature.class);
//註冊Filter
clientConfig.register(new AnotherClientFilter());
//創建Client
Client client = ClientBuilder.newClient(clientConfig);
//通過property設置相關屬性
client.property("MyProperty", "MyValue");

//配置完畢後,可以通過getConfiguration()獲取配置信息
Configuration configuration = client.getConfiguration();
Map<String, Object> properties = configuration.getProperties();
Iterator<Entry<String, Object>> it = properties.entrySet().iterator();
...

Client接口還提供了對客戶端的安全連接和異步支持。

1.2 WebTarget接口

WebTarget接口爲REST客戶端實現資源定位,可以定義請求資源的地址、查詢參數和媒體類型等信息。Jersey中的WebTarget接口實現類是JerseyWebTarget。

WebTarget對象接收配置參數的方法是通過方法鏈,採用不變模式完成。如果分開寫每次都返回一個新的WebTarget對象,如果不將其覆值會造成信息丟失。

WebTarget webTarget = client.target(BASE_URI);
webTarget.path("books").path("book").queryParam("bookId", "1");

1.3 Invocation接口

當WebTarget接口完成資源定位後,Invocation接口向REST服務端發起請求。請求包括同步和異步方式,由Invocation接口內部的Builder接口定義。Jersey中的Invocation接口實現類是JerseyInvocation。

final Invocation.Builder invocationBuilder = webTarget.request();

//以多種方式請求數據
final Book book = invocationBuilder.get(Book.class);
Response response = invocationBuilder.post(userEntity);
invocationBuilder.put(userEntity);

JAX-RS 2.0的REST框架無需開發者編碼實現對客戶端實例的資源管理,Response實例的readEntity()在返回響應實體的同時,就完成了對客戶端資源的釋放。

2. Connector

Connector接口是REST客戶端底層連接器接口,Jersey提供了4個實現:

  • HttpUrlConnector REST客戶端的默認連接器
  • ApacheConnector
  • GrizzlyConnector
  • InMemoryConnector 不是真實的HTTP連接器,而是使用JVM調用來模擬HTTP請求訪問。

2.1 默認連接器

默認情況下,Jersey的Client初始化時會構造一個HttpUrlConnector實例作爲連接器。

2.2 Apache連接器

ApacheConnector是基於Apache HTTP Client的連接器實現,比默認連接器功能更完整。可以實現代理服務器設置、超時設置。示例如下:

final ClientConfig clientConfig = new ClientConfig();

//代理服務器配置
clientConfig.property(ApacheClientProperties.PROXY_URI, "http://192.168.0.100");
clientConfig.property(ApacheClientProperties.PROXY_USERNAME, "user");
clientConfig.property(ApacheClientProperties.PROXY_PASSWORD , "pwd");
//連接超時配置
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 1000);
//讀取超時配置,指連接和資源定位成功後,客戶端接收服務響應的最長時間
clientConfig.property(ClientProperties.READ_TIMEOUT, 2000);

clientConfig.connectorProvider(new ApacheConnectorProvider());
client = ClientBuilder.newClient(clientConfig);

2.3 Grizzly連接器

GrizzlyConnector是Grizzly提供的連接器實現,內部使用異步處理客戶端com.ning.http.client.AsyncHttpClient類作爲底層的連接。

final ClientConfig clientConfig = new ClientConfig();
clientConfig.property("TestKey", "TestValue");

clientConfig.connectorProvider(new GrizzlyConnectorProvider());
Client client = ClientBuilder.newClient(clientConfig);

2.4 HTTP連接池

既然Client是一個重型組件,因此頻繁地創建Client實例會影響總體性能。一種常見的解決方案是使用HTTP連接池來管理連接。下例使用ApacheConnector來實現HTTP連接池:

final ClientConfig clientConfig = new ClientConfig();
final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
//設置最大連接數
cm.setMaxTotal(20000);
//設置每條路由的默認最大連接數
cm.setDefaultMaxPerRoute(10000);
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, cm);

clientConfig.connectorProvider(new ApacheConnectorProvider());
client = ClientBuilder.newClient(clientConfig);

後記

通常REST式的Web服務會按模塊分別提供獨立的Web服務,而模塊之間的調用通過Web服務的REST API來實現。也就是說每個模塊對其他模塊的調用就是客戶端請求。爲了避免每次請求時重複編寫構造客戶端實例的代碼,可以封裝Client到公共模塊,減少代碼冗餘。

參考:《Java RESTful Web Service實戰》

轉載自:http://blog.ubone.com/blog/2015/04/12/rest-ke-hu-duan/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章