servicii Web, într-o formă sau alta, au fost în jur de mai mult de două decenii. De exemplu, serviciile XML-RPC au apărut la sfârșitul anilor 1990, urmate în scurt timp de cele scrise în offshoot-ul SOAP. Servicii în restul stil arhitectural, de asemenea, a făcut scena în urmă cu aproximativ două decenii, la scurt timp după XML-RPC și săpun trailblazers. Serviciile în stil REST (în continuare, Restful) domină acum pe site-uri populare precum eBay, Facebook și Twitter. În ciuda alternativelor la serviciile web pentru calculul distribuit (de ex., serviciile web Restful rămân atractive din mai multe motive:
-
serviciile Restful se bazează pe infrastructura și protocoalele existente, în special pe serverele web și pe protocoalele HTTP/HTTPS. O organizație care are site-uri web bazate pe HTML poate adăuga cu ușurință servicii web pentru clienții interesați mai mult de date și de funcționalitatea de bază decât de prezentarea HTML., Amazon, de exemplu, a inițiat punerea la dispoziție a acelorași informații și funcționalități atât prin intermediul site-urilor web, cât și al serviciilor web, fie pe bază de săpun, fie odihnitor.serviciile Restful tratează HTTP ca un API, evitând astfel stratificarea software complicată care a ajuns să caracterizeze abordarea bazată pe SOAP a serviciilor web. De exemplu, API-ul Restful acceptă operațiunile standard CRUD (Create-Read-Update-Delete) prin verbele HTTP POST-GET-PUT-DELETE, respectiv; codurile de stare HTTP informează un solicitant dacă o solicitare a reușit sau de ce a eșuat.,serviciile web Restful pot fi la fel de simple sau complicate după cum este necesar. Restful este un stil—într-adevăr, unul foarte flexibil-mai degrabă decât un set de prescripții despre modul în care serviciile ar trebui să fie proiectate și structurate. (Dezavantajul însoțitor este că poate fi greu pentru a determina ceea ce nu contează ca un serviciu odihnitor.pentru un consumator sau client, serviciile web Restful sunt neutre din punct de vedere lingvistic și al platformei. Clientul face cereri în HTTP(S) și primește răspunsuri text într-un format adecvat pentru schimbul de date moderne (de exemplu, JSON).,aproape fiecare limbaj de programare cu scop general are cel puțin suport adecvat (și adesea puternic) pentru HTTP/HTTPS, ceea ce înseamnă că clienții de servicii web pot fi scrise în acele limbi.
acest articol explorează servicii ușoare Restful în Java printr-un exemplu de cod complet.
Odihnitor romane de servicii web
Odihnitor romane serviciu web este format din trei programator-definite clase:
-
Novel
clasa reprezintă un roman cu doar trei proprietăți: o mașină generat de IDENTITATE, un autor, și un titlu., Proprietățile ar putea fi extinse pentru mai mult realism, dar vreau să păstrez acest exemplu simplu.
-
Novels
clasa este format de utilități pentru diferite sarcini: conversia unui text simplu de codare de unNovel
sau o listă a acestora în XML sau JSON; sprijinirea operațiunile CRUD pe romanele de colectare; și inițializarea colecție de date stocate într-un fișier. ClasaNovels
mediază între instanțeleNovel
și servlet.,
-
NovelsServlet
clasa derivă dinHttpServlet
, un robust și flexibil bucată de software-ul care a fost în jurul valorii de foarte devreme enterprise Java de la sfârșitul anilor 1990. Servlet acționează ca un HTTP final pentru client CRUD cereri. Codul servlet se concentrează pe procesarea cererilor clientului și generarea răspunsurilor corespunzătoare, lăsând detaliile diabolice utilităților din clasaNovels
.unele cadre Java, cum ar fi Jersey (JAX-RS) și Restlet, sunt proiectate pentru Servicii odihnitoare., Cu toate acestea,HttpServlet
pe cont propriu oferă un API ușor, flexibil, puternic și bine testat pentru furnizarea unor astfel de servicii. Voi demonstra acest lucru cu exemplul romanelor.implementați serviciul web romane
implementarea serviciului web romane necesită un server web, desigur. Alegerea mea este Tomcat, dar serviciul ar trebui să funcționeze (ultimele cuvinte celebre!) dacă este găzduit pe, de exemplu, Jetty sau chiar un server de aplicații Java. Codul și un README care rezumă modul de instalare Tomcat sunt disponibile pe site-ul meu., Există, de asemenea, un script documentat Apache Ant care construiește serviciul romanelor (sau orice alt serviciu sau site web) și îl implementează sub Tomcat sau echivalentul.
Tomcat este disponibil pentru descărcare de pe site-ul său. După ce îl instalați local, lăsați
TOMCAT_HOME
să fie directorul de instalare., Există două subdirectoare de interes imediat:-
TOMCAT_HOME/bin
director conține pornire și oprire script-uri pentru sistemele Unix-like (startup.sh
șishutdown.sh
) și Windows (startup.bat
șishutdown.bat
). Tomcat rulează ca o aplicație Java. Container servlet serverului web este numit Catalina. (În Jetty, serverul web și containerul au același nume.) Odată ce Tomcat pornește, introducețiîntr-un browser pentru a vedea documentație extinsă, inclusiv exemple.,directorul
-
TOMCAT_HOME/webapps
este implicit pentru site-urile web și serviciile web implementate. Simplu mod de a implementa un site sau serviciu web este de a copia un fișier JAR cu un.war
extensia (prin urmare, un fișier WAR) pentruTOMCAT_HOME/webapps
sau un subdirector al acestuia. Tomcat despachetează apoi fișierul de război în propriul său director. De exemplu, Tomcat ar despachetanovels.war
într-un subdirector numitnovels
, lăsândnovels.war
ca-este., Un site web sau un serviciu poate fi eliminat prin ștergerea fișierului WAR și actualizat prin suprascrierea fișierului WAR cu o nouă versiune. Apropo, primul pas în depanarea unui site web sau a unui serviciu este să verificați dacă Tomcat a despachetat fișierul de război; dacă nu, site-ul sau serviciul nu a fost publicat din cauza unei erori fatale în cod sau configurație., -
Pentru Tomcat ascultă în mod implicit pe portul 8080 pentru cereri HTTP, o cerere URL-ul pentru Tomcat de pe mașina locală începe:
Access a programmer-deployed WAR file by adding the WAR file’s name but without the
.war
extension:If the service was deployed in a subdirectory (e.g.,
myapps
) ofTOMCAT_HOME
, this would be reflected in the URL:I’ll offer more details about this in the testing section near the end of the article.
As noted, the ZIP file on my homepage contains an Ant script that compiles and deploys a website or service. (A copy of
novels.war
is also included in the ZIP file.) For the novels example, a sample command (with%
as the command-line prompt) is:% ant -Dwar.name=novels deploy
Aceasta comanda compilează fișierele sursă Java și apoi construiește un dislocabile fișier numit
novels.war
, frunzele acest fișier în directorul curent, și copii săTOMCAT_HOME/webapps
., Dacă totul merge bine, unGET
cerere (folosind un browser sau un utilitar de linie de comandă, cum ar ficurl
) servește ca un prim test:% curl http://localhost:8080/novels/
Tomcat este configurat, în mod implicit, pentru hot implementează: serverul web nu trebuie să fie închisă pentru a implementa, actualiza, sau a elimina o aplicație web.
serviciul romanelor la nivel de cod
Să revenim la exemplul romanelor, dar la nivel de cod. Luați în considerare clasa
Novel
de mai jos:Exemplul 1., Romanul clasa
Această clasă implementează
compareTo
metoda deComparable
interfață pentruNovel
cazuri sunt stocate într-un fir de siguranțăConcurrentHashMap
, care nu impune o ordine sortată. În răspuns la solicitările de a vizualiza o colecție de romane de servicii felul o colecție (oArrayList
) extrase de pe hartă; punerea în aplicare acompareTo
impune o ordine crescătoare ordine sortată prinNovel
ID.,clasa
Novels
conține diferite funcții de utilitate:Exemplul 2. Clasa de utilitate romane
metoda cea mai complicată este
populate
, care se citește dintr-un fișier text conținut în fișierul de război desfășurat. Fișierul text conține colecția inițială de romane. Pentru a deschide fișierul text,populate
metoda trebuieServletContext
, un Java hartă care conține toate informațiile critice despre servlet încorporate în container de servlet., Fișierul text, la rândul său, conține înregistrări, cum ar fi acest lucru:Jane Austen!Persuasion
linia este analizat în două părți (autorul și titlul), separate printr-bang simbolul (
!
). Metoda construiește apoi o instanțăNovel
, stabilește proprietățile autorului și titlului și adaugă romanul la colecție, care acționează ca un depozit de date în memorie.Novels
clasa are, de asemenea, utilitare pentru a codifica colecția de romane în XML sau JSON, în funcție de formatul pe care solicitantul îl preferă., XML este implicit, dar JSON este disponibil la cerere. Un pachet XML-to-JSON ușor oferă JSON. Mai multe detalii despre codificare sunt mai jos.Exemplul 3. La NovelsServlet clasa
Reamintim că
NovelsServlet
clasa de mai sus se extindeHttpServlet
clasa, care la rândul său se extindeGenericServlet
clasa, care implementeazăServlet
interfata:NovelsServlet extends HttpServlet extends GenericServlet implements Servlet
Ca numele face clar,
HttpServlet
este proiectat pentru servlet-uri livrate prin HTTP(S)., Clasa oferă gol metode numit după cerere HTTP standard verbe (oficial, metode):-
doPost
(Post = Crea) -
doGet
(Ia = a Citi) -
doPut
(Pune = Update) -
doDelete
(Delete = Șterge)
Unele suplimentare HTTP verbe sunt acoperite, de asemenea. O extensie a
HttpServlet
, cum ar fiNovelsServlet
, anulează oricedo
metoda de interes, lăsând pe alții așa cum nu-ops.,NovelsServlet
înlocuiește șapte dintre metodeledo
.fiecare dintre metodele
HttpServlet
CRUD are aceleași două argumente. Aici estedoPost
ca un exemplu:public void doPost(HttpServletRequest request, HttpServletResponse response) {
request
argument este o hartă de cerere HTTP informații, șiresponse
oferă un flux de ieșire înapoi solicitantului., O metodă cum ar fidoPost
este structurat după cum urmează:- Citeste
request
informații, luând orice măsură necesară pentru a genera un răspuns. Dacă informațiile lipsesc sau sunt deficitare în alt mod, generați o eroare.
- de a Folosi extrase solicita informații pentru a efectua adecvat CRUD funcționare (în acest caz, de a crea un
Novel
) și apoi codifica un răspuns adecvat la solicitant folosindresponse
flux de ieșire să facă acest lucru., În cazuldoPost
, răspunsul este o confirmare a faptului că un nou roman a fost creat și adăugat la colecție. Odată ce răspunsul este trimis, fluxul de ieșire este închis, ceea ce închide și conexiunea.
mai multe despre metoda do suprascrie
o cerere HTTP are o structură relativ simplă. Iată o schiță în HTTP 1 familiar.,1 format, cu comentarii introduse de dublu semne clare:
linia De start incepe cu HTTP verb (în acest caz,
GET
) și URI (Uniform Resource Identifier), care este substantiv (în acest caz,novels
) ca nume vizate de resurse. Anteturile constau din perechi cheie-valoare, cu un punct care separă cheia din stânga de valoarea(valorile) din dreapta., Antetul cu tastaHost
(case insensitive) este necesar; hostnamelocalhost
este simbolic adresa locale masina de pe mașina locală, și numărul de port8080
este implicit pentru Tomcat web server așteaptă cereri HTTP. (În mod implicit, Tomcat ascultă pe portul 8443 pentru cererile HTTPS.) Elementele antetului pot apărea în ordine arbitrară. În acest exemplu, valoarea antetuluiAccept-type
este tipul MIMEtext/plain
.,Unele cereri (în special,
POST
șiPUT
) au trupuri, în timp ce altele (în special,GET
șiDELETE
) nu. Dacă există un corp (poate gol), două linii noi separă anteturile de corp; corpul HTTP este format din perechi cheie-valoare. Pentru cererile fără corp, elementele antetului, cum ar fi șirul de interogare, pot fi utilizate pentru a trimite informații., Aici este o cerere de aGET
/novels
resurse cu ID-ul de 2:GET /novels?id=2
șirul De interogare începe cu semnul de întrebare și, în general, constă din perechi cheie-valoare, deși o cheie fără o valoare este posibil.
HttpServlet
, cu metode, cum ar figetParameter
șigetParameterMap
, frumos se ascunde distincția între cereri HTTP cu și fără trup., În romanele exemplu,getParameter
metodă este folosită pentru a extrage informațiile necesare din parteaGET
,POST
șiDELETE
cereri. (Manipularea unuiPUT
cerere necesită cod de nivel inferior, deoarece Tomcat nu oferă o hartă parametru funcțional pentruPUT
cereri.,) Aici, pentru ilustrare, o felie dedoPost
metoda înNovelsServlet
override:Pentru o bodyless
DELETE
cerere, abordarea este în esență același:doGet
metoda trebuie să se facă distincția între două arome de unGET
cerere: o aroma înseamnă „toate”, întrucât alte mijloace de a obține un anumit una., DacăGET
cerere URL-ul conține un șir de interogare a cărui cheie este un ID, atunci cererea este interpretat ca fiind „cea specificată”:http://localhost:8080/novels?id=2 ## GET specified
Dacă nu există nici un șir de interogare,
GET
cererea este interpretat ca „toate”:http://localhost:8080/novels ## GET all
diabolic detalii
romanele servicii de design reflectă modul în care un bazate pe Java web server, cum ar fi lucrări de Tomcat. La pornire, Tomcat construiește un pool de fir din care sunt desenate manipulatorii de Cereri, o abordare cunoscută sub numele de modelul one thread per request., Versiunile moderne ale Tomcat folosesc, de asemenea, I/O care nu blochează pentru a spori performanța.
serviciul romane execută ca o singură instanță a clasei
NovelsServlet
, care la rândul său menține o singură colecție de romane. În consecință, ar apărea o condiție de cursă, de exemplu, dacă aceste două solicitări ar fi procesate simultan:- o cerere schimbă colecția adăugând un nou roman.
- cealaltă cerere primește toate romanele din colecție.
rezultatul este nedeterminat, în funcție de exact cum se suprapun operațiunile de citire și scriere., Pentru a evita această problemă, serviciul romanes folosește un fir sigur
ConcurrentMap
. Cheile pentru această hartă sunt generate cu un fir sigurAtomicInteger
. Aici este segmentul de cod relevant:public class Novels {
private ConcurrentMap<Integer, Novel> novels;
private AtomicInteger mapKey;
...în mod implicit, un răspuns la o solicitare client este codificat ca XML. Programul romanelor folosește clasa
XMLEncoder
pentru simplitate; o opțiune mult mai bogată este biblioteca JAX-B., Codul este simplu:Object
parametru este fie un sortateArrayList
de romane (ca răspuns la o „ia tot” cerere); sau un singurNovel
exemplu (ca răspuns la o cerere); sau unString
(un mesaj de confirmare).dacă un antet de solicitare HTTP se referă la JSON ca tip dorit, atunci XML este convertit în JSON., Aici este check-in-ul
doGet
metoda deNovelsServlet
:String accept = request.getHeader("accept"); // "accept" is case insensitive
if (accept != null && accept.contains("json")) json = true;Novels
clasa de casetoJson
metoda, care transformă XML JSON:NovelsServlet
verifică erorile de diferite tipuri. De exemplu, o solicitarePOST
ar trebui să includă un autor și un titlu pentru noul roman., Dacă lipsește,doPost
metoda arunca o exceptie:if (author == null || title == null)
throw new RuntimeException(Integer.toString(HttpServletResponse.SC_BAD_REQUEST));SC
înSC_BAD_REQUEST
standuri pentru cod de stare, șiBAD_REQUEST
standard HTTP valoare numerică de 400. Dacă HTTP verb într-o cerere esteTRACE
, un alt cod de stare este returnat:Testarea romane de servicii
Testarea unui serviciu web cu un browser este complicat., Printre verbele CRUD, browserele moderne generează doar
POST
(Create) șiGET
(Read) cereri. Chiar și oPOST
cerere este o provocare de la un browser, ca valorile-cheie pentru organismul trebuie să fie incluse; acest lucru se face de obicei printr-un formular HTML. O utilitate linie de comandă, cum ar fi curl este o modalitate mai bună de a merge, ca această secțiune ilustrează cu unelecurl
comenzi, care sunt incluse în ZIP pe site-ul meu.,iată câteva teste de probă fără ieșirea corespunzătoare:
% curl localhost:8080/novels/
% curl localhost:8080/novels?id=1
% curl --header "Accept: application/json" localhost:8080/novels/prima comandă solicită toate romanele, care sunt codificate implicit în XML. A doua comandă solicită romanul cu un ID de 1, Care este codificat în XML. Ultima comandă adaugă un
Accept
antet element cuapplication/json
ca tip MIME dorit. Comandaget one
ar putea folosi și acest element de antet. Astfel de cereri au JSON, mai degrabă decât răspunsurile XML.,următoarele două comenzi crea un nou roman în colecția și confirma plus:
% curl --request POST --data "author=Tolstoy&title=War and Peace" localhost:8080/novels/
% curl localhost:8080/novels?id=4PUT
comandacurl
seamănă cu unPOST
comanda cu excepția faptului căPUT
corpul nu folosește sintaxa standard. Documentația pentrudoPut
metoda înNovelsServlet
merge în detaliu, dar versiunea scurtă este că Tomcat nu generează o harta buna pePUT
cereri., Aici este probaPUT
comandă și o confirmare de comandă:% curl --request PUT --data "id=3#title=This is an UPDATE" localhost:8080/novels/
% curl localhost:8080/novels?id=3Cea de-a doua comandă confirmă actualizarea.
în cele din urmă, comanda
DELETE
funcționează conform așteptărilor:% curl --request DELETE localhost:8080/novels?id=2
% curl localhost:8080/novels/cererea este ca romanul cu ID-ul 2 să fie șters. A doua comandă Arată romanele rămase.
web.fișierul de configurare xml
deși este oficial opțional, un fișier de configurare
web.xml
este un element principal într-un site web sau serviciu de producție., Fișierul de configurare permite rutarea, securitatea și alte caracteristici ale unui site sau serviciu să fie specificate independent de codul de implementare. Configurația pentru romanele de servicii se ocupă de rutare prin furnizarea unui model de URL pentru cereri expediate la acest serviciu:servlet-name
element oferă o abreviere (novels
) pentru servlet este complet calificat nume de clasă (novels.NovelsServlet
), și acest nume este utilizat înservlet-mapping
element de mai jos.,Reamintim că un URL pentru un implementat serviciul de numele fișierului WAR după numărul de port:
slash imediat după numărul de port începe URI cunoscute ca calea spre resursa solicitată, în acest caz, romane de serviciu; prin urmare, termenul
novels
apare după primul single slash.În
web.xml
fișier,url-pattern
este specificat ca/*
, ceea ce înseamnă că orice drum începe cu /romane., Să presupunem că Tomcat întâlnește un contrived cerere URL, cum ar fi acest lucru:web.xml
configurare specifică faptul că această cerere, de asemenea, ar trebui să fie expediate către romane servlet pentru că/*
model acoperă/foobar
. URL-ul contrived are astfel același rezultat ca cel legitim prezentat mai sus.un fișier de configurare la nivel de producție poate include informații despre securitate, atât la nivel de fir, cât și la nivel de utilizatori., Chiar și în acest caz, fișierul de configurare ar fi doar de două sau trei ori mai mare decât cel al eșantionului.
înfășurarea
HttpServlet
este în Centrul Tehnologiilor Web Java. Un site web sau un serviciu web, cum ar fi serviciul romanelor, extinde această clasă, depășind verbele de interesdo
. Un cadru Restful, cum ar fi Jersey (JAX-RS) sau Restlet face în esență același lucru prin furnizarea unui servlet personalizat, care apoi acționează ca punct final HTTP(S) pentru cererile împotriva unei aplicații web scrise în cadru.,o aplicație bazată pe servlet are acces, desigur, la orice bibliotecă Java necesară în aplicația web. Dacă cererea urmează separarea de preocupările principiu, atunci servlet codul rămâne atractiv, simplu: codul verifică o cerere, eliberarea de eroare corespunzător dacă există deficiențe; în caz contrar, codul apeluri pentru orice funcționalitate pot fi necesare (de exemplu, interogarea unei baze de date, codificarea un răspuns într-un anumit format), și apoi trimite raspunsul solicitantului.,
HttpServletRequest
șiHttpServletResponse
tipuri de face mai ușor pentru a efectua servlet-activitatea specifică de lectură la cerere și în scris răspunsul.Java are API-uri care variază de la foarte simplu la foarte complicat. Dacă trebuie să furnizați câteva servicii odihnitoare folosind Java, sfatul meu este să încercațiHttpServlet
înainte de orice altceva. -
Lasă un răspuns