Vodič za JavaLite - Izrada RESTful CRUD aplikacije

1. Uvod

JavaLite je zbirka okvira za pojednostavljivanje uobičajenih zadataka s kojim se svaki programer mora suočiti prilikom izrade aplikacija.

U ovom uputstvu ćemo pogledati značajke JavaLite usredotočene na izgradnju jednostavnog API-ja.

2. Postavljanje

Tijekom ovog vodiča stvorit ćemo jednostavnu RESTful CRUD aplikaciju. Da bi to učinili, koristit ćemo ActiveWeb i ActiveJDBC - dva okvira s kojima se JavaLite integrira.

Pa, krenimo i dodajte prvu ovisnost koja nam treba:

 org.javalite activeweb 1.15 

Artefakt ActiveWeb uključuje ActiveJDBC, pa ga nema potrebe dodavati zasebno. Imajte na umu da se najnovija aktivna web verzija može naći u Maven Central.

Druga ovisnost koja nam treba je konektor baze podataka. U ovom ćemo primjeru koristiti MySQL pa moramo dodati:

 mysql mysql-konektor-java 5.1.45 

Opet, najnoviju ovisnost o mysql-connector-java možete pronaći na Maven Central.

Posljednja ovisnost koju moramo dodati nešto je specifično za JavaLite:

 org.javalite activejdbc-instrumentacija 1.4.13 instrument klase procesa 

Najnoviji dodatak activejdbc-instrumentation također se može naći u Maven Central.

Imajući sve ovo na mjestu i prije početka s entitetima, tablicama i preslikavanjima, pobrinut ćemo se za to jedna od podržanih baza podataka radi i radi. Kao što smo već rekli, koristit ćemo MySQL.

Sada smo spremni započeti s objektno-relacijskim mapiranjem.

3. Objektno-relacijsko mapiranje

3.1. Kartiranje i instrumentacija

Krenimo od stvaranje a Proizvod klasa koja će biti naš glavni entitet:

proizvod javne klase {}

I, hajde također izradite odgovarajuću tablicu za to:

IZRADI TABLIČNE PROIZVODE (id int (11) ZADATAK NULL auto_increment PRIMARNI KLJUČ, naziv VARCHAR (128));

Napokon, možemo izmijeniti naš Proizvod razred za izradu preslikavanja:

proizvod javne klase proširuje model {}

Trebamo samo produžiti org.javalite.activejdbc.Model razred. ActiveJDBC iz baze podataka izvodi parametre DB sheme. Zahvaljujući ovoj mogućnosti, nema potrebe za dodavanjem getera i postavljača ili bilo koje bilješke.

Nadalje, ActiveJDBC to automatski prepoznaje Proizvod razred treba preslikati PROIZVODI stol. Koristi engleske fleksije za pretvaranje oblika jednine u oblik množine tablice. I da, radi i s iznimkama.

Postoji još jedna stvar koja će nam trebati da bi naše mapiranje funkcioniralo: instrumentacija. Instrumentacija je dodatni korak koji zahtijeva ActiveJDBC to će nam omogućiti da se igramo s našim Proizvod klase kao da ima getere, postavljače i DAO-slične metode.

Nakon pokretanja instrumentacije moći ćemo raditi sljedeće:

Proizvod p = novi proizvod (); str.set ("ime", "Kruh"); p.saveIt ();

ili:

Popis proizvoda = Product.findAll ();

Ovo je gdje aktivjdbc-instrumentacija dodatak dolazi. Kako već imamo ovisnosti u našem pomu, trebali bismo vidjeti kako se klase instrumentiraju tijekom gradnje:

... [INFO] --- activejdbc-instrumentacija: 1.4.11: instrument (zadano) @ javalite --- ************************ **** POČNITE INSTRUMENTACIJU ****************************** Imenik: ... \ tutorials \ java-lite \ target \ classes Instrumented class: ... / tutorials / java-lite / target / classes / app / models / Product.class *************************** * ZAVRŠI INSTRUMENTACIJU **************************** ...

Zatim ćemo stvoriti jednostavan test kako bismo bili sigurni da ovo djeluje.

3.2. Testiranje

Na kraju, da bismo testirali naše mapiranje, slijedit ćemo tri jednostavna koraka: otvoriti vezu s bazom podataka, spremiti novi proizvod i preuzeti ga:

@Test javna praznina givenSavedProduct_WhenFindFirst_ThenSavedProductIsReturned () {Base.open ("com.mysql.jdbc.Driver", "jdbc: mysql: // localhost / dbname", "user", "password"); Product toSaveProduct = novi proizvod (); toSaveProduct.set ("ime", "Kruh"); toSaveProduct.saveIt (); Proizvod je sačuvanProduct = Product.findFirst ("name =?", "Kruh"); assertEquals (toSaveProduct.get ("name"), savedProduct.get ("name")); }

Imajte na umu da je sve ovo (i više) moguće samo ako imate prazan model i instrumente.

4. Kontroleri

Sad kad je naše mapiranje spremno, možemo početi razmišljati o našoj aplikaciji i njezinim CRUD metodama.

