Mikrotjenester med Oracle Helidon

1. Oversikt

Helidon er det nye Java microservice-rammeverket som nylig har blitt åpnet av Oracle. Den ble brukt internt i Oracle-prosjekter under navnet J4C (Java for Cloud).

I denne opplæringen vil vi dekke hovedkonseptene i rammeverket, og deretter flytte vi til å bygge og kjøre en Helidon-basert mikroservice.

2. Programmeringsmodell

For tiden, rammeverket støtter to programmeringsmodeller for skriving av mikrotjenester: Helidon SE og Helidon MP.

Mens Helidon SE er designet for å være et mikrorammer som støtter den reaktive programmeringsmodellen, er Helidon MP derimot en Eclipse MicroProfile-kjøretid som lar Jakarta EE-samfunnet kjøre mikrotjenester på en bærbar måte.

I begge tilfeller er en Helidon-mikrotjeneste et Java SE-program som starter en tinny HTTP-server fra hovedmetoden.

3. Helidon SE

I denne delen vil vi oppdage hovedkomponentene i Helidon SE i flere detaljer: WebServer, Config og Security.

3.1. Sette opp WebServer

For å komme i gang med WebServer API, Vi må legge til den nødvendige Maven-avhengigheten til pom.xml fil:

 io.helidon.webserver helidon-webserver 0.10.4 

For å ha en enkel webapplikasjon, vi kan bruke en av følgende byggemetoder: WebServer.create (serverConfig, ruting) eller bare WebServer.create (ruting). Den siste tar en standard serverkonfigurasjon som lar serveren kjøre på en tilfeldig port.

Her er en enkel webapplikasjon som kjører på en forhåndsdefinert port. Vi har også registrert en enkel behandler som vil svare med hilsen på alle HTTP-forespørsler med ‘/hilse på' sti og Metode:

public static void main (String ... args) kaster Unntak {ServerConfiguration serverConfig = ServerConfiguration.builder () .port (9001) .build (); Routing routing = Routing.builder () .get ("/ greet", (forespørsel, svar) -> response.send ("Hello World!")). Build (); WebServer.create (serverConfig, routing) .start () .thenAccept (ws -> System.out.println ("Server startet på: // localhost:" + ws.port ())); }

Den siste linjen er å starte serveren og vente på servering av HTTP-forespørsler. Men hvis vi kjører denne eksempelkoden i hovedmetoden, får vi feilen:

Unntak i tråden "hoved" java.lang.IllegalStateException: Ingen implementering funnet for SPI: io.helidon.webserver.spi.WebServerFactory

De Internett server er egentlig et SPI, og vi må tilby en kjøretidsimplementering. For tiden, Helidon sørger for NettyWebServer gjennomføring som er basert på Netty Core.

Her er Maven-avhengigheten for denne implementeringen:

 io.helidon.webserver helidon-webserver-netty 0.10.4 kjøretid 

Nå kan vi kjøre hovedprogrammet og kontrollere at det fungerer ved å påkalle det konfigurerte endepunktet:

// localhost: 9001 / hilsen

I dette eksemplet konfigurerte vi både porten og banen ved hjelp av byggmønsteret.

Helidon SE tillater også bruk av et konfigurasjonsmønster der konfigurasjonsdataene leveres av Konfig API. Dette er temaet for neste avsnitt.

3.2. De Konfig API

De Konfig API gir verktøy for å lese konfigurasjonsdata fra en konfigurasjonskilde.

Helidon SE tilbyr implementeringer for mange konfigurasjonskilder. Standardimplementeringen er levert av helidon-config der konfigurasjonskilden er en application.properties filen ligger under klassestien:

 io.helidon.config helidon-config 0.10.4 

For å lese konfigurasjonsdataene, trenger vi bare å bruke standardbyggeren som standard tar konfigurasjonsdataene fra application.properties:

Config config = Config.builder (). Build ();

La oss lage en application.properties filen under src / main / resource katalog med følgende innhold:

server.port = 9080 web.debug = ekte web.page-size = 15 user.home = C: / Brukere / app

For å lese verdiene kan vi bruke Config.get () metode etterfulgt av en praktisk casting til de tilsvarende Java-typene:

int port = config.get ("server.port"). asInt (); int pageSize = config.get ("web.page-size"). asInt (); boolsk feilsøking = config.get ("web.debug"). asBoolean (); String userHome = config.get ("user.home"). AsString ();

Faktisk laster standardbyggeren den første funnet filen i denne prioritetsrekkefølgen: application.yaml, application.conf, application.json og application.properties. De siste tre formatene trenger en ekstra relatert konfigurasjonsavhengighet. For eksempel, for å bruke YAML-formatet, må vi legge til den relaterte YAML-konfigurasjonsavhengigheten:

 io.helidon.config helidon-config-yaml 0.10.4 

