Programování

REST pro vývojáře Java, část 2: Restlet pro unavené

Open-source Restlet API snižuje pracovní zátěž spojenou s vytvářením a spotřebováváním RESTful API v Javě. V tomto druhém článku v REST pro vývojáře Java Brian Sletten vám představí Restlet a provede ukázkovou aplikaci při nasazování jejích rozhraní do servletových kontejnerů, které používáte dnes, a zároveň se připravuje na systémy budoucnosti. Brian také krátce představuje JSR 311: JAX-RS, snahu společnosti Sun o integraci rozhraní RESTful API do zásobníku Java EE.

Vývojáři prostředí Java se dlouho zajímali o architektonický styl REST, ale jen málo z nich dosud urazilo vzdálenost mezi známým světem objektů a světem RESTful zdrojů. I když se nám může líbit skutečnost, že služby RESTful mohou být vytvářeny nebo spotřebovávány jinými jazyky, nenávidíme nutnost převádět data do a z bajtových proudů. Nesnášíme, když musíme myslet na HTTP, když používáme nástroje jako Apache HTTP Client. Toužebně se díváme na objekty vytvořené wsdl2java příkaz, který nám umožňuje předávat argumenty do služby SOAP stejně snadno jako jakékoli jiné volání metody, a zametat podrobnosti vyvolání vzdálené služby pod koberec. A zjistíme, že model servletu je jen trochu příliš odpojen od produkovaných zdrojů. Stačí říct, že když jsme byli schopný vybudovat služby RESTful od nuly, nebyl to příjemný zážitek.

REST pro vývojáře Java

Přečtěte si sérii:

  • Část 1: Jedná se o informace
  • Část 2: Restlet pro unavené
  • Část 3: NetKernel

Politické problémy někdy spojovaly technické překážky. Mnoho manažerů má pocit, že webové služby založené na protokolu SOAP jsou předepsaným způsobem vytváření architektur orientovaných na služby (SOA) v prostředí Java EE. To se mění se vznikem důležitých činností, jako jsou JSR 311, JAX-RS: Java API pro RESTful Web Services, o kterých se dozvíte v tomto článku. Pokud nic jiného, ​​toto úsilí legitimuje RESTful vývoj v prostoru JEE.

Mezitím dorazila pomoc. Elegantním způsobem umožňuje otevřený rámec Restletu vyhnout se trnitým problémům, které mohou nastat při používání tradiční technologie JEE k vytváření a využívání služeb RESTful.

Restletovy kořeny

Ve snaze řešit některé technické problémy spojené s prováděním REST s Javou se Jérome Louvel, francouzský softwarový konzultant, snažil vytvořit rámec, který by poskytoval přirozenější střih. Nejprve se podíval na prostředí NetKernel jako na výchozí bod. Jakkoli se mu líbilo, nebylo to perfektní řešení pro rámec zaměřený na API, který se snažil zpřístupnit. Zkušenost však pomohla ovlivnit jeho myšlení o tom, co všechno může prostředí orientované na REST nabídnout. (Následující článek v této sérii prozkoumá NetKernel podrobněji.)

Když Louvel pracoval na svém rámci, vytvořil tři cíle:

  • Pro základní použití by měly být jednoduché akce jednoduché. Výchozí hodnoty by měly fungovat s minimálním úsilím, ale také by měly umožňovat složitější konfigurace.
  • Kód zapsaný do tohoto API by měl být přenositelný napříč kontejnery. Přestože systémy založené na servletech lze přesouvat mezi kontejnery, jako jsou Tomcat, Jetty a IBM WebSphere, měl Louvel na mysli větší obrázek. Specifikace servletu je vázána na HTTP a blokující I / O model. Chtěl, aby jeho API bylo oddělitelné od obou a nasaditelné do dnes používaných kontejnerů. Také chtěl, aby byly použitelné s malým úsilím v alternativních a vznikajících kontejnerech, jako jsou Grizzly, AsyncWeb a Simple Framework.
  • Nemělo by to obohatit pouze serverovou stranu výroby rozhraní RESTful v Javě, ale také klientskou stranu. The HttpURLConnection třída a klient Apache HTTP jsou příliš nízké úrovně na to, aby se mohli čistě integrovat přímo do většiny aplikací.

S ohledem na tyto cíle se vydal na produkci Restlet API. Po několika letech vývoje se API stalo stabilním a kolem něj rostla komunita. Dnes má jádro API živou uživatelskou základnu a probíhají významné aktivity na podporu integrace s dalšími nástrojovými sadami a iniciativami, jako je JAX-RS. (Louvel je nyní ve skupině odborníků JAX-RS.)

