Programování

Navrhněte jednoduchý aplikační rámec J2EE orientovaný na služby

Dnes jsou vývojáři zaplaveni otevřenými zdrojovými rámci, které pomáhají s programováním J2EE: Struts, Spring, Hibernate, Tiles, Avalon, WebWorks, Tapestry nebo Oracle ADF. Mnoho vývojářů zjistilo, že tyto rámce nejsou všelékem na jejich problémy. To, že jsou open source, ještě neznamená, že se snadno mění a vylepšují. Když rámec selže v klíčové oblasti, oslovuje pouze konkrétní doménu nebo je jen nafouklý a příliš drahý, možná budete muset na jeho vrcholu vytvořit vlastní rámec. Vytváření rámce jako Struts je netriviální úkol. Ale postupný vývoj rámce, který využívá Struts a další rámce, nemusí být.

V tomto článku vám ukážu, jak se rozvíjet X18p (Xiangnong 18 Palm, pojmenovaný pro legendárního mocného bojovníka kung-fu), ukázkový rámec, který řeší dva běžné problémy ignorované většinou rámců J2EE: těsné propojení a nafouklý kód DAO (objekt přístupu k datům). Jak uvidíte později, X18p využívá Struts, Spring, Axis, Hibernate a další rámce v různých vrstvách. Doufejme, že s podobnými kroky můžete snadno zavést svůj vlastní rámec a rozšířit ho z projektu na projekt.

Přístup, který používám při vývoji tohoto rámce, využívá koncepty z IBM Rational Unified Process (RUP). Postupuji podle těchto kroků:

  1. Nejprve si stanovte jednoduché cíle
  2. Analyzujte stávající architekturu aplikace J2EE a identifikujte problémy
  3. Porovnejte alternativní rámce a vyberte ten, který je nejjednodušší sestavit
  4. Vyvíjejte kód postupně a často refaktorujte
  5. Setkejte se s koncovým uživatelem rámce a pravidelně shromažďujte zpětnou vazbu
  6. Test, test, test

Krok 1. Stanovte si jednoduché cíle

Je lákavé stanovit ambiciózní cíle a zavést špičkový rámec, který řeší všechny problémy. Pokud máte dostatek zdrojů, není to špatný nápad. Obecně se vývoj rámce předem pro váš projekt považuje za režii, která neposkytuje hmatatelnou obchodní hodnotu. Začátek menší vám pomůže snížit nepředvídaná rizika, užít si méně času na vývoj, snížit křivku učení a získat buy-in účastníků projektu. U X18p jsem stanovil pouze dva cíle na základě mých minulých setkání s kódem J2EE:

  1. Snižte J2EE Akce kódová vazba
  2. Snižte opakování kódu ve vrstvě J2EE DAO

Celkově chci poskytnout kvalitnější kód a snížit celkové náklady na vývoj a údržbu zvýšením své produktivity. S tím projdeme dvě iterace kroků 2 až 6, abychom tyto cíle splnili.

Snižte vazbu kódu

Krok 2. Analyzujte předchozí architekturu aplikace J2EE

Pokud je implementován aplikační rámec J2EE, musíme nejprve vidět, jak jej lze vylepšit. Je zřejmé, že začínat od nuly nemá smysl. Pro X18p se podívejme na typický příklad aplikace J2EE Struts, který je znázorněn na obrázku 1.

Akce hovory XXXManager, a XXXManager hovory XXXDAOs. V typickém designu J2EE, který zahrnuje Struts, máme následující položky:

  • HttpServlet nebo vzpěry Akce vrstva, která zpracovává HttpRequest a HttpResponse
  • Vrstva obchodní logiky
  • Vrstva přístupu k datům
  • Vrstva domény, která se mapuje na entity domény

Co se děje s výše uvedenou architekturou? Odpověď: těsné spojení. Architektura funguje dobře, pokud je logika v Akce je jednoduchý. Ale co když potřebujete získat přístup k mnoha komponentům EJB (Enterprise JavaBeans)? Co když potřebujete přístup k webovým službám z různých zdrojů? Co když potřebujete přístup k JMX (Java Management Extensions)? Má Struts nástroj, který vám pomůže vyhledat tyto zdroje z struts-config.xml soubor? Odpověď je ne. Struts je zamýšlen jako rámec pouze pro web. Je možné kódovat Akces jako různí klienti a volat back-end pomocí vzoru vyhledávače služeb. Tím však smícháte dva různé typy kódu Akceje vykonat() metoda.

První typ kódu se týká webové úrovně HttpRequest/HttpResponse. Například kód načte data formuláře HTTP z ActionForm nebo HttpRequest. Máte také kód, který nastavuje data v požadavku HTTP nebo relaci HTTP a předává je na stránku JSP (JavaServer Pages), která se má zobrazit.

