Embedded Jetty Server i Java

1. Oversikt

I denne artikkelen vil vi se på Brygge bibliotek. Jetty tilbyr en webserver som kan kjøre som en innebygd container og integreres enkelt med javax.servlet bibliotek.

2. Maven-avhengigheter

For å komme i gang legger vi til Maven-avhengigheter til brygger-server og bryg-servlet-biblioteker:

 org.eclipse.jetty bryggeserver 9.4.3.v20170317 org.eclipse.jetty bryggeservlet 9.4.3.v20170317 

3. Starte bryggeserver med Servlet

Det er enkelt å starte den innebygde containeren. Vi trenger å sette i gang et nytt Server objekt og sett den til å starte på en gitt port:

offentlig klasse JettyServer {privat server server; offentlig ugyldig start () kaster Unntak {server = ny Server (); ServerConnector-kontakt = ny ServerConnector (server); connector.setPort (8090); server.setConnectors (ny Connector [] {connector}); }

La oss si at vi ønsker å lage et sluttpunkt som vil svare med HTTP-statuskoden på 200 hvis alt går bra og en enkel JSON-nyttelast.

Vi oppretter en klasse som utvider HttpServlet klasse for å håndtere en slik forespørsel; denne klassen vil være en tråd og blokkere til den er fullført:

offentlig klasse BlockingServlet utvider HttpServlet {beskyttet ugyldig doGet (HttpServletRequest-forespørsel, HttpServletResponse-svar) kaster ServletException, IOException {respons.setContentType ("applikasjon / json"); respons.setStatus (HttpServletResponse.SC_OK); respons.getWriter (). println ("{\" status \ ": \" ok \ "}"); }}

Deretter må vi registrere BlockingServlet klasse i ServletHandler objektet ved å bruke addServletWithMapping () metode og start serveren:

servletHandler.addServletWithMapping (BlockingServlet.class, "/ status"); server.start ();

Hvis vi ønsker å teste vår Servlet-logikk, må vi starte serveren vår ved å bruke den tidligere opprettet JettyServer klasse som er en innpakning av den faktiske Jetty-serverforekomsten i testoppsettet:

@Før offentlige ugyldige oppsett () kaster unntak {jettyServer = ny JettyServer (); jettyServer.start (); }

Når den er startet, sender vi en HTTP-testforespørsel til /status sluttpunkt:

String url = "// localhost: 8090 / status"; HttpClient-klient = HttpClientBuilder.create (). Build (); HttpGet forespørsel = ny HttpGet (url); HttpResponse respons = client.execute (forespørsel); assertThat (respons.getStatusLine (). getStatusCode ()). er EqualTo (200);

4. Ikke-blokkerende servlets

Brygge har god støtte for asynkron behandling av forespørsler.

La oss si at vi har en enorm ressurs som er I / U-intensiv, og tar lang tid å laste blokkering av kjøringstråden i betydelig tid. Det er bedre om den tråden kan frigjøres til å håndtere andre forespørsler i mellomtiden, i stedet for å vente på noen I / U-ressurser.

For å gi slik logikk med brygge, kan vi lage en servlet som skal bruke AsyncContext klasse ved å ringe startAsync () metoden på HttpServletRequest. Denne koden vil ikke blokkere den utførende tråden, men vil utføre I / O-operasjonen i separat tråd som returnerer resultatet når du er klar til å bruke AsyncContext.complete () metode:

offentlig klasse AsyncServlet utvider HttpServlet {privat statisk streng HEAVY_RESOURCE = "Dette er en tung ressurs som vil bli servert på en asynkronisert måte"; beskyttet ugyldig doGet (HttpServletRequest-forespørsel, HttpServletResponse-svar) kaster ServletException, IOException {ByteBuffer content = ByteBuffer.wrap (HEAVY_RESOURCE.getBytes (StandardCharsets.UTF_8)); AsyncContext async = request.startAsync (); ServletOutputStream ut = respons.getOutputStream (); out.setWriteListener (ny WriteListener () {@Override public void onWritePossible () kaster IOException {while (out.isReady ()) {if (! content.hasRemaining ()) {response.setStatus (200); async.complete () ; return;} out.write (content.get ());}} @ Override public void onError (Throwable t) {getServletContext (). log ("Async Error", t); async.complete ();}}) ; }}

Vi skriver ByteBuffer til OutputStream, og når hele bufferen er skrevet signaliserer vi at resultatet er klart til å returnere til klienten ved å påkalle fullstendig() metode.

Deretter må vi legge til AsyncServlet som en bryggekartett:

servletHandler.addServletWithMapping (AsyncServlet.class, "/ heavy / async");

Vi kan nå sende en forespørsel til / tung / asynkronisert endepunkt - forespørselen vil bli håndtert av bryggen på en asynkron måte:

String url = "// localhost: 8090 / heavy / async"; HttpClient-klient = HttpClientBuilder.create (). Build (); HttpGet forespørsel = ny HttpGet (url); HttpResponse respons = client.execute (forespørsel); assertThat (respons.getStatusLine (). getStatusCode ()) .isEqualTo (200); String responseContent = IOUtils.toString (r esponse.getEntity (). GetContent (), StandardCharsets.UTF_8); assertThat (responseContent) .isEqualTo ("Dette er en tung ressurs som vil bli servert på en asynkronisert måte");

Når søknaden vår behandler forespørsler på en asynkron måte, bør vi konfigurere trådbasseng eksplisitt. I neste avsnitt vil vi konfigurere Brygge for å bruke et tilpasset trådbasseng.

5. Bryggekonfigurasjon

Når vi kjører webapplikasjonen vår på produksjon, vil vi kanskje justere hvordan Jetty-serveren behandler forespørsler. Dette gjøres ved å definere trådbassenget og bruke det på bryggeserveren vår.

For å gjøre dette har vi tre konfigurasjonsinnstillinger som vi kan angi:

  • maxTråder - Å spesifisere maksimalt antall tråder som Jetty kan opprette og bruke i bassenget
  • minTråder - For å angi det første antallet tråder i bassenget som Jetty skal bruke
  • idleTimeout - Denne verdien i millisekunder definerer hvor lenge en tråd kan være inaktiv før den stoppes og fjernes fra trådbassenget. Antall gjenværende tråder i bassenget vil aldri gå under minTråder omgivelser

Med disse kan vi konfigurere det innebygde Brygge serveren programmatisk ved å sende den konfigurerte trådgruppen til Server konstruktør:

int maxThreads = 100; int minTråder = 10; int idleTimeout = 120; QueuedThreadPool threadPool = ny QueuedThreadPool (maxThreads, minThreads, idleTimeout); server = ny server (threadPool);

Så når vi starter serveren vår, vil den bruke tråder fra en bestemt trådgruppe.

6. Konklusjon

I denne raske opplæringen så vi hvordan vi kunne integrere innebygde servere med Jetty og testet vår webapplikasjon.

Som alltid er koden tilgjengelig på GitHub.


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