Základy restletu

Základní server s Restlet API už snad nemůže být jednodušší, jak je uvedeno v seznamu 1.

Výpis 1. Základní server s Restletem

balíček net.bosatsu.restlet.basic; import org.restlet.Restlet; import org.restlet.Server; import org.restlet.data.MediaType; import org.restlet.data.Protocol; import org.restlet.data.Request; importovat org.restlet.data.Response; public class SimpleServer {public static void main (String [] args) throws Exception {Restlet restlet = new Restlet () {@Override public void handle (Request request, Response response) {response.setEntity ("Hello, Java RESTafarians!", MediaType.TEXT_PLAIN); }}; // Vyhněte se konfliktům s jinými kontejnery Java naslouchajícími na 8080! nový server (Protocol.HTTP, 8182, restlet) .start (); }}

Tato aplikace moc nedělá (kromě šíření dobré nálady), ale ukazuje dva základní principy společnosti Restlet. Za prvé, jednoduché věci jsou jednoduché. Složitější činnosti jsou jistě možné, ale staráte se o ně pouze tehdy, když potřebujete. RESTu nechybí schopnost vynucovat zabezpečení, omezení, vyjednávání obsahu nebo jiné důležité úkoly. Ty zůstávají převážně ortogonálními aktivitami, zcela odlišnými od procesu uspokojování RESTful API. Složitost navrstvíte podle potřeby.

Za druhé, kód v seznamu 1 je navržen tak, aby byl přenosný mezi typy kontejnerů. Všimněte si, že neurčuje kontejner. Restlets jsou skutečné zdroje, které nakonec reagují na požadavky. Neexistuje žádný rozdíl mezi kontejnerem zpracovávajícím požadavek a respondérem informačních zdrojů, jak může být v modelu servletu. Pokud zadáte kód do IDE a přidáte závislosti na org.restlet.jar a com.noelios.restlet.jar archivů, můžete aplikaci spustit a měla by se zobrazit taková zpráva protokolu:

7. prosince 2008 23:37:32 com.noelios.restlet.http.StreamServerHelper start INFO: Spuštění interního serveru HTTP

Nasměrujte prohlížeč na // localhost: 8182a měli byste vidět přátelský pozdrav.

V zákulisí org.restlet.jar obsahuje všechna hlavní rozhraní pro toto API. The com.noelios.restlet.jar obsahuje základní implementaci těchto rozhraní a poskytuje výchozí schopnost zpracování HTTP. S tímto modulem HTTP nebudete chtít přejít do výroby, ale pro účely vývoje a testování je to mimořádně výhodné. K otestování kódu RESTful nemusíte spustit hlavní kontejner. Výsledkem může být testování jednotek a integrace.

Ukázka v seznamu 1 používá k vytvoření výchozího nastavení hodně výchozího chování aplikace instance (budu diskutovat aplikace v dalším příkladu) a poslouchejte požadavky protokolu HTTP na portu 8182. The StreamServerHelper třída začne poslouchat na tomto portu a odešle požadavky do Restlet například jak přicházejí.

Cíl společnosti Louvel spočívající v podpoře RESTful Java na straně klienta je také snadno splněn, jak vidíte v seznamu 2.

Výpis 2. Klient Restlet

balíček net.bosatsu.restlet.basic; import java.io.IOException; import org.restlet.Client; import org.restlet.data.Protocol; public class SimpleClient {public static void main (String [] args) hodí IOException {String uri = (args.length> 0)? args [0]: "// localhost: 8182"; Klient klient = nový klient (Protocol.HTTP); client.get (uri) .getEntity (). write (System.out); }}

S SimpleServer Spuštění tohoto nového klientského kódu se stejnými závislostmi JAR, které stále běží, by mělo vytisknout přátelský pozdrav do konzoly. Tisk výstupu v tomto stylu by samozřejmě nefungoval pro binárně orientované typy MIME, ale opět je to vhodný výchozí bod.

Příklad bez CRUD

Většina pedagogických příkladů REST zobrazuje služby CRUDish (vytváření, načítání, aktualizace, mazání) kolem jednoduchých objektů. Ačkoli tento styl určitě funguje dobře s REST, není to v žádném případě jediný přístup, který dává smysl - a většina z nás je unavená z příkladů CRUD. Následující příklad ukazuje základy aplikace Restlet zabalením kontroly pravopisu Jazzy open source.

REST je o správě informací, nikoli o vyvolání svévolného chování, takže při zvažování API zaměřeného na chování, jako je Jazzy, musíte být opatrní. Trik spočívá v zacházení s RESTful API jako s informačním prostorem pro slova, která existují a neexistují v používaných slovnících. Problém lze vyřešit různými způsoby, ale tento článek bude definovat dva informační prostory. /slovník se používá ke správě slov ve slovníku. / kontrola pravopisu se používá k hledání návrhů na slova podobná chybně napsaným slovům. Oba se zaměřují na informace zvážením absence nebo přítomnosti slov v informačních prostorech.

V architektuře RESTful by tento příkaz HTTP mohl vrátit definici slova ve slovníku:

ZÍSKAT // localhost: 8182 / dictionary /slovo

Pravděpodobně by vrátil kód odpovědi HTTP „Not Found“ pro slova, která nejsou ve slovníku. V tomto informačním prostoru je dobré označit, že slova neexistují. Jazzy neposkytuje definice slov, takže ponechám vrácení nějakého obsahu jako cvičení pro čtenáře.

Tento další příkaz HTTP by měl přidat slovo do slovníku:

PUT // localhost: 8182 / dictionary /slovo

Tento příklad používá DÁT protože můžete zjistit, co je URI v /slovník informační prostor by měl být předem a vydávat více DÁTs by neměly dělat rozdíl. (DÁT je idempotentní požadavek, jako DOSTAT. Vydání stejného příkazu vícekrát by nemělo znamenat rozdíl.) Pokud chcete přidat definice, můžete je předat jako těla do DÁT psovod. Pokud chcete v průběhu času přijmout více definic, možná budete chtít POŠTA ty definice v, protože DÁT je operace přepsání.

Nepřehlédněte synchronizaci

V zájmu zachování soustředění příkladů tento článek nevěnuje zvláštní pozornost synchronizačním problémům. Nezacházejte s výrobním kódem tak nonšalantně! Obraťte se na zdroj, jako je Souběžnost Java v praxi Pro více informací.

The Restlet instance, které vytvořím, musí být svázány s příslušnými informačními prostory, jak je uvedeno v seznamu 3.

Výpis 3. Jednoduchá RESTful kontrola pravopisu

balíček net.bosatsu.restlet.spell; import com.swabunga.spell.event.SpellChecker; import com.swabunga.spell.engine.GenericSpellDictionary; import com.swabunga.spell.engine.SpellDictionary; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import org.restlet.data.Protocol; import org.restlet. *; veřejná třída SpellCheckingServer rozšiřuje aplikaci {public static String dictionary = "Restlet / dict / english.0"; public static SpellDictionary spellingDict; veřejný statický SpellChecker spellChecker; public static Restlet spellCheckerRestlet; public static Restlet dictionaryRestlet; static {try {spellingDict = new GenericSpellDictionary (nový soubor (slovník)); spellChecker = nový SpellChecker (spellingDict); spellCheckerRestlet = nový SpellCheckerRestlet (spellChecker); dictionaryRestlet = nový DictionaryRestlet (spellChecker); } catch (Výjimka e) {e.printStackTrace (); }} public static void main (String [] args) vyvolá výjimku {Component component = new Component (); component.getServers (). add (Protocol.HTTP, 8182); SpellCheckingServer spellingService = nový SpellCheckingServer (); component.getDefaultHost (). attach ("", spellingService); component.start (); } public Restlet createRoot () {Router router = new Router (getContext ()); router.attach ("/ spellchecker / {word}", spellCheckerRestlet); router.attach ("/ dictionary / {word}", dictionaryRestlet); zpětný směrovač; }}

Poté, co vytvoří instanci slovníku a kontrolu pravopisu, je nastavení Restletu ve výpisu 3 o něco složitější než v dřívějším základním příkladu (ale ne moc!). The SpellCheckingServer je instance Restletu aplikace. An aplikace je organizační třída, která koordinuje nasazení funkčně propojených Restlet instance. Okolí Součástka ptá se aplikace pro jeho kořen Restlet voláním createRoot () metoda. Kořen Restlet vrácené označuje, kdo by měl reagovat na externí požadavky. V tomto příkladu volala třída Router slouží k odeslání do podřízených informačních prostorů. Kromě provedení této kontextové vazby nastavuje vzor adresy URL, který umožňuje, aby byla část „slova“ adresy URL k dispozici jako atribut na vyžádání. To bude využito v Restletjsou vytvořeny v seznamech 4 a 5.

The DictionaryRestlet, uvedený v seznamu 4, odpovídá za vyřizování požadavků na manipulaci s /slovník informační prostor.

$config[zx-auto] not found$config[zx-overlay] not found