JAX-RS20REST客戶端編程實例-Java開發Java經驗技巧_第1頁
JAX-RS20REST客戶端編程實例-Java開發Java經驗技巧_第2頁
JAX-RS20REST客戶端編程實例-Java開發Java經驗技巧_第3頁
JAX-RS20REST客戶端編程實例-Java開發Java經驗技巧_第4頁
JAX-RS20REST客戶端編程實例-Java開發Java經驗技巧_第5頁
已閱讀5頁,還剩9頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、jax-rs 2.0 rest客戶端編程實例-編程 開發技術jax-rs 2.0 rest客戶端編程實例木文由importnew 靳禹翻譯自hascodc。歡迎加入翻譯小組。轉載請見文末要求。導讀jax-rs72. 0?乂稱?jsr?339?不僅定義了一套用于構建?restful?網絡服務 的?api,同時也通過增強客戶端?api功能簡化了 rest?客戶端的構建過程。jax-rs: java api for restful web services 是一個 java 編程 語言的應用程序接口,支持按照?表象化狀態轉變? (rest)架構風格 創建web服務web服務.jax-rs使用t ja

2、va se 5引入的java標 注來簡化web服務客戶端和服務端的開發和部署?wikipedia。在下面的教程中,我們將為一個預先設置好的?rest?服務構建一個客戶端,并在 這個過程屮探索新的構建選項。例如,如何處理同步或者異步的請求,如何給一 個請求注冊一個回調,如何指定調用對象來構建一個請求使得請求可以被延遲執 行。再或者比如,如何使用客戶端請求和相應的過濾方法來過濾客戶端與服務器 之前的通信。我們開始吧對于想要重建下述客戶端例子的讀者,我已經使用?maven創建好了一個完整 的?restful?網絡服務程序。程序中有內歐的應用程序服務器,以及一個可獨立 運行的應用服務器(war-fil

3、e?可以通過下文屮的下載地址獲取)。請根據下面的一系列命令來下載并啟動?rest?服務器(下載所有依賴可能會耗 費些時間):clone /hascode/jaxrs2client-tutoria1. git && cd jaxrs2-client-tutorial && make rest-scrvcr現在,讓我們先來看看這個?rest?服務的一些實現細節和我們的客戶端示例中要 用到的對彖。如果你對這些沒什么興趣,大可以略過服務端的細節直接去看客戶 端示例。rest?服務下面的代碼就是個客戶端提供服務的?rest?服務。這

4、里的?bookrepository?就是 一個由?singletorr和?加p?修飾的簡單 session bean,這個?bean?用來模擬存儲或獲取book entityo服務對外捉供了保存一本書、刪除一本書、根據 標識查找書籍和獲取所有可用書籍的接口。當一本書被保存在服務端時,服務器 會為該書生成一個?id,并會返冋一個entity或一組entity的js0n數據。packeige com. hascode. tutorial, jaxrs. server;import java. util. list;import javax. ejb. ejb;import javax. ejb.

5、stateless;import javax. ws. rs. consumes;import javax. ws. rs. delete;import javax. ws. rs. get;import javax. ws. rs. post;import javax. ws. rs. path;import javax. ws. rs. pathparam;import javax. ws. rs. produces;import javax. ws. rs. core. genericentity;import javax. ws. rs. core. mediatype;import

