Opbygning af en API med Spark Java Framework

1. Introduktion

I denne artikel vil vi have en hurtig introduktion til Spark framework. Spark framework er en hurtig udviklingswebramme inspireret af Sinatra-rammen for Ruby og er bygget op omkring Java 8 Lambda Expression-filosofi, hvilket gør den mindre detaljeret end de fleste applikationer skrevet i andre Java-rammer.

Det er et godt valg, hvis du vil have en Node.js som oplevelse, når du udvikler en web-API eller mikrotjenester i Java. Med Spark kan du have en REST API klar til at betjene JSON i mindre end ti linjer kode.

Vi får en hurtig start med et “Hello World” -eksempel efterfulgt af en simpel REST API.

2. Maven-afhængigheder

2.1. Spark Framework

Medtag følgende Maven-afhængighed i din pom.xml:

 com.sparkjava gnistkerne 2.5.4 

Du kan finde den nyeste version af Spark på Maven Central.

2.2. Gson-biblioteket

På forskellige steder i eksemplet bruger vi Gson-biblioteket til JSON-operationer. Hvis du vil inkludere Gson i dit projekt, skal du inkludere denne afhængighed i din pom.xml:

 com.google.code.gson gson 2.8.0 

Du kan finde den nyeste version af Gson på Maven Central.

3. Kom godt i gang med Spark Framework

Lad os se på de grundlæggende byggesten i en Spark-applikation og demonstrere en hurtig webservice.

3.1. Ruter

Webtjenester i Spark Java er bygget på ruter og deres håndterere. Ruter er vigtige elementer i Spark. I henhold til dokumentationen består hver rute af tre enkle stykker - a udsagnsord, a stiog en ring tilbage.

  1. Det udsagnsord er en metode, der svarer til en HTTP-metode. Verbmetoder inkluderer: get, post, put, delete, head, trace, connect, og muligheder
  2. Det sti (også kaldet et rutemønster) bestemmer hvilke URI (r) ruten skal lytte til og give et svar på
  3. Det ring tilbage er en behandlingsfunktion, der påkaldes for et givet verbum og sti for at generere og returnere et svar på den tilsvarende HTTP-anmodning. En tilbagekaldelse tager et anmodningsobjekt og et svarobjekt som argumenter

Her viser vi den grundlæggende struktur for en rute, der bruger udsagnsord:

få ("/ din-rute-sti /", (anmodning, svar) -> {// din tilbagekaldskode});

3.2. Hej verdens API

Lad os oprette en simpel webservice, der har to ruter til GET-anmodninger og returnerer "Hej" -meddelelser som svar. Disse ruter bruger metode, som er en statisk import fra klassen gnist. gnist:

importer statisk gnist.Spark. *; offentlig klasse HelloWorldService {public static void main (String [] args) {get ("/ hello", (req, res) -> "Hello, world"); get ("/ hello /: name", (req, res) -> {return "Hello", + req.params (": name");}); }}

Det første argument til metoden er stien til ruten. Den første rute indeholder en statisk sti, der kun repræsenterer en enkelt URI ("/Hej").

Den anden rute sti (“/ Hej /: navn”) indeholder en pladsholder til "navn" som angivet ved forud for parameteren med et kolon (“:”). Denne rute påberåbes som svar på GET-anmodninger til URI'er som f.eks “/ Hej / Joe” og “/ Hej / Mary”.

Det andet argument til metoden er et lambda-udtryk, der giver en funktionel programmeringssmag til denne ramme.

Lambda-udtrykket har anmodning og svar som argumenter og hjælper med at returnere svaret. Vi lægger vores controller-logik i lambda-udtrykket for REST API-ruterne, som vi skal se senere i denne vejledning.

3.3. Test af Hello World API

Efter at have kørt klassen HelloWorldService Som en normal Java-klasse vil du kunne få adgang til tjenesten på dens standardport 4567 ved hjælp af de ruter, der er defineret med metoden ovenfor.

Lad os se på anmodningen og svaret på den første rute:

Anmodning:

FÅ // localhost: 4567 / hej

Respons:

Hej Verden

Lad os teste den anden rute, forbi navn parameter i sin sti:

Anmodning:

FÅ // localhost: 4567 / hej / baeldung

Respons:

Hej baeldung

Se hvordan placeringen af ​​teksten “Baeldung” i URI blev brugt til at matche rutemønsteret “/ Hej /: navn” - forårsager, at den anden rutes tilbagekaldshåndteringsfunktion påberåbes.

4. Design af en RESTful service

I dette afsnit designer vi en simpel REST-webservice til følgende Bruger enhed:

offentlig klasse bruger {privat streng-id; privat streng fornavn; privat streng efternavn; privat streng e-mail; // konstruktører, getters og settere}

4.1. Ruter

Lad os liste de ruter, der udgør vores API:

  • GET / brugere - få en liste over alle brugere
  • GET / brugere /: id - få bruger med givet id
  • POST / brugere /: id - tilføj en bruger
  • PUT / brugere /: id - rediger en bestemt bruger
  • VALGMULIGHEDER / brugere /: id - kontroller, om en bruger eksisterer med et givet id
  • SLET / brugere /: id - slet en bestemt bruger

4.2. Brugertjenesten

Nedenfor er UserService interface, der erklærer CRUD - operationerne for Bruger enhed:

offentlig grænseflade UserService {public void addUser (brugerbruger); offentlig indsamling getUsers (); offentlig bruger getUser (streng-id); offentlig brugerredigeringBruger (brugerbruger) kaster UserException; offentlig ugyldighed deleteUser (streng-id); offentlig boolsk brugerExist (streng-id); }

Til demonstrationsformål leverer vi en Kort implementering af dette UserService interface i GitHub-koden for at simulere vedholdenhed. Du kan levere din egen implementering med den database og det persistenslag, du vælger.

4.3. JSON-responsstrukturen

Nedenfor er JSON-strukturen af ​​svarene brugt i vores REST-tjeneste:

{status: besked: data:}

Det status feltværdi kan være enten SUCCES eller FEJL. Det data felt indeholder JSON-repræsentationen af ​​returneringsdataene, såsom en Bruger eller samling af Brugere.

Når der ikke returneres data, eller hvis status er FEJL, vi udfylder besked felt for at formidle en årsag til fejlen eller manglen på returneringsdata.

Lad os repræsentere ovenstående JSON-struktur ved hjælp af en Java-klasse:

offentlig klasse StandardResponse {privat StatusResponse status; privat streng besked; private JsonElement-data; public StandardResponse (StatusResponse status) {// ...} public StandardResponse (StatusResponse status, String message) {// ...} public StandardResponse (StatusResponse status, JsonElement data) {// ...} // getters and setters }

hvor Status Svar er en enum defineret som nedenfor:

offentlig enum StatusResponse {SUCCESS ("Succes"), FEJL ("Fejl"); privat strengstatus; // konstruktører, getters}

5. Implementering af RESTful Services

Lad os nu implementere ruterne og håndtererne til vores REST API.

5.1. Oprettelse af controllere

Følgende Java-klasse indeholder ruterne til vores API, inklusive verbene og stierne og en oversigt over håndtererne for hver rute:

public class SparkRestExample {public static void main (String [] args) {post ("/ users", (anmodning, svar) -> {// ...}); get ("/ brugere", (anmodning, svar) -> {// ...}); get ("/ brugere /: id", (anmodning, svar) -> {// ...}); sæt ("/ brugere /: id", (anmodning, svar) -> {// ...}); slet ("/ brugere /: id", (anmodning, svar) -> {// ...}); valgmuligheder ("/ brugere /: id", (anmodning, svar) -> {// ...}); }}

Vi viser den fulde implementering af hver rutehåndterer i de følgende underafsnit.

5.2. Tilføj bruger

Nedenfor er stolpe metode svarhåndtering, som tilføjer en Bruger:

post ("/ brugere", (anmodning, svar) -> {respons.type ("applikation / json"); Brugerbruger = ny Gson (). fraJson (anmodning.krop (), Bruger.klasse); brugerService.addUser (bruger); returner ny Gson () .toJson (ny StandardResponse (StatusResponse.SUCCESS));});

Bemærk: I dette eksempel er JSON-repræsentationen af Bruger objekt sendes som den rå krop i en POST-anmodning.

Lad os teste ruten:

Anmodning:

POST // localhost: 4567 / brugere {"id": "1012", "email": "[email protected]", "firstName": "Mac", "lastName": "Mason1"}

Respons:

{"status": "SUCCESS"}

5.3. Få alle brugere

Nedenfor er behandlingsmetode svarhåndtering, som returnerer alle brugere fra UserService:

get ("/ brugere", (anmodning, svar) -> {respons.type ("applikation / json"); returner ny Gson (). tilJson (ny StandardResponse (StatusResponse.SUCCESS, ny Gson () .toJsonTree (userService) getUsers ())));});

Lad os nu teste ruten:

Anmodning:

GET // localhost: 4567 / brugere

Respons:

{"status": "SUCCESS", "data": [{"id": "1014", "firstName": "John", "lastName": "Miller", "email": "[email protected]"} , {"id": "1012", "firstName": "Mac", "lastName": "Mason1", "email": "[email protected]"}}}

5.4. Få bruger efter id

Nedenfor er metode svarhåndterer, som returnerer en Bruger med det givne id:

get ("/ users /: id", (request, response) -> {response.type ("application / json"); returner ny Gson (). toJson (ny StandardResponse (StatusResponse.SUCCESS, ny Gson () .toJsonTree (userService.getUser (anmodning.params (": id")))));});

Lad os nu teste ruten:

Anmodning:

GET // localhost: 4567 / brugere / 1012

Respons:

{"status": "SUCCESS", "data": {"id": "1012", "firstName": "Mac", "lastName": "Mason1", "email": "[email protected]"}}

5.5. Rediger en bruger

Nedenfor er sætte behandlingsmetode, der redigerer brugeren, der har id leveres i rutemønsteret:

sæt ("/ brugere /: id", (anmodning, svar) -> {respons.type ("applikation / json"); bruger til redigering = ny Gson (). fraJson (anmodning.krop (), bruger.klasse); Bruger editedUser = userService.editUser (toEdit); hvis (editedUser! = Null) {returner ny Gson (). ToJson (ny StandardResponse (StatusResponse.SUCCESS, ny Gson () .toJsonTree (editedUser)));} ellers {returner ny Gson (). ToJson (ny StandardResponse (StatusResponse.ERROR, ny Gson () .toJson ("Bruger ikke fundet eller fejl i redigering")))}});

Bemærk: I dette eksempel overføres dataene i den rå krop af en POST-anmodning som et JSON-objekt, hvis egenskabsnavne matcher felterne i Bruger objekt, der skal redigeres.

Lad os teste ruten:

Anmodning:

PUT // localhost: 4567 / users / 1012 {"lastName": "Mason"}

Respons:

{"status": "SUCCESS", "data": {"id": "1012", "firstName": "Mac", "lastName": "Mason", "email": "[email protected]"}}

5.6. Slet en bruger

Nedenfor er slet metoden svarhåndtering, som vil slette Bruger med det givne id:

slet ("/ brugere /: id", (anmodning, svar) -> {respons.type ("applikation / json"); userService.deleteUser (anmodning.params (": id")); returner ny Gson (). toJson (ny StandardResponse (StatusResponse.SUCCESS, "bruger slettet"))}};

Lad os nu teste ruten:

Anmodning:

SLET // localhost: 4567 / brugere / 1012

Respons:

{"status": "SUCCESS", "message": "bruger slettet"}

5.7. Kontroller, om brugeren findes

Det muligheder metoden er et godt valg til betinget kontrol. Nedenfor er muligheder metode svarhåndtering, som vil kontrollere, om en Bruger med det givne id eksisterer:

optioner ("/ brugere /: id", (anmodning, svar) -> {respons.type ("applikation / json"); returner ny Gson (). tilJson (ny StandardResponse (StatusResponse.SUCCESS, (userService.userExist (anmodning) .params (": id")))? "Bruger findes": "Bruger eksisterer ikke"));});

Lad os nu teste ruten:

Anmodning:

VALGMULIGHEDER // localhost: 4567 / brugere / 1012

Respons:

{"status": "SUCCESS", "message": "Brugeren findes"}

6. Konklusion

I denne artikel havde vi en hurtig introduktion til Spark-rammen til hurtig webudvikling.

Denne ramme fremmes primært til generering af mikrotjenester i Java. Node.js udviklere med Java-viden, der ønsker at udnytte biblioteker, der er bygget på JVM-biblioteker, skal føle sig hjemme ved hjælp af denne ramme.

Og som altid kan du finde alle kilderne til denne tutorial i Github-projektet.