亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

詳解如何使用Jersey客戶端請求Spring Boot(RESTFul)服務

2024-07-13 10:16:39
字體:
來源:轉載
供稿:網友

本文介紹了使用Jersey客戶端請求Spring Boot(RESTFul)服務,分享給大家,具體如下:

Jersey客戶端獲取Client對象實例封裝:

@Service("jerseyPoolingClient") public class JerseyPoolingClientFactoryBean implements FactoryBean<Client>, InitializingBean, DisposableBean{      /**    * Client接口是REST客戶端的基本接口,用于和REST服務器通信。Client被定義為一個重量級的對象,其內部管理著    * 客戶端通信底層的各種對象,比如連接器,解析器等。因此,不推薦在應用中產生大量的的Client實例,這一點在開發中    * 需要特別小心,另外該接口要求其實例要有關閉連接的保障,否則會造成內存泄露    */   private Client client;      /**    * 一個Client最大的連接數,默認為2000    */   private int maxTotal = 2000;      /**    * 每路由的默認最大連接數    */   private int defaultMaxPerRoute = 1000;      private ClientConfig clientConfig;      public JerseyPoolingClientFactoryBean() {   }      /**    * 帶配置的構造函數    * @param clientConfig    */   public JerseyPoolingClientFactoryBean(ClientConfig clientConfig) {     this.clientConfig = clientConfig;   }    public JerseyPoolingClientFactoryBean(int maxTotal, int defaultMaxPerRoute) {     this.maxTotal = maxTotal;     this.defaultMaxPerRoute = defaultMaxPerRoute;   }    /**    * attention:    * Details:容器銷毀時,釋放Client資源    * @author chhliu    */   @Override   public void destroy() throws Exception {     this.client.close();   }    /**    *    * attention:    * Details:以連接池的形式,來初始化Client對象    * @author chhliu    */   @Override   public void afterPropertiesSet() throws Exception {     // 如果沒有使用帶ClientConfig的構造函數,則該類的實例為null,則使用默認的配置初始化     if(this.clientConfig == null){       final ClientConfig clientConfig = new ClientConfig();       // 連接池管理實例,該類是線程安全的,支持多并發操作       PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager();       pcm.setMaxTotal(this.maxTotal);       pcm.setDefaultMaxPerRoute(this.defaultMaxPerRoute);              clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, pcm);       /*        * 在使用Jersey來請求Spring Boot服務時,Spring Boot默認使用Jackson來解析JSON        * 而Jersey默認使用MOXy解析JSON,當Jersey Client想Spring Boot服務請求資源時,        * 這個差異會導致服務端和客戶端對POJO的轉換不同,造成反序列化的錯誤        * 因此,此處需要在Client的Config實例中注冊Jackson特性        */       clientConfig.register(JacksonFeature.class);       // 使用配置Apache連接器,默認連接器為HttpUrlConnector       clientConfig.connectorProvider(new ApacheConnectorProvider());       client = ClientBuilder.newClient(clientConfig);     }else{       // 使用構造函數中的ClientConfig來初始化Client對象       client = ClientBuilder.newClient(this.clientConfig);     }   }    /**    * attention:    * Details:返回Client對象,如果該對象為null,則創建一個默認的Client    * @author chhliu    */   @Override   public Client getObject() throws Exception {     if(null == this.client){       return ClientBuilder.newClient();     }     return this.client;   }    /**    * attention:    * Details:獲取Client對象的類型    * @author chhliu    */   @Override   public Class<?> getObjectType() {     return (this.client == null ? Client.class : this.client.getClass());   }    /**    * attention:    * Details:Client對象是否為單例,默認為單例    * @author chhliu    */   @Override   public boolean isSingleton() {     return true;   } } 

請求Spring Boot服務的封裝:

@Component("jerseyClient") public class JerseyClient {      @Resource(name="jerseyPoolingClient")   private Client client;      /**    * attention:    * Details:通過id來查詢對象    * @author chhliu    */   public ResultMsg<GitHubEntity> getResponseById(final String id) throws JsonProcessingException, IOException{     WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/user/"+id);     Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);     GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){};     Response response = invocationBuilder.get();     if(response.getStatus() == 200){       /*        * 當調用readEntity方法時,程序會自動的釋放連接        * 即使沒有調用readEntity方法,直接返回泛型類型的對象,底層仍然會釋放連接        */       return response.readEntity(genericType);     }else{       ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;     }   }      /**    * attention:    * Details:分頁查詢    * @author chhliu    */   public ResultMsg<Pager<GitHubEntity>> getGithubWithPager(final Integer pageOffset, final Integer pageSize, final String orderColumn){     WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/users/page")         .queryParam("pageOffset", pageOffset)         .queryParam("pageSize", pageSize)         .queryParam("orderColumn", orderColumn);         // 注意,如果此處的媒體類型為MediaType.APPLICATION_JSON,那么對應的服務中的參數前需加上@RequestBody         Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);     GenericType<ResultMsg<Pager<GitHubEntity>>> genericType = new GenericType<ResultMsg<Pager<GitHubEntity>>>(){};     Response response = invocationBuilder.get();     if(response.getStatus() == 200){       return response.readEntity(genericType);     }else{       ResultMsg<Pager<GitHubEntity>> res = new ResultMsg<Pager<GitHubEntity>>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;     }        }      /**    * attention:    * Details:根據用戶名來查詢    * @author chhliu    */   public ResultMsg<List<GitHubEntity>> getResponseByUsername(final String username) throws JsonProcessingException, IOException{     WebTarget webTarget = client.target("http://localhost:8080").path("/github/get/users/"+username);     Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);     GenericType<ResultMsg<List<GitHubEntity>>> genericType = new GenericType<ResultMsg<List<GitHubEntity>>>(){};     Response response = invocationBuilder.get();     if(response.getStatus() == 200){       return response.readEntity(genericType);     }else{       ResultMsg<List<GitHubEntity>> res = new ResultMsg<List<GitHubEntity>>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;     }   }      /**    * attention:    * Details:根據id來刪除一個記錄    * @author chhliu    */   public ResultMsg<GitHubEntity> deleteById(final String id) throws JsonProcessingException, IOException{     WebTarget target = client.target("http://localhost:8080").path("/github/delete/"+id);     GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){};     Response response = target.request().delete();     if(response.getStatus() == 200){       return response.readEntity(genericType);     }else{       ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;     }   }      /**    * attention:    * Details:更新一條記錄    * @author chhliu    */   public ResultMsg<GitHubEntity> update(final GitHubEntity entity) throws JsonProcessingException, IOException{     WebTarget target = client.target("http://localhost:8080").path("/github/put");     GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){};     Response response = target.request().buildPut(Entity.entity(entity, MediaType.APPLICATION_JSON)).invoke();     if(response.getStatus() == 200){       return response.readEntity(genericType);     }else{       ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;     }   }      /**    * attention:    * Details:插入一條記錄    * @author chhliu    */   public ResultMsg<GitHubEntity> save(final GitHubEntity entity) throws JsonProcessingException, IOException{       WebTarget target = client.target("http://localhost:8080").path("/github/post");      GenericType<ResultMsg<GitHubEntity>> genericType = new GenericType<ResultMsg<GitHubEntity>>(){};      Response response = target.request().buildPost(Entity.entity(entity, MediaType.APPLICATION_JSON)).invoke();      if(response.getStatus() == 200){        return response.readEntity(genericType);      }else{       ResultMsg<GitHubEntity> res = new ResultMsg<GitHubEntity>();       res.setErrorCode(String.valueOf(response.getStatus()));       res.setErrorMsg(response.getStatusInfo().toString());       res.setOK(false);       return res;      }   } } 

Jersey客戶端接口詳解

1 Client接口

創建一個Client實例是通過ClientBuilder構造的,通常使用一個ClientConfig實例作為參數,如果我們使用Client client = ClientBuilder.newClient()的方式來創建Client實例的時候,每次都會創建一個Client實例,但該實例是一個重量級的對象,所以,建議使用HTTP連接池的方式來管理連接,而不是每次請求都去創建一個Client對象,具體的連接池管理方式見上面的代碼示例。

2 WebTarget接口

WebTarget接口是為REST客戶端實現資源定位的接口,通過WebTarget接口,我們可以定義請求資源的具體地址,查詢參數和媒體類型信息等。我們可以通過方法鏈的方式完成對一個WebTarget實例的配置,但是需要注意的是,雖然WebTarget的使用方式和StringBuffer的方法鏈方式非常類似,但實質是不一樣的,WebTarget的方法鏈必須設置方法的返回值,作為后續流程的句柄,這個是什么意思了,看下面的幾個示例:

示例1:StringBuffer的方法鏈示例

StringBuffer sb = new StringBuffer("lch");      sb.append("hello");      sb.append("world");      sb.append("hello").append("world"); // 這種方式和上面的兩行代碼實現的效果是一樣的。 

示例2:WebTarget的方法鏈示例

// 使用一行代碼的方法鏈來實例化WebTarget WebTarget webTarget = client.target("http://localhost:8080"); webTarget.path("/github/get/users/page")   .queryParam("pageOffset", pageOffset)   .queryParam("pageSize", pageSize)   .queryParam("orderColumn", orderColumn); // 下面是分開使用方法鏈來實例化WebTarget webTarget.path("/github/get/users/page"); webTarget.queryParam("pageOffset", pageOffset); webTarget.queryParam("pageSize", pageSize); // 上面兩種實例化的方式最后產生的結果大相徑庭,上面的實例化方式是OK的,沒有問題,下面的實例化方式卻有問題,下面的實例化方式中,每一行都會生成一個 // 新的WebTarget對象,原來的WebTarget并沒有起任何作用,畢竟每一行的實例都不一樣,如果我們想要分多行實例化了,就必須為每個方法的返回提供一個句柄,方式如下:  WebTarget target = client.target("http://localhost:8080"); WebTarget pathTarget = target.path("/github/get/users/page"); WebTarget paramTarget = pathTarget.queryParam("pageOffset", pageOffset);  // 最后使用的時候,用最后一個WebTarget實例對象即可 

3 Invocation接口

Invocation接口是在完成資源定位配置后,向REST服務端發起請求的接口,請求包括同步和異步兩種方式,由Invocation接口內部的Builder接口定義,Builder接口繼承了同步接口SyncInvoker,異步調用的使用示例如下:

Future<ResultMsg<List<GitHubEntity>>> response = invocationBuilder.async().get(genericType);      if(response.isDone()){       return response.get();     } 

Invocation.Builder接口實例分別執行了GET和POST請求來提交查詢和創建,默認情況下,HTTP方法調用的返回類型是Response類型,同時也支持泛型類型的返回值,在上面的示例中,我們使用了大量的泛型,這里就不做過多的解釋了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩成人精品| 日韩av在线影院| 久久国产精品影片| 中文字幕亚洲一区| 日韩电影在线观看中文字幕| 日韩欧美在线一区| 精品精品国产国产自在线| 岛国av一区二区三区| 欧美中文字幕第一页| 久久精品国产精品| 国产精品小说在线| 欧美在线视频播放| 大胆人体色综合| 欧美美女15p| 欧美大片免费观看在线观看网站推荐| 亚洲a在线观看| 91精品国产成人www| 91精品久久久久久久久久久久久| xvideos成人免费中文版| 久久久天堂国产精品女人| 97成人在线视频| 欧美性高跟鞋xxxxhd| 欧美成人激情在线| 欧美一级电影在线| 色婷婷综合久久久久中文字幕1| 久久99青青精品免费观看| 在线观看日韩专区| 日韩欧美福利视频| 国产精品入口夜色视频大尺度| 日韩精品免费在线播放| 最新的欧美黄色| 亚洲欧美色婷婷| 成人国产精品久久久| 久久精品视频一| 不卡av在线网站| 亚洲性无码av在线| 成人欧美一区二区三区在线湿哒哒| 亚洲欧洲午夜一线一品| 亚洲美女激情视频| 久久69精品久久久久久久电影好| 亚洲高清av在线| 欧美日韩一区二区免费在线观看| 亚洲专区在线视频| 91精品啪aⅴ在线观看国产| 色哟哟入口国产精品| 国产精品黄色av| 91久久在线视频| 亚洲精品美女久久久久| 91久久在线播放| 最近2019中文字幕第三页视频| 亚洲日韩欧美视频| 久久久999国产精品| 国产精品天天狠天天看| 欧美日韩亚洲激情| 午夜欧美大片免费观看| 久久免费精品视频| 国产精品美女主播| 成人精品视频99在线观看免费| 国模叶桐国产精品一区| 欧美成人午夜视频| 日本在线精品视频| 久久久999国产精品| 日韩av网站大全| 69国产精品成人在线播放| 伊是香蕉大人久久| 日韩在线视频免费观看高清中文| 91久久久久久久| 国产美女被下药99| 欧美尺度大的性做爰视频| 日韩免费中文字幕| 97国产在线观看| 欧美激情在线观看视频| 久久久免费精品视频| 国产99久久精品一区二区| 亚洲iv一区二区三区| 亚洲男人天堂2019| 日韩欧美亚洲国产一区| 日本在线观看天堂男亚洲| 中文字幕亚洲综合| 欧美精品videossex88| 欧美不卡视频一区发布| 2019国产精品自在线拍国产不卡| 亚洲第一天堂av| 在线成人激情视频| 久久视频免费观看| 亚洲aaa激情| 中国人与牲禽动交精品| 欧美日产国产成人免费图片| 亚洲三级 欧美三级| 久热99视频在线观看| 欧美精品在线免费| 欧美精品少妇videofree| 中文字幕精品久久| 久久久久久美女| 欧美精品免费在线观看| 亚洲偷熟乱区亚洲香蕉av| 中文字幕亚洲综合久久筱田步美| 欧美性受xxxx黑人猛交| 性色av一区二区三区在线观看| 亚洲伊人成综合成人网| 久久久精品视频成人| 亚洲香蕉成人av网站在线观看| 操日韩av在线电影| 91情侣偷在线精品国产| 国产精品久久久久秋霞鲁丝| 日韩在线视频线视频免费网站| 欧美特级www| 亚洲成人教育av| 日韩在线中文视频| 国产精品美女久久久免费| 欧美理论电影在线观看| 国产午夜精品一区二区三区| 国产综合香蕉五月婷在线| 欧美日韩午夜视频在线观看| 日韩欧美中文免费| 欧美日韩高清区| 国产精品久久久久久久久久免费| 久久精品在线视频| 亚洲精品v天堂中文字幕| 色噜噜狠狠色综合网图区| 亚洲自拍偷拍视频| 欧美在线视频播放| 精品久久香蕉国产线看观看gif| 欧美电影免费观看| 欧美视频在线观看 亚洲欧| 国产丝袜精品第一页| 欧美一级大片在线观看| 日韩欧美亚洲一二三区| 亚洲福利视频久久| 国产视频精品在线| 2019亚洲男人天堂| 亚洲成人网在线| 欧美国产精品日韩| 国产精品激情av在线播放| 国产精品入口免费视频一| 97涩涩爰在线观看亚洲| 亚洲综合中文字幕在线观看| 亚洲精品日韩激情在线电影| 欧美成人免费观看| 激情av一区二区| 国产精品网站入口| 最近2019年日本中文免费字幕| 久久人91精品久久久久久不卡| 色黄久久久久久| 亚洲香蕉伊综合在人在线视看| 国产日产久久高清欧美一区| 久久在线视频在线| 成人春色激情网| 国产一区二区三区在线视频| 欧美国产日韩xxxxx| 97色在线观看免费视频| 性欧美在线看片a免费观看| 日韩电影免费观看在线| 在线成人免费网站| 国产欧美精品日韩| 91久久在线播放| 久久99亚洲精品| 成人妇女淫片aaaa视频| wwwwwwww亚洲| 日韩h在线观看| 国产91亚洲精品| 国产美女久久久| 日韩欧美亚洲成人| 少妇高潮久久77777|