6、javax. ws. rs. core. response;import com. hascode. tutorial, jaxrs. entity. book;statelesspath("/book")public class bookstoreservice ejbprivate bookrepository bookrepository;post©consumes(mcdiatypc. application,json)©produces(mediatype. application,json) public response savebook(

7、final book book) book bookpersisled = bookrepository. savebook(book); return response, ok(bookpersisted). buildo ;©deletepath(/id)public response deletebook(final pathparam(z,idz,) string id) bookrepository. deletebook(id);return response, ok (). buiid ();get©produces(mediatype. applicatio

8、n_json) public response getall() li st<book> books = bookrepository. gegcncricentity<listbook>> bookwrappcr 二 new genericentity<list<book>>(books) ;return response, ok(bookwrapper). build();getpath("/id “)©produces(mediatype. application_json)public response getb

9、yid(final pathparam(id)string id) book book = bookrepository. getbytd(id);return rcsp on sc. ok (book). build();備注:我修改了應用服務器,以便使用?jackson提供的服務發現機制處理?json? 數據。book entity下而代碼屮的?bean?就是貫穿本教程的book entity,它包含id、書名、價格 和出版日期屬性。package com. hascode. tutorial, jaxrs.enti ty;import java. io. serializable; im

10、port java. math. bigdecimal;import java.util calendar;public class book implements serializable privatc static final long serialversionuid = il;private string id;private string title; private bigdecimal price; private calendar published;/ getter+setter.創建并綁定一個客戶端我們可以創建一個?rest?客戶端,將其綁定到一個特定的目標?url?一上

11、。并且為 它指定專屬的、參數化的路徑。具體步驟如下: 通過?clientbuilder?獲取一個客戶端的引用:client?client?=?clientbiulder.newclient();使用?target()?方法將客戶端綁定到?rest?服務上提供的某個?url:client.targetfhttpv/localhostoso/myrestseryice “); 通過?path()?和? resolvetemplateo?方法來處理動態的? url?路徑參數: client.target(.).path(itlid,).resolvetetnplate(iiicr?soineld);

12、使用?request()?w數來初始化一個請求并用后續的?post?或者?get?等方法來指定請 求的類型,例如:client.target(.).request().get();每一步都提供了多樣的可選擇的參數和配置選項,稍麻的教程中我將用到其屮的一 些配進像異步請求、回調處理、還有過濾器注冊和特性類等。現在,讓我們先看一些具備說明性的例子。客戶端例子由于我把所有客戶端示例都融進了?junit?和?hamcrest?駆動的測試用例,因此 下面的代碼實際上在每一個測試用例屮都有使用。不過為了讓文章盡量簡練,重 復代碼將在后面的代碼示例中省略。private static final priva