Og så legger vi til en application.yml:

server: port: 9080 web: feilsøking: ekte sidestørrelse: 15 bruker: hjem: C: / Brukere / app

På samme måte, for å bruke CONF, som er et JSON-forenklet format, eller JSON-format, må vi legge til avhengigheten av helidon-config-hocon.

Merk at konfigurasjonsdataene i disse filene kan overstyres av miljøvariabler og Java-systemegenskaper.

Vi kan også kontrollere standard oppførsel ved å deaktivere miljøvariabler og systemegenskaper eller ved å spesifisere spesifiseringskonfigurasjonskilden:

ConfigSource configSource = ConfigSources.classpath ("application.yaml"). Build (); Config config = Config.builder () .disableSystemPropertiesSource () .disableEnvironmentVariablesSource () .sources (configSource) .build ();

I tillegg til å lese konfigurasjonsdata fra klassestien, kan vi også bruke to eksterne kildekonfigurasjoner, det vil si git- og etcd-konfigurasjonene. For dette trenger vi avhengighetene helidon-config-git og helidon-git-etcd.

Til slutt, hvis alle disse konfigurasjonskildene ikke tilfredsstiller vårt behov, tillater Helidon oss å gi en implementering for konfigurasjonskilden. For eksempel kan vi tilby en implementering som kan lese konfigurasjonsdataene fra en database.

3.3. De Rute API

De Rute API gir mekanismen som vi binder HTTP-forespørsler til Java-metoder. Vi kan oppnå dette ved å bruke forespørselsmetoden og banen som samsvarende kriterier eller RequestPredicate objekt for å bruke flere kriterier.

Så for å konfigurere en rute kan vi bare bruke HTTP-metoden som kriterier:

Routing routing = Routing.builder () .get ((forespørsel, svar) -> {});

Eller vi kan kombinere HTTP-metoden med forespørselsbanen:

Routing routing = Routing.builder () .get ("/ path", (forespørsel, svar) -> {});

Vi kan også bruke RequestPredicate for mer kontroll. For eksempel kan vi se etter en eksisterende overskrift eller for innholdstypen:

Routing routing = Routing.builder () .post ("/ save", RequestPredicate.whenRequest () .containsHeader ("header1") .containsCookie ("cookie1") .accepts (MediaType.APPLICATION_JSON) .containsQueryParameter ("param1"). hasContentType ("application / json") .thenApply ((forespørsel, svar) -> {}). ellers ((forespørsel, svar) -> {})) .build ();

Inntil nå har vi levert håndterere i funksjonell stil. Vi kan også bruke Service klasse som gjør det mulig å skrive håndtere på en mer sofistikert måte.

Så la oss først lage en modell for objektet vi jobber med, the Bok klasse:

public class Book {private String id; privat strengnavn; privat strengforfatter; private heltalssider; // ...}

Vi kan opprette REST-tjenester for Bok klasse ved å implementere Service.update () metode. Dette gjør det mulig å konfigurere delstiene til samme ressurs:

offentlig klasse BookResource implementerer Service {private BookManager bookManager = ny BookManager (); @Override offentlig ugyldig oppdatering (Routing.Rules regler) {regler .get ("/", dette :: bøker) .get ("/ {id}", dette :: bookById); } privat ugyldig bookById (ServerRequest serverRequest, ServerResponse serverResponse) {String id = serverRequest.path (). param ("id"); Bokbok = bookManager.get (id); JsonObject jsonObject = fra (bok); serverResponse.send (jsonObject); } private ugyldige bøker (ServerRequest serverRequest, ServerResponse serverResponse) {List books = bookManager.getAll (); JsonArray jsonArray = fra (bøker); serverResponse.send (jsonArray); } // ...}

Vi har også konfigurert medietypen som JSON, så vi trenger helidon-webserver-json-avhengighet for dette formålet:

 io.helidon.webserver helidon-webserver-json 0.10.4 

Endelig, vi bruker registrere() metoden for Rute byggherre for å binde rotstien til ressursen. I dette tilfellet, Stier konfigurert av tjenesten er prefikset av rotbanen:

Routing routing = Routing.builder () .register (JsonSupport.get ()) .register ("/ books", new BookResource ()) .build ();

Vi kan nå starte serveren og sjekke sluttpunktene:

// localhost: 9080 / books // localhost: 9080 / books / 0001-201810

3.4. Sikkerhet

I denne seksjonen, vi skal sikre ressursene våre ved hjelp av sikkerhetsmodulen.

La oss starte med å erklære alle nødvendige avhengigheter:

 io.helidon.security helidon-sikkerhet 0.10.4 io.helidon.security helidon-security-provider-http-auth 0.10.4 io.helidon.security helidon-security-integration-webserver 0.10.4 

Avhengighetene til helidon-sikkerhet, helidon-security-provider-http-auth og helidon-security-integration-webserver er tilgjengelige fra Maven Central.

Sikkerhetsmodulen tilbyr mange leverandører for autentisering og autorisasjon. For dette eksemplet bruker vi leverandøren av grunnleggende HTTP-godkjenning siden det er ganske enkelt, men prosessen for andre leverandører er nesten den samme.

Det første du må gjøre er å lage en Sikkerhet forekomst. Vi kan gjøre det enten programmatisk for enkelhets skyld:

Kartbrukere = // ... UserStore butikk = bruker -> Valgfritt.avNullable (brukere.get (bruker)); HttpBasicAuthProvider httpBasicAuthProvider = HttpBasicAuthProvider.builder () .realm ("myRealm") .subjectType (SubjectType.USER) .userStore (store) .build (); Sikkerhetssikkerhet = Security.builder () .addAuthenticationProvider (httpBasicAuthProvider) .build ();

Eller vi kan bruke en konfigurasjonsmetode.

I dette tilfellet erklærer vi all sikkerhetskonfigurasjonen i application.yml filen som vi laster gjennom Konfig API:

#Config 4 Security ==> Kartlagt til Security Object security: providers: - http-basic-auth: realm: "helidon" principal-type: USER # Kan være USER eller SERVICE, standard er USER brukere: - login: "user" passord: "bruker" -roller: ["ROLE_USER"] - pålogging: "admin" passord: "admin" -roller: ["ROLE_USER", "ROLE_ADMIN"] #Config 4 Security Web Server Integration ==> Kartlagt til WebSecurity Object web- server: securityDefaults: autentisere: sanne stier: - sti: "/ user" metoder: ["get"] -roller-tillatt: ["ROLE_USER", "ROLE_ADMIN"] - sti: "/ admin" metoder: ["get"] roller-tillatt: ["ROLE_ADMIN"]

Og for å laste den, trenger vi bare å lage en Konfig objekt, og deretter påkaller vi Security.fromConfig () metode:

Config config = Config.create (); Sikkerhetssikkerhet = Security.fromConfig (config);

Når vi har fått Sikkerhet For eksempel må vi først registrere det med Internett server bruker WebSecurity.from () metode:

Routing routing = Routing.builder () .register (WebSecurity.from (security) .securityDefaults (WebSecurity.authenticate ())) .build ();

Vi kan også lage en WebSecurity forekommer direkte ved hjelp av konfigurasjonsmetoden som vi laster inn både sikkerhet og konfigurasjon av webserver:

Routing routing = Routing.builder () .register (WebSecurity.from (config)) .build ();

Vi kan nå legge til noen håndtere for /bruker og / admin baner, start serveren og prøv å få tilgang til dem:

Routing routing = Routing.builder () .register (WebSecurity.from (config)) .get ("/ user", (request, response) -> response.send ("Hello, I'm Helidon SE")) .get ("/ admin", (forespørsel, svar) -> respons.send ("Hei, jeg er Helidon SE")) .build ();

4. Helidon MP

Helidon MP er en implementering av Eclipse MicroProfile og gir også en kjøretid for å kjøre MicroProfile-baserte mikrotjenester.

Siden vi allerede har en artikkel om Eclipse MicroProfile, sjekker vi kildekoden og endrer den for å kjøre på Helidon MP.

Etter å ha sjekket ut koden, fjerner vi alle avhengigheter og plugins og legger til Helidon MP-avhengigheter i POM-filen:

 io.helidon.microprofile.bundles helidon-microprofile-1.2 0.10.4 org.glassfish.jersey.media jersey-media-json-binding 2.26 

Helidon-microprofile-1.2 og jersey-media-json-bindende avhengigheter er tilgjengelig fra Maven Central.

Neste, vi legger til bønner.xml filen under src / main / resource / META-INF katalog med dette innholdet:

I LibraryApplication klasse, overstyre getClasses () metode slik at serveren ikke skanner etter ressurser:

@Override public Set getClasses () {return CollectionsHelper.setOf (BookEndpoint.class); }

Til slutt oppretter du en hovedmetode og legger til denne kodebiten:

public static void main (String ... args) {Server server = Server.builder () .addApplication (LibraryApplication.class) .port (9080) .build (); server.start (); }

Og det er det. Vi vil nå kunne påkalle alle bokressursene.

5. Konklusjon

I denne artikkelen har vi utforsket hovedkomponentene i Helidon, som også viser hvordan du setter opp enten Helidon SE og MP. Siden Helidon MP bare er en Eclipse MicroProfile-kjøretid, kan vi kjøre hvilken som helst eksisterende MicroProfile-basert mikroservice ved å bruke den.

Som alltid kan koden til alle eksemplene ovenfor bli funnet på GitHub.


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