Za to ćemo se poslužiti kontrolerima koji obrađuju HTTP zahtjeve.

Stvorimo svoje ProductsController:

@RESTful javna klasa ProductsController proširuje AppController {javni void indeks () {// ...}}

Ovom implementacijom ActiveWeb će se automatski mapirati indeks() metoda na sljedeći URI:

//: / proizvodi

Kontroleri označeni s @Miran, pružaju fiksni skup metoda koje se automatski preslikavaju na različite URI-je. Pogledajmo one koje će biti korisne za naš primjer CRUD-a:

Metoda kontroleraHTTP metodaURI
STVORITIstvoriti()OBJAVI// domaćin: luka / proizvodi
PROČITAJ JEDNUpokazati()DOBITI// host: port / products / {id}
PROČITAJTE SVEindeks()DOBITI// domaćin: luka / proizvodi
AŽURIRANJEažuriranje()STAVITI// host: port / products / {id}
IZBRISATIuništiti()IZBRISATI// host: port / products / {id}

A ako ovom skupu metoda dodamo i naš ProductsController:

@RESTful javna klasa ProductsController proširuje AppController {javni void index () {// kôd da bi se dobili svi proizvodi} public void create () {// kôd za stvaranje novog proizvoda} javno void ažuriranje () {// kôd za ažuriranje postojećeg product} javna void emisija () {// kôd za pronalaženje jednog proizvoda} javna void uništiti () {// kôd za uklanjanje postojećeg proizvoda}}

Prije nego što prijeđemo na našu logičku implementaciju, kratko ćemo pogledati nekoliko stvari koje moramo konfigurirati.

5. Konfiguracija

ActiveWeb se uglavnom temelji na konvencijama, primjer toga je struktura projekta. ActiveWeb projekti trebaju slijediti unaprijed definirani izgled paketa:

src | ---- glavni | ---- java.app | | ---- konfiguracija | | ---- kontroleri | | ---- modeli | ---- resursi | ---- webapp | ---- WEB-INF | ---- prikazi

Postoji jedan određeni paket koji moramo pogledati - astr.konfig.

Unutar tog paketa stvorit ćemo tri klase:

javna klasa DbConfig proširuje AbstractDBConfig {@Override public void init (AppContext appContext) {this.configFile ("/ database.properties"); }}

Ova klasa konfigurira veze baze podataka pomoću datoteke svojstava u korijenskom direktoriju projekta koja sadrži potrebne parametre:

development.driver = com.mysql.jdbc.Driver development.username = razvoj korisnika.password = razvoj lozinke.url = jdbc: mysql: // localhost / dbname

To će stvoriti vezu koja će automatski zamijeniti ono što smo učinili u prvom retku našeg testa preslikavanja.

Druga klasa koju moramo uključiti unutra app.config paket je:

javna klasa AppControllerConfig proširuje AbstractControllerConfig {@Override javna void init (AppContext appContext) {add (new DBConnectionFilter ()). to (ProductsController.class); }}

Ovaj kodpovezati će vezu koju smo upravo konfigurirali s našim kontrolerom.

Treći razred htjetikonfigurirajte kontekst naše aplikacije:

javna klasa AppBootstrap proširuje Bootstrap {javna void init (kontekst AppContext) {}}

Nakon stvaranja tri klase, posljednja stvar u vezi s konfiguracijom je stvarajući naše web.xml datoteka pod, ispod webapp / WEB-INF imenik:

   dispečer org.javalite.activeweb.RequestDispatcher izuzeća css, slike, js, ico kodiranje UTF-8 dispečer / * 

Sad kad je konfiguracija gotova, možemo nastaviti i dodati svoju logiku.

6. Implementacija CRUD logike

S DAO-sličnim mogućnostima koje pruža naš Proizvod razreda, to je super jednostavno dodajte osnovnu CRUD funkcionalnost:

@RESTful javna klasa ProductsController proširuje AppController {private ObjectMapper mapper = new ObjectMapper (); indeks javne praznine () {Popis proizvoda = Product.findAll (); // ...} javna praznina create () {Map payload = mapper.readValue (getRequestString (), Map.class); Proizvod p = novi proizvod (); p.fromMap (korisni teret); p.saveIt (); // ...} javno void ažuriranje () {Map payload = mapper.readValue (getRequestString (), Map.class); String id = getId (); Proizvod p = Product.findById (id); p.fromMap (korisni teret); p.saveIt (); // ...} javna void emisija () {String id = getId (); Proizvod p = Product.findById (id); // ...} javna praznina uništi () {String id = getId (); Proizvod p = Product.findById (id); p.delete (); // ...}}

Lako, zar ne? Međutim, ovo još ništa ne vraća. Da bismo to učinili, moramo stvoriti neke poglede.

7. Pogledi

ActiveWeb koristi FreeMarker kao mehanizam za izradu predložaka, a svi njegovi predlošci trebaju se nalaziti pod src / main / webapp / WEB-INF / views.

Unutar te mape smjestit ćemo svoje poglede u mapu koja se zove proizvoda (isto kao i naš kontroler). Stvorimo svoj prvi predložak pod nazivom _product.ftl:

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

U ovom je trenutku prilično jasno da je ovo JSON odgovor. Naravno, ovo će raditi samo za jedan proizvod, pa krenimo i stvorimo drugi predložak pod nazivom indeks.ftl:

[]

To će u osnovi prikazati zbirku nazvanu proizvoda, pri čemu je svaki formatiran u obliku _product.ftl.

Konačno, moramo rezultat našeg kontrolera povezati s odgovarajućim prikazom:

@RESTful javna klasa ProductsController proširuje AppController {javni void index () {Popis proizvoda = Product.findAll (); pogled ("proizvodi", proizvodi); render (); } javna void emisija () {String id = getId (); Proizvod p = Product.findById (id); pogled ("proizvod", str); render ("_ proizvod"); }}

U prvom slučaju dodjeljujemo proizvoda popis u našu kolekciju predložaka pod nazivom također proizvoda.

Tada, kako ne specificiramo nijedan pogled, indeks.ftl će se koristiti.

U drugoj metodi dodjeljujemo proizvod str elementu proizvod u prikazu i izričito kažemo koji pogled treba prikazati.

Mogli bismo stvoriti i pogled poruka.ftl:

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

A onda ga nazovite bilo kojim od naših ProductsController'S metoda:

pogled ("poruka", "Došlo je do pogreške.", "kôd", 200); render ("poruka");

Pogledajmo sada naše finale ProductsController:

@RESTful javna klasa ProductsController proširuje AppController {private ObjectMapper mapper = new ObjectMapper (); indeks javne praznine () {view ("products", Product.findAll ()); render (). contentType ("application / json"); } javna praznina create () {Map payload = mapper.readValue (getRequestString (), Map.class); Proizvod p = novi proizvod (); p.fromMap (korisni teret); p.saveIt (); pogled ("poruka", "Uspješno spremljen ID proizvoda" + p.get ("id"), "kôd", 200); render ("poruka"); } javno void ažuriranje () {Map payload = mapper.readValue (getRequestString (), Map.class); String id = getId (); Proizvod p = Product.findById (id); if (p == null) {view ("message", "id proizvoda" + id + "not found.", "code", 200); render ("poruka"); povratak; } str.fromMap (korisni teret); p.saveIt (); pogled ("poruka", "Uspješno ažuriran ID proizvoda" + ID, "kôd", 200); render ("poruka"); } javna void emisija () {String id = getId (); Proizvod p = Product.findById (id); if (p == null) {view ("message", "id proizvoda" + id + "not found.", "code", 200); render ("poruka"); povratak; } pogled ("proizvod", str); render ("_ proizvod"); } javna void uništiti () {String id = getId (); Proizvod p = Product.findById (id); if (p == null) {view ("message", "id proizvoda" + id + "not found.", "code", 200); render ("poruka"); povratak; } p.delete (); pogled ("poruka", "Uspješno izbrisani ID proizvoda" + ID, "kôd", 200); render ("poruka"); } @Override zaštićeni niz getContentType () {return "application / json"; } @Override zaštićeni niz getLayout () {return null; }}

U ovom trenutku naša je aplikacija gotova i spremni smo je pokrenuti.

8. Pokretanje aplikacije

Koristit ćemo dodatak Jetty:

 org.eclipse.jetty jetty-maven-plugin 9.4.8.v20171121 

Pronađite najnoviji dodatak za jetty-maven u Maven Central.

I mi smo spremni, možemo pokrenuti našu aplikaciju:

mvn jetty: trči

Stvorimo nekoliko proizvoda:

$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Water"}' {"message": "Uspješno spremljen ID proizvoda 1", " kod ": 200}
$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Bread"}' {"message": "Uspješno spremljen ID proizvoda 2", " kod ": 200}

.. pročitajte ih:

$ curl -X GET // localhost: 8080 / products [{"id": 1, "name": "Water"}, {"id": 2, "name": "Kruh"}]

.. ažurirajte jedan od njih:

$ curl -X PUT // localhost: 8080 / products / 1 -H 'content-type: application / json' -d '{"name": "Juice"}' {"message": "Uspješno ažuriran ID proizvoda 1" , "kôd": 200}

... pročitajte onu koju smo upravo ažurirali:

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

Konačno, možemo izbrisati jedan:

$ curl -X DELETE // localhost: 8080 / products / 2 {"message": "Uspješno izbrisani ID proizvoda 2", "code": 200}

9. Zaključak

JavaLite ima puno alata koji pomažu programerima pokrenuti aplikaciju za nekoliko minuta. Međutim, iako zasnivanje stvari na konvencijama rezultira čišćim i jednostavnijim kodom, treba neko vrijeme da se shvati imenovanje i mjesto klasa, paketa i datoteka.

Ovo je bio samo uvod u ActiveWeb i ActiveJDBC, pronaći više dokumentacije na njihovoj web stranici i potražiti aplikaciju naših proizvoda u projektu Github.


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