En guide til JavaLite - Bygg en RESTful CRUD-applikasjon

1. Introduksjon

JavaLite er en samling rammer for å forenkle vanlige oppgaver som hver utvikler må forholde seg til når han bygger applikasjoner.

I denne opplæringen skal vi ta en titt på JavaLite-funksjoner som er fokusert på å bygge en enkel API.

2. Oppsett

Gjennom denne opplæringen oppretter vi en enkel RESTful CRUD-applikasjon. For å gjøre det, vi bruker ActiveWeb og ActiveJDBC - to av rammene som JavaLite integrerer med.

Så la oss komme i gang og legge til den første avhengigheten vi trenger:

 org.javalite activeweb 1.15 

ActiveWeb-gjenstand inkluderer ActiveJDBC, så det er ikke nødvendig å legge den til separat. Vær oppmerksom på at den nyeste activeweb-versjonen finnes i Maven Central.

Den andre avhengigheten vi trenger er en databasekontakt. For dette eksemplet skal vi bruke MySQL, så vi må legge til:

 mysql mysql-connector-java 5.1.45 

Igjen, siste mysql-connector-java avhengighet kan bli funnet på Maven Central.

Den siste avhengigheten vi må legge til er noe spesifikt for JavaLite:

 org.javalite activejdbc-instrumentering 1.4.13 prosessklasser instrument 

Den siste plugin-en for aktivjdbc-instrumentering finnes også i Maven Central.

Når vi har alt dette på plass, og før du begynner med enheter, tabeller og kartlegginger, sørger vi for at det en av de støttede databasene er i gang. Som vi sa tidligere, bruker vi MySQL.

Nå er vi klare til å starte med objektrelasjonell kartlegging.

3. Objektrelasjonell kartlegging

3.1. Kartlegging og instrumentering

La oss komme i gang med skape en Produkt klasse som vil være vår hovedenhet:

produkt i offentlig klasse {}

Og la oss også lag den tilsvarende tabellen for den:

OPPRETT TABELLPRODUKTER (id int (11) STANDARD NULL auto_increment PRIMÆR NØKKEL, navn VARCHAR (128));

Endelig kan vi endre vår Produkt klasse for å gjøre kartleggingen:

offentlig klasse Produkt utvider modell {}

Vi trenger bare å utvide org.javalite.activejdbc.Modell klasse. ActiveJDBC utleder DB-skjemaparametere fra databasen. Takket være denne muligheten, det er ikke nødvendig å legge til getters og settere eller noen kommentar.

Videre gjenkjenner ActiveJDBC det automatisk Produkt klassen må kartlegges til PRODUKTER bord. Den bruker engelske bøyninger for å konvertere entallform av en modell til flertall av en tabell. Og ja, det fungerer også med unntak.

Det er en siste ting som vi trenger for å få kartleggingen til å fungere: instrumentering. Instrumentering er et ekstra trinn som kreves av ActiveJDBC som vil tillate oss å leke med vår Produkt klasse som om det hadde getters, settere og DAO-lignende metoder.

Etter å ha kjørt instrumentering, kan vi gjøre ting som:

Produkt p = nytt produkt (); p.set ("navn", "Brød"); p.saveIt ();

eller:

Liste produkter = Product.findAll ();

Dette er hvor aktivjdbc-instrumentering plugin kommer inn. Ettersom vi allerede har avhengighet i vår pom, bør vi se at klasser blir instrumentert under byggingen:

... [INFO] --- activejdbc-instrumentering: 1.4.11: instrument (standard) @ javalite --- *********************** **** STARTINSTRUMENTASJON **************************** Katalog: ... \ tutorials \ java-lite \ target \ classes Instrumented klasse: ... / tutorials / java-lite / target / classes / app / models / Product.class *************************** * SLUTTINSTRUMENTASJON **************************** ...

Deretter lager vi en enkel test for å sikre at dette fungerer.

3.2. Testing

Til slutt, for å teste kartleggingen vår, følger vi tre enkle trinn: Åpne en forbindelse til databasen, lagre et nytt produkt og hente det:

@Test offentlig ugyldig givenSavedProduct_WhenFindFirst_ThenSavedProductIsReturned () {Base.open ("com.mysql.jdbc.Driver", "jdbc: mysql: // localhost / dbname", "bruker", "passord"); Produkt toSaveProduct = nytt produkt (); toSaveProduct.set ("navn", "brød"); toSaveProduct.saveIt (); Produkt sparet Produkt = Produkt.findFirst ("navn =?", "Brød"); assertEquals (toSaveProduct.get ("name"), savedProduct.get ("name")); }

Merk at alt dette (og mer) er mulig ved bare å ha en tom modell og instrumentering.

