Útmutató a JavaLite programhoz - RESTful CRUD alkalmazás felépítése

1. Bemutatkozás

A JavaLite a közös feladatok egyszerűsítésére szolgáló keretrendszerek gyűjteménye amellyel minden fejlesztőnek meg kell küzdenie az alkalmazások készítésekor.

Ebben az oktatóanyagban áttekintjük a JavaLite szolgáltatásait, amelyek egy egyszerű API felépítésére összpontosítanak.

2. Beállítás

A bemutató során létrehozunk egy egyszerű RESTful CRUD alkalmazást. Ennek érdekében az ActiveWebet és az ActiveJDBC-t fogjuk használni - a JavaLite által integrált keretek közül kettő.

Tehát kezdjük és adjuk hozzá az első szükséges függőséget:

 org.javalite activeweb 1.15 

Az ActiveWeb-artefaktum tartalmazza az ActiveJDBC-t, ezért nem szükséges külön hozzáadni. Felhívjuk figyelmét, hogy a legújabb activeweb verzió a Maven Central oldalon található.

A második függőség, amire szükségünk van egy adatbázis-csatlakozó. Ebben a példában a MySQL-t fogjuk használni, ezért hozzá kell adnunk:

 mysql mysql-connector-java 5.1.45 

Ismét a legújabb mysql-connector-java függőség megtalálható a Maven Centralon.

Az utolsó függőség, amelyet hozzá kell adnunk, a JavaLite-re jellemző:

 org.javalite activejdbc-instrumentation 1.4.13 process-class eszköz 

A legújabb activejdbc-instrumentation plugin szintén megtalálható a Maven Central-ban.

Ha mindez a helyén van, és mielőtt az entitásokkal, táblázatokkal és leképezésekkel kezdünk, meg fogunk győződni arról az egyik támogatott adatbázis működik és működik. Mint korábban mondtuk, a MySQL-t fogjuk használni.

Most készen állunk az objektum-reláció leképezésre.

3. Objektum-relációs leképezés

3.1. Térképezés és műszerezés

Kezdjük azzal létrehozása a Termék osztály lesz a fő entitásunk:

nyilvános osztályú termék {}

És, nézzük is hozza létre a hozzá tartozó táblázatot:

TÁBLÁZATI TERMÉKEK LÉTREHOZÁSA (id int (11) DEFAULT NULL auto_increment PRIMARY KEY, név VARCHAR (128));

Végül megtehetjük módosítsa a mi Termék osztály elvégzi a feltérképezést:

public class Termék kiterjeszti a modellt {}

Csak hosszabbítanunk kell org.javalite.activejdbc.Modell osztály. Az ActiveJDBC kikéri a DB séma paramétereit az adatbázisból. Ennek a képességnek köszönhetően nincs szükség getterek és beállítók vagy bármilyen megjegyzés hozzáadására.

Ezenkívül az ActiveJDBC automatikusan felismeri ezt Termék osztályt fel kell térképezni TERMÉKEK asztal. Angol nyelvű ragozással konvertálja a modell egyes alakját egy többes számú táblává. És igen, kivételek mellett is működik.

Van egy utolsó dolog, amire a térképészeti munkához szükségünk lesz: a műszerezés. A műszerezés az ActiveJDBC által igényelt extra lépés ez lehetővé teszi számunkra, hogy játsszunk a mi Termék osztály mintha getterekkel, beállítókkal és DAO-szerű módszerekkel rendelkezne.

A műszerek futtatása után az alábbiakra leszünk képesek:

P termék = új termék (); p.set ("név", "Kenyér"); p.saveIt ();

vagy:

Terméklista = Product.findAll ();

Ez az, ahol activejdbc-műszerezés bejön a beépülő modul. Mivel már van függőségünk a pomunkban, látnunk kell, hogy az osztályokat műszerezzük a build során:

... [INFO] --- activejdbc-instrumentation: 1.4.11: instrument (alapértelmezett) @ javalite --- ************************* **** INDÍTÁS INDÍTÁSA ***************************** Directory: ... \ tutorials \ java-lite \ target \ class Instrumented osztály: ... / oktatóanyagok / java-lite / target / osztályok / app / modellek / Product.class **************************** * VÉGREHASZNÁLAT ***************************** ...

Ezután létrehozunk egy egyszerű tesztet, hogy megbizonyosodjunk arról, hogy ez működik-e.

3.2. Tesztelés

Végül a leképezés teszteléséhez három egyszerű lépést fogunk követni: nyissunk kapcsolatot az adatbázissal, mentsünk el egy új terméket és szerezzük be:

@Test public void givenSavedProduct_WhenFindFirst_ThenSavedProductIsReturned () {Base.open ("com.mysql.jdbc.Driver", "jdbc: mysql: // localhost / dbname", "felhasználó", "jelszó"); Termék toSaveProduct = új termék (); toSaveProduct.set ("név", "Kenyér"); toSaveProduct.saveIt (); Product savedProduct = Product.findFirst ("név =?", "Kenyér"); assertEquals (toSaveProduct.get ("név"), savedProduct.get ("név")); }

Ne feledje, hogy mindez (és még sok más) csak üres modell és műszer birtokában lehetséges.

4. Vezérlők

Most, hogy elkészült a térképezésünk, elkezdhetünk gondolkodni alkalmazásunkon és annak CRUD módszerein.

Ehhez a HTTP kéréseket feldolgozó vezérlőket fogjuk használni.

Hozzuk létre a sajátunkat ProductsController:

@RESTful public class ProductsController kiterjeszti az AppController {public void index () {// ...}}

Ezzel a megvalósítással az ActiveWeb automatikusan feltérképezi index() módszer a következő URI-hoz:

//:/Termékek

A vezérlők megjegyezték a következővel: @Nyugalmas, fix metóduskészletet biztosítanak, amelyek automatikusan különböző URI-khoz vannak hozzárendelve. Lássuk azokat, amelyek hasznosak lehetnek a CRUD példánkban:

Vezérlő módszerHTTP módszerURI
TEREMTteremt()POST// host: port / termékek
OLVASSA EL EGYETelőadás()KAP// host: port / products / {id}
MINDENET OLVASSA ELindex()KAP// host: port / termékek
FRISSÍTÉSfrissítés ()PUT// host: port / products / {id}
TÖRÖLelpusztítani()TÖRÖL// host: port / products / {id}

És ha hozzáadjuk ezt a módszerkészletet a sajátunkhoz ProductsController:

@RESTful public class ProductsController kiterjeszti az AppController {public void index () {// kódot, hogy az összes termék} public void create () {// kód új termék létrehozásához} public void update () {// kód egy meglévő frissítéséhez termék} public void show () {// kód egy termék megtalálásához} public void megsemmisítés () {// kód egy meglévő termék eltávolításához}}

Mielőtt továbblépnénk a logikai megvalósításunkra, gyorsan áttekintünk néhány dolgot, amelyet konfigurálnunk kell.

5. Konfiguráció

Az ActiveWeb többnyire konvenciókra épül, a projekt felépítése erre példa. Az ActiveWeb projekteknek előre meghatározott csomagelrendezést kell követniük:

src | ---- main | ---- java.app | | ---- config | | ---- vezérlők | | ---- modellek | ---- források | ---- webalkalmazás | ---- WEB-INF | ---- nézetek

Van egy speciális csomag, amelyet meg kell vizsgálnunk - app.config.

A csomag belsejében három osztályt fogunk létrehozni:

a public class DbConfig kiterjeszti az AbstractDBConfig {@Override public void init (AppContext appContext) {this.configFile ("/ database.properties"); }}

Ez az osztály konfigurálja az adatbázis-kapcsolatokat egy tulajdonságfájl segítségével a projekt gyökérkönyvtárában, amely tartalmazza a szükséges paramétereket:

development.driver = com.mysql.jdbc.Driver development.username = felhasználói fejlesztés.jelszó = jelszó fejlesztés.url = jdbc: mysql: // localhost / dbname

Ez létrehozza a kapcsolatot, amely automatikusan felváltja a térképezési teszt első sorában tetteket.

A második osztály, amelyet be kell vonnunk app.config csomag:

public class AppControllerConfig kiterjeszti az AbstractControllerConfig {@Override public void init (AppContext appContext) {add (new DBConnectionFilter ()). to (ProductsController.class); }}

Ez a kódösszekapcsolja a vezérlőnkkel az imént konfigurált kapcsolatot.

A harmadik osztály akaratkonfigurálja az alkalmazás kontextusát:

public class AppBootstrap kiterjeszti a Bootstrap {public void init (AppContext context) {}}

A három osztály létrehozása után az utolsó dolog a konfigurációval kapcsolatban megalkotva a mi web.xml fájl alatt webapp / WEB-INF Könyvtár:

   diszpécser org.javalite.activeweb.RequestDispatcher kizárja a css, képeket, js, ico kódoló UTF-8 diszpécsert / * 

Most, hogy a konfiguráció elkészült, folytathatjuk és hozzáadhatjuk a logikánkat.

6. A CRUD Logic megvalósítása

A mi általunk biztosított DAO-szerű képességekkel Termék osztály, nagyon egyszerű adja hozzá az alapvető CRUD funkciókat:

@RESTful public class ProductsController kiterjeszti az AppController {private ObjectMapper mapper = new ObjectMapper (); public void index () {Termékek felsorolása = Product.findAll (); // ...} public void create () {Map payload = mapper.readValue (getRequestString (), Map.class); P termék = új termék (); p.fromMap (hasznos teher); p.saveIt (); // ...} public void update () {Map payload = mapper.readValue (getRequestString (), Map.class); Karakterlánc id = getId (); P termék = Product.findById (id); p.fromMap (hasznos teher); p.saveIt (); // ...} public void show () {String id = getId (); P termék = Product.findById (id); // ...} public void megsemmisít () {String id = getId (); P termék = Product.findById (id); p.delete (); // ...}}

Könnyű, igaz? Ez azonban még nem hoz semmit. Ehhez létre kell hoznunk néhány nézetet.

7. Nézetek

Az ActiveWeb a FreeMarkert használja sablonmotorként, és az összes sablonjának a alatt kell lennie src / main / webapp / WEB-INF / nézetek.

A könyvtárban a nézeteinket egy mappába helyezzük Termékek (ugyanaz, mint a kontrollerünk). Hozzuk létre az első sablont _product.ftl:

{"id": $ {product.id}, "name": "$ {product.name}"}}

Ezen a ponton elég világos, hogy ez egy JSON válasz. Természetesen ez csak egy terméknél fog működni, ezért folytassuk és hozzunk létre egy másik sablont, az úgynevezett index.ftl:

[]

Ez alapvetően egy elnevezett gyűjteményt jelenít meg Termékek, mindegyiket formázta _product.ftl.

Végül, az eredményt a vezérlőnkből kell a megfelelő nézethez kötnünk:

@RESTful public class ProductsController kiterjeszti az AppController {public void index () {Termékek felsorolása = Product.findAll (); nézet ("termékek", termékek); Vakol(); } public void show () {String id = getId (); P termék = Product.findById (id); nézet ("termék", p); render ("_ termék"); }}

Az első esetben kijelöljük Termékek listát a szintén megnevezett sablongyűjteményünkbe Termékek.

Aztán, mivel nem adunk meg nézetet, index.ftl használva lesz.

A második módszerben a terméket rendeljük hozzá o elemre termék a nézetben, és kifejezetten megmondjuk, melyik nézetet kell megjeleníteni.

Nézetet is létrehozhatnánk message.ftl:

{"message": "$ {message}", "code": $ {code}}

És akkor nevezzük bármelyikünkből ProductsControllerMódszere:

nézet ("üzenet", "Hiba történt.", "kód", 200); render ("üzenet");

Lássuk most a döntőnket ProductsController:

@RESTful public class ProductsController kiterjeszti az AppController {private ObjectMapper mapper = new ObjectMapper (); public void index () {view ("termékek", Product.findAll ()); render (). contentType ("alkalmazás / json"); } public void create () {Map payload = mapper.readValue (getRequestString (), Map.class); P termék = új termék (); p.fromMap (hasznos teher); p.saveIt (); nézet ("üzenet", "Sikeresen mentett termékazonosító" + p.get ("id"), "kód", 200); render ("üzenet"); } public void update () {Map payload = mapper.readValue (getRequestString (), Map.class); Karakterlánc id = getId (); P termék = Product.findById (id); if (p == null) {view ("message", "Product id" + id + "not found.", "code", 200); render ("üzenet"); Visszatérés; } p.fromMap (hasznos teher); p.saveIt (); nézet ("üzenet", "Sikeresen frissített termékazonosító" + azonosító, "kód", 200); render ("üzenet"); } public void show () {String id = getId (); P termék = Product.findById (id); if (p == null) {view ("message", "Product id" + id + "not found.", "code", 200); render ("üzenet"); Visszatérés; } nézet ("termék", p); render ("_ termék"); } public void megsemmisítés () {String id = getId (); P termék = Product.findById (id); if (p == null) {view ("message", "Product id" + id + "not found.", "code", 200); render ("üzenet"); Visszatérés; } p.delete (); nézet ("üzenet", "Termék azonosítójának sikeres törlése" + azonosító, "kód", 200); render ("üzenet"); } @Orride védett karakterlánc getContentType () {return "application / json"; } @Orride védett karakterlánc getLayout () {return null; }}

Ezen a ponton elkészült az alkalmazásunk, és készen állunk a futtatásra.

8. Az alkalmazás futtatása

A Jetty plugint fogjuk használni:

 org.eclipse.jetty móló-maven-plugin 9.4.8.v20171121 

Keresse meg a legújabb móló-maven-plugint a Maven Central-ban.

És készen állunk, futtathatjuk az alkalmazásunkat:

mvn móló: futás

Hozzunk létre néhány terméket:

$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Water"}' {"message": "Sikeresen elmentett 1. termékazonosító", " kód ": 200}
$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Kenyér"} "{" message ":" Sikeresen elmentett 2. termékazonosító "," kód ": 200}

.. olvasd el őket:

$ curl -X GET // localhost: 8080 / termékek [{"id": 1, "név": "Víz"}, {"id": 2, "név": "Kenyér"}]

.. frissítse az egyiket:

$ curl -X PUT // localhost: 8080 / products / 1 -H 'content-type: application / json' -d '{"name": "Juice"}' {"message": "1-es termékazonosító sikeresen frissítve" , "kód": 200}

... olvassa el az imént frissítettet:

$ curl -X GET // localhost: 8080 / products / 1 {"id": 1, "name": "Juice"}

Végül törölhetünk egyet:

$ curl -X DELETE // localhost: 8080 / products / 2 {"message": "2. termékazonosító sikeresen törölve", "code": 200}

9. Következtetés

A JavaLite rengeteg eszközzel segíti a fejlesztőket percek alatt elkészül egy alkalmazás. Noha a konvenciókra alapozva a dolgok tisztább és egyszerűbb kódot eredményeznek, az osztályok, csomagok és fájlok elnevezésének és helyének megértéséhez idő kell.

Ez csak az ActiveWeb és az ActiveJDBC bevezetése volt, további dokumentációt találhat a weboldalán, és keresse termékeinket a Github projektben.