Ú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ódszer | HTTP módszer | URI | |
---|---|---|---|
TEREMT | teremt() | POST | // host: port / termékek |
OLVASSA EL EGYET | előadás() | KAP | // host: port / products / {id} |
MINDENET OLVASSA EL | index() | KAP | // host: port / termékek |
FRISSÍTÉS | frissítés () | PUT | // host: port / products / {id} |
TÖRÖL | elpusztí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.