Indlejret Jetty Server i Java

1. Oversigt

I denne artikel vil vi se på Anløbsbro bibliotek. Jetty leverer en webserver, der kan køre som en integreret container og let kan integreres med javax.servlet bibliotek.

2. Maven-afhængigheder

For at komme i gang tilføjer vi Maven-afhængigheder til jetty-server- og jetty-servlet-biblioteker:

 org.eclipse.jetty anløbsbro 9.4.3.v20170317 org.eclipse.jetty anløbsbro 9.4.3.v20170317 

3. Start af Jetty Server med Servlet

Det er enkelt at starte den indlejrede container fra Jetty. Vi er nødt til at instantiere et nyt Server objekt og indstil det til at starte på en given port:

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

Lad os sige, at vi vil oprette et slutpunkt, der vil svare med HTTP-statuskoden på 200, hvis alt går godt og en simpel JSON-nyttelast.

Vi opretter en klasse, der udvider HttpServlet klasse til at håndtere en sådan anmodning denne klasse vil være enkelt gevind og blokere indtil afslutning:

offentlig klasse BlockingServlet udvider HttpServlet {beskyttet ugyldig doGet (HttpServletRequest anmodning, HttpServletResponse svar) kaster ServletException, IOException {respons.setContentType ("applikation / json"); respons.setStatus (HttpServletResponse.SC_OK); respons.getWriter (). println ("{\" status \ ": \" ok \ "}"); }}

Dernæst skal vi registrere BlockingServlet klasse i ServletHandler objekt ved hjælp af addServletWithMapping () metode og start serveren:

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

Hvis vi ønsker at teste vores Servlet-logik, skal vi starte vores server ved hjælp af den tidligere oprettede JettyServer klasse, der er en indpakning af den aktuelle Jetty-serverinstans inden for testopsætningen:

@Før offentlig ugyldig opsætning () kaster undtagelse {jettyServer = ny JettyServer (); jettyServer.start (); }

Når det er startet, sender vi en test-HTTP-anmodning til / status slutpunkt:

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

4. Ikke-blokerende servlets

Anløbsbro har god support til asynkron behandling af anmodninger.

Lad os sige, at vi har en enorm ressource, der er I / O-intens, der tager lang tid at indlæse, hvilket blokerer den udførende tråd i en betydelig periode. Det er bedre, hvis denne tråd kan frigøres til at håndtere andre anmodninger i mellemtiden i stedet for at vente på en I / O-ressource.

For at give en sådan logik med Jetty kan vi oprette en servlet, der bruger AsyncContext klasse ved at ringe til startAsync () metode til HttpServletRequest. Denne kode blokerer ikke den udførende tråd, men vil udføre I / O-operationen i separat tråd, der returnerer resultatet, når du er klar til at bruge AsyncContext.complete () metode:

offentlig klasse AsyncServlet udvider HttpServlet {privat statisk streng HEAVY_RESOURCE = "Dette er en tung ressource, der vil blive serveret på en asynkroniseret måde"; beskyttet ugyldigt doGet (HttpServletRequest anmodning, HttpServletResponse svar) kaster ServletException, IOException {ByteBuffer indhold = ByteBuffer.wrap (HEAVY_RESOURCE.getBytes (StandardCharsets.UTF_8)); AsyncContext async = request.startAsync (); ServletOutputStream out = respons.getOutputStream (); out.setWriteListener (ny WriteListener () {@Override offentlig ugyldighed onWritePossible () kaster IOException {mens (out.isReady ()) {hvis (! content.hasRemaining ()) {respons.setStatus (200); async.complete () ; return;} out.write (content.get ());}} @ Overstyr offentlig ugyldighed 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 klar til at vende tilbage til klienten ved at påberåbe sig komplet() metode.

Dernæst skal vi tilføje AsyncServlet som en Jetty servlet kortlægning:

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

Vi kan nu sende en anmodning til / tung / asynkroniseret slutpunkt - denne anmodning håndteres af anløbsbroen på en asynkron måde:

String url = "// localhost: 8090 / heavy / async"; HttpClient-klient = HttpClientBuilder.create (). Build (); HttpGet anmodning = ny HttpGet (url); HttpResponse respons = client.execute (anmodning); assertThat (respons.getStatusLine (). getStatusCode ()) .isEqualTo (200); String responseContent = IOUtils.toString (r esponse.getEntity (). GetContent (), StandardCharsets.UTF_8); assertThat (responsContent) .isEqualTo ("Dette er en tung ressource, der vil blive serveret på en asynkroniseret måde");

Når vores applikation håndterer anmodninger på en asynkron måde, skal vi udtrykkeligt konfigurere trådpuljen. I det næste afsnit konfigurerer vi Anløbsbro at bruge en brugerdefineret trådpulje.

5. Brygekonfiguration

Når vi kører vores webapplikation på produktion, vil vi måske indstille, hvordan Jetty-serveren behandler anmodninger. Dette gøres ved at definere trådpuljen og anvende den på vores Jetty-server.

For at gøre dette har vi tre konfigurationsindstillinger, som vi kan indstille:

  • maxThreads - For at specificere det maksimale antal tråde, som Jetty kan oprette og bruge i puljen
  • minTråde - For at indstille det indledende antal tråde i den pool, som Jetty vil bruge
  • idleTimeout - Denne værdi i millisekunder definerer, hvor længe en tråd kan være inaktiv, før den stoppes og fjernes fra trådpuljen. Antallet af resterende tråde i puljen vil aldrig gå under minTråde indstilling

Med disse kan vi konfigurere det integrerede Anløbsbro server programmatisk ved at sende den konfigurerede trådpulje til Server konstruktør:

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

Derefter, når vi starter vores server, bruger den tråde fra en bestemt trådpulje.

6. Konklusion

I denne hurtige vejledning så vi, hvordan vi integrerede integrerede servere med Jetty og testede vores webapplikation.

Som altid er koden tilgængelig på GitHub.