13、te static finalprivate static final string rest_service_url 二 "http: /localhost: 8080/tutor ial/rs/book,z;string title 二 0ne big book"bigdecimal price 二 new bigdecimal("20. 0");gregorianca1cndar published = new12, 24);private static finalgregoriancalendar (2013,client client 二cli

14、cntbuildcr. ncwclient() register(jacksonfcaturc. class);public book mockbook() book book 二 new book ();book.settitle (title);book.sctprice (price);book.setpublished (published); return book;唯一值得注意的是,我在客戶端運行時屮加入了?jackson?框架,因此可以通 ?javax. ivs. rs. client. clientbuildei來獲取客戶端實例。maven?整合所冇代碼示例運行都需要用到下面依

15、賴:<dcpcndcncy><groupld>org. glassfish, jersey. core</groupld> <artifactld>jersey-client</artifactld> <version>2. 5</version></dependency><dcpcndcncy><groupld>org. glassfish, jersey. media</groupld> <artifactid>jersey-media-json-

16、jackson</artifactid> <version>2. 5</version></dependency>基礎操作下面的示例中我們首先將一個書本實體的信息序列化成?jsoy?格式,通過?post? 請求發送到服務端來保存這木書。之后,我們使用客戶端提供的?p& th 0湘j ? resol ve tempi ate o?jj法通過匹配服 務端返回值的協議來獲取該木書的標識。第三步,我們獲取所有可用圖帖的列表,并在最后刪除掉剛才保存的那本帖。©testpublic void crudexample() / 1. save

17、a new bookbook book 二 mockbook ();book bookpersisted = die nt target (rest_service_url) request () post (entity. entity(book, mediatype. application_json),book, class);string bookid 二 bookpersisted. getld(); assertthat (booktd, notnullvalue ();/ 2. fetch book by idbook book2 = client, target (rest_s

18、ervice_url). path(z,/bookidresolvetemplate(bookict, bookid) request(). get(book class);assertthat (book2, notnulivalue ();asscrtthat(book2.gcttitlc(), cqualto(title);assertthat (book2. getprice(), equalto (price);assertthat(book2. getpublished(). gettime(), equalto(published. gettimeo);/ 3- fetch al

19、l booksgenerictype<list<book» booktype = new generictype<list<book>> () ; / generic type to wrap a generic list of bookslist<book> books 二 client.target (rest servtce url). request() get (booktype);assertthat(books, size(), equalto(l);/ 4. delete a bookclient, target(res

20、t_service_url) path(7bookid)resolvetemplatc(bookld, bookld) request (). delete ();list<book> books2 = client.target (rest servicejjrl). request() get (booktype);assertthat (books2. isempty (), equalto (true);異步處理只要給請求構造器加一個簡單的async 0?h法,我們就可以使用?java? 的?future? 提供的多種途徑來異步地處理請求。下面的例子中,我們在第一個請求中添

21、加一本書,然后再刪除它。最后獲取所冇 可用圖書的列表。test public void asyncexample() throws exception book book = mockbook ();futurc<book> fb = client target(rest_service_url) reques t () asy nc () post (entity, entity(book, mediatype. applicationjson),book, class);book bookpersisted 二 fb. get();string bookid 二 bookpcr

22、sisted. gctld ();assertthat (bookld,notnullvalue ();client, target (rest_service_url). path(/bookid) resolvetempla te (bo()kld,bookid) request () async () delete () get ();future<list<book» bookrequest 二client, target(rest_servtce_url) request () async () get (newgenerictypelistbook>&g

23、t;() );list<book> books2 二 bookrequest. get(); assertthat (books2 isempty (), equalto (true);發起回調在客戶端與服務器通信過程中,我們還有另一種方式可以對服務器的相應進行修 改,那就是在請求屮加入一個?invocationcal lback?冋調處理。可以看到,下面代碼段中有著很多縮進那部分就是我們的回調函數了,這些回調 可以打卬保存成功的圖書的完整信息,或者在出現錯誤的情況下則打卬錯誤和堆 棧信息。testpublic void invocationcalibackexample() th

24、rows exception book book 二 mockbook ();client.target(rest service url) request () asy nc () post (entity. entity(book,mediatype. application_json),new invocationcallbackbook>() ©overridepublic void completed(final book bookpersisted) sys tent out. printin (,zbook saved:+ bookpersisted);asser

25、tthat(bookpersisted. getld (),notnullvalue ();©override public void failed (final throwab1e throwab1e) throwable. printstacktrace(); ). get();client, target (rest service url) request() async() get(new invocationcallback<list<book>>() 0verri depublic void completcd(final listbook>

26、; books) system. out. println (books, size () + books received'7);assertthat (books, size ()、 greaterthanorequalto(l);©overridepublic void failed(final throwable throwable) throwable. printstacktrace (); ). get();延遲調用?/?請求構建通過? javax. ivs. rs. client. invocatiorr類,我們可以先構建一個請求而不用即 時發送。這個請求可以

27、是同步的,?也可以是異步的。在下面的示例屮,我們構建了兩個調用但并不馬上使用個請求用來保存 圖書,另一個請求則是獲取所有可用的圖書。然后,我們在后面調用吋才使用這 兩個構建好的請求。我們應當使用?invokc()?法來同步地調用一個請求。當需要使用異步請求時, 則需要用?subn】it()m法兩種調用都會返回一個?javax. ws. rs. core. response?辣。如果調用者在調用參數中給定了返冋實 體的類,則上述方法會返回該類。testpublic void requcstpreparationexample() throws exception book book 二 mock

28、booko ;invocation savebook 二 client, target (rest_service_url). request () buildpost(entity. entity(book,mediatype. application_json);invocation listbooks =client, target(rest_serv1ce_url). request () buildget ();response response 二 savebook. invoke (); book bl = response- rcaclentity (book, class);

29、/ alternative: book bl 二 savebook. invoke (book, class); assertthat (bl. getldo, notnullvalue();/ async invocationfuture<list<book» b 二 listbooks. submit(new generictype<listbook>>() );listbook> books = b. get();assertthat (books.size (), grcatcrthanorequalto (2);客戶端請求過濾器jax-r

30、s?允許我們使用請求過濾器來截獲客戶端發送到服務器的請求。為 了達成這個 口標,只需要實現?javax. ws. rs. client. cliontroquestfil ter? 這個接口。當創建客戶端時,使用客戶端的?register()?法將?c1 i en treques tfi 1 ter啲具體實現注冊到客戶端中。javax. ws. rs. client. clientrequestcontext象將賦了訪問信息請求足夠的 權限。下面就是一個客戶端請求過濾的例了。這個例了中,所有客戶端發出的?post? 請求屮如果包含書籍實體,則書籍價格都會被這個過濾器修改(雖然這不是一個 好的實

31、際示例)。對價格的修改則依據相應的稅率。package com. hascode. tutorial, client;import java. io. ioexception;import java. math. bigdecimal;import javax. ws. rs. client. clientrequestcontext;import javax. ws. rs. client. clientrequestfilter;import com. hascode. tutorial. jaxrs. entity. book;public class taxadjustmentfilt

32、er implements clientrequestfilter public static final bigdecimal tax rate = new bigdecimal (,z2. 5); ©overridepublic void f訂tcr(final clicntrcquestcontcxt rc) throws loexception string method = rc. getmethod();if (z,postz,. equals (method) && rc. hasentity () book book = (book) rc. gete

33、ntityo; bigdecimal pricewithtaxcs 二book. getprice(). multiply(tax_rate);book.setprice (pricewithtaxes); rc.setentity(book);在我們的測試用例中,只耍把這個過濾器注冊到客戶端上,隨后就會看到:保存 書籍時候,書本的價格就會根據稅率進行的調整。testpublic void clientrequestfi1terexample() book book = mockbook();client client 二 clientbuilder.newclient() register

34、(jeicksonfcaturc. class) register(taxadjustmentfilter. class);book bookpersisted = client target (rest_service_url) request () post (entity. entity(book,mediatype. application_json),book, class);string bookid = bookpersisted. getldo ; assertthat (bookid, notnullvalue(); assertthat(bookpersisted. get

35、price(),equalto(price, multiply (taxadjustmentftax_rate);客戶端響應過濾器為了獲得對服務器相應的控制,有一個十分類似的辦法:客戶端相應過濾器。同樣地,只要實現?7日炮¥. ©s. rs. client. clientresponsefilter?區個接口,就 能夠修改或者截獲服務器返冋的響應。下面這個響應過濾器能夠將一些?http?響應頭打印到標準輸出(stdout):package com. hascode. tutorial. client;import java. io. loexception;import j

36、ava. util. list;import java, ut訂.map entry;import javax. ws. rs. clicnt. clicntrcqucstcontcxt;import javax. ws. rs. client. clientresponsecontext; import javax. ws. rs. client. clientresponsefilter;public class clientresponseloggingfi1 ter implementsclientresponsefilter ©overridepublic void fil

37、ter (final clientrequestcontext reqctx,final clientresponsecontext resctx) tbrows ioexception system, out. printin("status: " + resctx. getstatus();system, o ut pri nt in ("date: " + resctx. getdateo);system, out. printin(z,last-modified: " +resctx. getlastmodi fi ed();syste

38、m, out. println(/zlocation: " +resctx. getlocation();system, out. printin("headers:"); for (entrystring, list<string>> header :resctx. getheaders() entryset () system. out. pri+ header. getkey () + :); for (string value : header.getvalue() system, o ut .pri nt( value + "、“);system out. print (n); system, out. pr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論