4. Kontrollere

Nå som kartleggingen vår er klar, kan vi begynne å tenke på applikasjonen vår og dens CRUD-metoder.

For det skal vi bruke kontrollere som behandler HTTP-forespørsler.

La oss lage våre ProductsController:

@RESTful offentlig klasse ProductsController utvider AppController {public void index () {// ...}}

Med denne implementeringen vil ActiveWeb automatisk kartlegge indeks () metode til følgende URI:

//:/Produkter

Kontrollere kommentert med @Avslappende, gi et fast sett med metoder som automatisk tilordnes forskjellige URI-er. La oss se de som vil være nyttige for vårt CRUD-eksempel:

KontrollmetodeHTTP-metodenURI
SKAPEskape()POST// vert: port / produkter
LES ENvise fram()// vert: port / produkter / {id}
LES ALLEindeks ()// vert: port / produkter
OPPDATEROppdater()SETTE// vert: port / produkter / {id}
SLETTødelegge()SLETT// vert: port / produkter / {id}

Og hvis vi legger til dette settet med metoder til vårt ProductsController:

@RESTful offentlig klasse ProductsController utvider AppController {public void index () {// code for å få alle produkter} public void create () {// code for create a new product} public void update () {// code for update a eksisterende produkt} offentlig ugyldig visning () {// kode for å finne ett produkt} offentlig tomrom ødelegge () {// kode for å fjerne et eksisterende produkt}}

Før vi går videre til logikkimplementeringen, ser vi raskt på noen få ting som vi trenger å konfigurere.

5. Konfigurasjon

ActiveWeb er hovedsakelig basert på konvensjoner, prosjektstruktur er et eksempel på det. ActiveWeb-prosjekter må følge en forhåndsdefinert pakkeoppsett:

src | ---- main | ---- java.app | | ---- config | | ---- kontrollere | | ---- modeller | ---- ressurser | ---- webapp | ---- WEB-INF | ---- visninger

Det er en spesifikk pakke som vi må ta en titt på - app.konfig.

Inne i den pakken skal vi lage tre klasser:

offentlig klasse DbConfig utvider AbstractDBConfig {@Override public void init (AppContext appContext) {this.configFile ("/ database.properties"); }}

Denne klassen konfigurerer databaseforbindelser ved hjelp av en egenskapsfil i prosjektets rotkatalog som inneholder de nødvendige parametrene:

development.driver = com.mysql.jdbc.Driver development.username = brukerutvikling.passord = passordutvikling.url = jdbc: mysql: // localhost / dbname

Dette vil opprette forbindelsen som automatisk erstatter det vi gjorde i første linje i kartleggingsprøven.

Den andre klassen som vi må inkludere inne app.config pakken er:

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

Denne kodenvil binde forbindelsen som vi nettopp konfigurerte til kontrolleren vår.

Tredje klasse vilkonfigurer appens kontekst:

offentlig klasse AppBootstrap utvider Bootstrap {public void init (AppContext context) {}}

Etter å ha opprettet de tre klassene, er det siste angående konfigurasjon skape vår web.xml fil under webapp / WEB-INF katalog:

   dispatcher org.javalite.activeweb.RequestDispatcher eksklusjoner css, bilder, js, ico koding UTF-8 dispatcher / * 

Nå som konfigurasjonen er ferdig, kan vi fortsette og legge til logikken vår.

6. Implementering av CRUD Logic

Med de DAO-lignende funksjonene som tilbys av vår Produkt klasse, det er superenkelt å legge til grunnleggende CRUD-funksjonalitet:

@RESTful offentlig klasse ProductsController utvider AppController {private ObjectMapper mapper = ny ObjectMapper (); public void index () {List products = Product.findAll (); // ...} public void create () {Map payload = mapper.readValue (getRequestString (), Map.class); Produkt p = nytt produkt (); p.fromMap (nyttelast); p.saveIt (); // ...} offentlig ugyldig oppdatering () {Map payload = mapper.readValue (getRequestString (), Map.class); Streng-id = getId (); Produkt p = Product.findById (id); p.fromMap (nyttelast); p.saveIt (); // ...} offentlig ugyldig show () {String id = getId (); Produkt p = Product.findById (id); // ...} offentlig tomrom ødelegge () {String id = getId (); Produkt p = Product.findById (id); p.delete (); // ...}}

Enkelt, ikke sant? Dette gir imidlertid ikke noe ennå. For å gjøre det, må vi lage noen visninger.

7. Visninger

ActiveWeb bruker FreeMarker som en malmotor, og alle malene skal være under src / main / webapp / WEB-INF / visninger.

Inne i katalogen vil vi plassere våre synspunkter i en mappe som heter Produkter (samme som kontrolleren vår). La oss lage vår første mal som heter _product.ftl:

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

Det er ganske klart på dette punktet at dette er et JSON-svar. Selvfølgelig vil dette bare fungere for ett produkt, så la oss fortsette og lage en ny mal som heter index.ftl:

[]

Dette vil i utgangspunktet gi en samling navngitt Produkter, med hver og en formatert av _product.ftl.

Endelig, vi må binde resultatet fra kontrolleren vår til tilsvarende visning:

@RESTful offentlig klasse ProductsController utvider AppController {public void index () {List products = Product.findAll (); visning ("produkter", produkter); gjengi (); } offentlig ugyldig show () {String id = getId (); Produkt p = Product.findById (id); visning ("produkt", p); gjengi ("_ produkt"); }}

I det første tilfellet tildeler vi Produkter liste til malsamlingen vår også Produkter.

Da vi ikke spesifiserer noe syn, index.ftl vil bli brukt.

I den andre metoden tildeler vi produktet s til element produkt i visningen, og vi sier eksplisitt hvilken visning som skal gjengis.

Vi kan også lage et syn melding.ftl:

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

Og så kaller det fra noen av våre ProductsController‘S metode:

visning ("melding", "Det oppstod en feil.", "kode", 200); gjengi ("melding");

La oss nå se finalen vår ProductsController:

@RESTful offentlig klasse ProductsController utvider AppController {private ObjectMapper mapper = ny ObjectMapper (); public void index () {view ("products", Product.findAll ()); gjengi (). contentType ("applikasjon / json"); } public void create () {Map payload = mapper.readValue (getRequestString (), Map.class); Produkt p = nytt produkt (); p.fromMap (nyttelast); p.saveIt (); visning ("melding", "Vellykket lagret produkt-id" + s.get ("id"), "kode", 200); gjengi ("melding"); } offentlig ugyldig oppdatering () {Map payload = mapper.readValue (getRequestString (), Map.class); Streng-id = getId (); Produkt p = Product.findById (id); hvis (p == null) {view ("melding", "Produkt-id" + id + "ikke funnet.", "kode", 200); gjengi ("melding"); komme tilbake; } p.fromMap (nyttelast); p.saveIt (); view ("melding", "Oppdatert produkt-id" + id, "kode", 200); gjengi ("melding"); } offentlig ugyldig show () {String id = getId (); Produkt p = Product.findById (id); hvis (p == null) {view ("melding", "Produkt-id" + id + "ikke funnet.", "kode", 200); gjengi ("melding"); komme tilbake; } visning ("produkt", p); gjengi ("_ produkt"); } offentlig tomrom ødelegge () {String id = getId (); Produkt p = Product.findById (id); hvis (p == null) {visning ("melding", "Produkt-id" + id + "ikke funnet.", "kode", 200); gjengi ("melding"); komme tilbake; } p.delete (); visning ("melding", "Vellykket slettet produkt-id" + id, "kode", 200); gjengi ("melding"); } @ Override-beskyttet streng getContentType () {return "application / json"; } @ Override-beskyttet streng getLayout () {return null; }}

På dette tidspunktet er søknaden vår ferdig, og vi er klare til å kjøre den.

8. Kjøre applikasjonen

Vi bruker Jetty-plugin:

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

Finn siste jetty-maven-plugin i Maven Central.

Og vi er klare, vi kan kjøre applikasjonen vår:

mvn brygge: løp

La oss lage et par produkter:

$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Water"}' {"message": "Vellykket lagret produkt-ID 1", " kode ": 200}
$ curl -X POST // localhost: 8080 / products -H 'content-type: application / json' -d '{"name": "Bread"}' {"message": "Vellykket lagret produkt-ID 2", " kode ": 200}

.. Les dem:

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

.. oppdater en av dem:

$ curl -X PUT // localhost: 8080 / products / 1 -H 'content-type: application / json' -d '{"name": "Juice"}' {"message": "Oppdatert produkt-ID 1" , "kode": 200}

... les den vi nettopp oppdaterte:

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

Til slutt kan vi slette en:

$ curl -X SLETT // localhost: 8080 / products / 2 {"melding": "Produkt-ID 2 er slettet," kode ": 200}

9. Konklusjon

JavaLite har mange verktøy for å hjelpe utviklere få en applikasjon i gang på få minutter. Mens det å basere ting på konvensjoner resulterer i en renere og enklere kode, tar det imidlertid en stund å forstå navn og plassering av klasser, pakker og filer.

Dette var bare en introduksjon til ActiveWeb og ActiveJDBC, finn mer dokumentasjon på deres nettsider og se etter produktsøknaden vår i Github-prosjektet.


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