Druhý typ kódu se však týká obchodní úrovně. v Akce, vyvoláte také backendový kód, jako je EJBObject, téma JMS (Java Message Service), nebo dokonce zdroje dat JDBC (Java Database Connectivity) a načíst výsledná data ze zdrojů dat JDBC. Můžete použít vzor vyhledávače služeb v Akce abychom vám pomohli s vyhledáváním. Je to také možné pro Akce odkazovat pouze na místní POJO (obyčejný starý objekt Java) xxxManager. Backendový objekt nebo xxxManagerPodpisy na úrovni metody jsou vystaveny Akce.

Takhle Akce funguje, že? Povaha Akce je servlet, který se má starat o to, jak převzít data z HTML a nastavit data do HTML s požadavkem / relací HTTP. Rozhraní také slouží k vrstvě obchodní logiky, aby získala nebo aktualizovala data z této vrstvy, ale v jaké formě nebo protokolu, Akce mohl by se starat méně.

Jak si dokážete představit, když aplikace Struts roste, můžete skončit s úzkými odkazy mezi nimi Akces (webová vrstva) a obchodní manažeři (obchodní vrstva) (viz červené čáry a šipky na obrázku 1).

K vyřešení tohoto problému můžeme vzít v úvahu otevřené rámce na trhu - nechme je inspirovat naše vlastní myšlení, než provedeme nějaký dopad. Jarní rámec se objeví na mé radarové obrazovce.

Krok 3. Porovnejte alternativní rámce

Jádrem jarního rámce je koncept zvaný BeanFactory, což je dobrá implementace vyhledávací továrny. Liší se od vzoru vyhledávače služeb v tom, že má funkci Inversion-of-Control (IoC) dříve nazvanou Závislost na injekci. Cílem je získat objekt voláním vašeho ApplicationContextje getBean () metoda. Tato metoda vyhledá jarní konfigurační soubor pro definice objektů, vytvoří objekt a vrátí a java.lang.Object objekt. getBean () je dobré pro vyhledávání objektů. Zdá se, že pouze jeden odkaz na objekt, ApplicationContext, musí být uveden v Akce. To však není případ, pokud jej použijeme přímo v Akce, protože musíme seslat getBean ()návratový typ objektu zpět do klienta EJB / JMX / JMS / webové služby. Akce stále musí být vědomi backendového objektu na úrovni metody. Těsné spojení stále existuje.

Pokud se chceme vyhnout odkazu na úrovni metody objektu, co jiného můžeme použít? Přirozeně, servis, přijde na mysl. Služba je všudypřítomný, ale neutrální koncept. Službou může být cokoli, nemusí to být nutně jen takzvané webové služby. Akce může metodu fazole relace bez státní příslušnosti považovat také za službu. Může zacházet s voláním tématu JMS také jako konzumace služby. Způsob, jakým navrhujeme využívání služby, může být velmi obecný.

Díky formulované strategii, odhalení nebezpečí a zmírnění rizika z výše uvedené analýzy a srovnání můžeme urychlit naši kreativitu a přidat tenkou vrstvu zprostředkovatele služeb, abychom demonstrovali koncept orientovaný na služby.

Krok 4. Vývoj a refaktorování

K implementaci konceptu myšlení orientovaného na služby do kódu musíme vzít v úvahu následující:

  • Vrstva zprostředkovatele služeb bude přidána mezi webovou vrstvu a obchodní vrstvu.
  • Koncepčně Akce volá pouze požadavek na obchodní službu, který požadavek předá směrovači služby. Směrovač služby ví, jak spojit požadavky na obchodní služby s různými řadiči nebo adaptéry poskytovatelů služeb vyhledáním souboru XML mapujícího službu, X18p-config.xml.
  • Správce poskytovatele služeb má specifické znalosti o hledání a vyvolání základních obchodních služeb. Zde by obchodní služby mohly být cokoli od POJO, LDAP (lehký přístupový protokol k adresáři), EJB, JMX, COM a webové služby až po API produktu COTS (komerčně dostupné). X18p-config.xml by měl poskytnout dostatek dat, aby pomohl řadiči poskytovatele služeb dokončit práci.
  • Využijte Spring pro interní vyhledávání objektů X18p a odkazy.
  • Postupně vytvářejte řadiče poskytovatelů služeb. Jak uvidíte, čím více implementovaných řadičů poskytovatelů služeb, tím větší integrační výkon má X18p.
  • Chraňte stávající znalosti, jako je Struts, ale mějte oči otevřené pro nové věci.

Nyní porovnáme Akce kód před a po použití rámce X18p orientovaného na služby:

Struts Action bez X18p

 veřejné spuštění ActionForward (mapování ActionMapping, formulář ActionForm, požadavek HttpServletRequest, odpověď HttpServletResponse) vyvolá IOException, ServletException {... UserManager userManager = new UserManager (); Řetězec userIDRetured = userManager.addUser ("John Smith") ...} 

Akce Struts s X18p

veřejné spuštění ActionForward (mapování ActionMapping, formulář ActionForm, požadavek HttpServletRequest, odpověď HttpServletResponse) vyvolá IOException, ServletException {... ServiceRequest bsr = this.getApplicationContext (). getBean ("businessServiceRequest"); bsr.setServiceName ("Služby uživatelů"); bsr.setOperation ("addUser"); bsr.addRequestInput ("param1", "addUser"); Řetězec userIDRetured = (Řetězec) bsr.service (); ...} 

Jaro podporuje vyhledávání požadavků na obchodní služby a dalších objektů, včetně správců POJO, pokud existují.

Obrázek 2 ukazuje, jak konfigurační soubor Spring, applicationContext.xml, podporuje vyhledávání businessServiceRequest a serviceRouter.

v ServiceRequest.javaservis() metoda jednoduše zavolá Spring, aby našla servisní router a předá se routeru:

 public Object service () {return ((ServiceRouter) this.serviceContext.getBean ("service router")). route (this); } 

Směrovač služeb v X18p směruje uživatelské služby do vrstvy obchodní logiky pomocí X18p-config.xmlpomoc. Klíčovým bodem je, že Akce kód nemusí vědět, kde a jak jsou implementovány uživatelské služby. Je potřeba pouze znát pravidla pro konzumaci služby, jako je posílání parametrů ve správném pořadí a sesílání správného typu návratu.

Obrázek 3 ukazuje segment X18p-config.xml který poskytuje informace o mapování služby, které ServiceRouter vyhledá v X18p.

U uživatelských služeb je typ služby POJO. ServiceRouter vytvoří ovladač poskytovatele služeb POJO ke zpracování požadavku na službu. Toto POJO springObjectId je userServiceManager. Řadič poskytovatele služeb POJO používá Spring k vyhledání tohoto POJO springObjectId. Od té doby userServiceManager ukazuje na typ třídy X18p.framework.UserPOJOManagerUserPOJOManager class je logický kód pro konkrétní aplikaci.

Prozkoumat ServiceRouter.java:

 trasa veřejného objektu (ServiceRequest serviceRequest) vyvolá výjimku {// / 1. Přečtěte si všechna mapování ze souboru XML nebo je načtěte z Factory // Config config = xxxx; // 2. Získejte typ služby z konfigurace. Řetězec businessServiceType = Config.getBusinessServiceType (serviceRequest.getServiceName ()); // 3. Vyberte příslušný směrovač / manipulátor / řadič, který s ním bude pracovat. if (businessServiceType.equalsIgnoreCase ("LOCAL-POJO")) {POJOController pojoController = (POJOController) Config.getBean ("POJOController"); pojoController.process (serviceRequest); } else if (businessServiceType.equalsIgnoreCase ("WebServices")) {String endpoint = Config.getWebServiceEndpoint (serviceRequest.getServiceName ()); WebServicesController ws = (WebServicesController) Config.getBean ("WebServicesController"); ws.setEndpointUrl (koncový bod); ws.process (serviceRequest); } else if (businessServiceType.equalsIgnoreCase ("EJB")) {EJBController ejbController = (EJBController) Config.getBean ("EJBController"); ejbController.process (serviceRequest); } else {// TODO System.out.println ("Neznámé typy, je jen na vás, jak s nimi v rámci zacházíte"); } // To je vše, je to váš rámec, můžete přidat libovolného nového poskytovatele služeb pro svůj další projekt. vrátit null; } 

Výše uvedený směrovaný blok if-else lze refaktorovat do příkazového vzoru. The Konfigurace objekt poskytuje vyhledávání konfigurace Spring a X18p XML. Dokud lze načíst platná data, je jen na vás, jak implementovat vyhledávací mechanismus.

Za předpokladu správce POJO, TestPOJOBusinessManager, je implementován řadič poskytovatele služeb POJO (POJOServiceController.java) pak hledá přidat uživatele() metoda z TestPOJOBusinessManager a vyvolá to s odrazem (viz kód k dispozici od zdrojů).

Zavedením tří tříd (BusinessServiceRequester, ServiceRouter, a ServiceProviderController) plus jeden konfigurační soubor XML, máme rámec orientovaný na služby jako proof-of-concept. Tady Akce nemá žádné znalosti o tom, jak je služba implementována. Zajímá se pouze o vstup a výstup.

Složitost používání různých API a programovacích modelů k integraci různých poskytovatelů služeb je chráněna před vývojáři Struts pracujícími na webové vrstvě. Li X18p-config.xml je navržen předem jako servisní smlouva, vývojáři Struts a backend mohou pracovat současně na základě smlouvy.

Obrázek 4 ukazuje nový vzhled architektury.

Shrnul jsem běžné řadiče poskytovatelů služeb a implementační strategie v tabulce 1. Můžete snadno přidat další.

Tabulka 1. Implementační strategie pro běžné správce poskytovatelů služeb