Ugrađeni Jetty poslužitelj u Javi

1. Pregled

U ovom ćemo članku pogledati Brana knjižnica. Jetty nudi web poslužitelj koji može raditi kao ugrađeni spremnik i lako se integrira s javax.servlet knjižnica.

2. Ovisnosti Mavena

Za početak ćemo dodati Mavenove ovisnosti knjižnicama jetty-server i jetty-servlet:

 org.eclipse.jetty jetty-server 9.4.3.v20170317 org.eclipse.jetty jetty-servlet 9.4.3.v20170317 

3. Pokretanje Jetty poslužitelja s Servletom

Pokretanje Jetty ugrađenog spremnika je jednostavno. Moramo napraviti novi Poslužitelj objekt i postavite ga za pokretanje na danom portu:

javna klasa JettyServer {privatni poslužitelj poslužitelja; public void start () baca iznimku {server = novi poslužitelj (); ServerConnector konektor = novi ServerConnector (poslužitelj); konektor.setPort (8090); server.setConnectors (novi Connector [] {konektor}); }

Recimo da želimo stvoriti krajnju točku koja će odgovoriti HTTP statusnim kodom 200 ako sve bude u redu i jednostavnim JSON korisnim opterećenjem.

Stvorit ćemo klasu koja proširuje HttpServlet klasa koja obrađuje takav zahtjev; ova će klasa biti jednonitna i blokirat će se do završetka:

javna klasa BlockingServlet proširuje HttpServlet {zaštićen void doGet (zahtjev HttpServletRequest, odgovor HttpServletResponse) baca ServletException, IOException {response.setContentType ("application / json"); response.setStatus (HttpServletResponse.SC_OK); response.getWriter (). println ("{\" status \ ": \" ok \ "}"); }}

Dalje, moramo registrirati BlockingServlet razred u ServletHandler objekt pomoću addServletWithMapping () metoda i pokrenite poslužitelj:

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

Ako želimo testirati našu Servlet logiku, trebamo pokrenuti naš poslužitelj pomoću prethodno stvorenih JettyServer klasa koja je omot stvarne instance poslužitelja Jetty unutar postavke testa:

@Prije javne void setup () baca iznimku {jettyServer = new JettyServer (); jettyServer.start (); }

Jednom kad započnemo, poslat ćemo testni HTTP zahtjev na /status krajnja točka:

URL niza = "// localhost: 8090 / status"; HttpClient klijent = HttpClientBuilder.create (). Build (); Zahtjev za HttpGet = novi HttpGet (url); HttpResponse odgovor = client.execute (zahtjev); assertThat (response.getStatusLine (). getStatusCode ()). isEqualTo (200);

4. Serbloti koji ne blokiraju

Jetty ima dobru podršku za asinkronu obradu zahtjeva.

Recimo da imamo ogroman resurs koji intenzivno ulaže / izlazi, a potrebno mu je dugo vremena kako bi se učitalo blokiranje izvršne niti u znatnom vremenu. Bolje je ako se ta nit u međuvremenu može osloboditi za obradu drugih zahtjeva, umjesto da se čeka neki I / O resurs.

Da bismo Jettyju pružili takvu logiku, možemo stvoriti servlet koji će koristiti AsyncContext razreda pozivom na startAsync () metoda na HttpServletRequest. Ovaj kôd neće blokirati izvršnu nit, već će izvršiti I / O operaciju u zasebnoj niti vraćajući rezultat kada bude spreman koristeći AsyncContext.complete () metoda:

javna klasa AsyncServlet proširuje HttpServlet {private static String HEAVY_RESOURCE = "Ovo je težak resurs koji će se služiti na asinkroni način"; zaštićeni void doGet (HttpServletRequest zahtjev, HttpServletResponse odgovor) baca ServletException, IOException {ByteBuffer content = ByteBuffer.wrap (HEAVY_RESOURCE.getBytes (StandardCharsets.UTF_8)); AsyncContext async = request.startAsync (); ServletOutputStream out = response.getOutputStream (); out.setWriteListener (new WriteListener () {@Override public void onWritePossible () baca 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 ();}}) ; }}

Pišemo ByteBuffer prema Izlazni tok, i nakon što je cijeli međuspremnik napisan, signaliziramo da je rezultat spreman za povratak klijentu pozivanjem dovršiti () metoda.

Dalje, moramo dodati AsyncServlet kao mapiranje servleta Jetty:

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

Sada možemo poslati zahtjev na / težak / asinkroniziran krajnja točka - taj će zahtjev Jetty obraditi na asinkroni način:

URL niza = "// localhost: 8090 / heavy / async"; HttpClient klijent = HttpClientBuilder.create (). Build (); Zahtjev za HttpGet = novi HttpGet (url); HttpResponse odgovor = client.execute (zahtjev); assertThat (response.getStatusLine (). getStatusCode ()) .isEqualTo (200); String responseContent = IOUtils.toString (r esponse.getEntity (). GetContent (), StandardCharsets.UTF_8); assertThat (responseContent) .isEqualTo ("Ovo je težak resurs koji će se služiti na asinkroni način");

Kada naša aplikacija obrađuje zahtjeve na asinkroni način, trebali bismo eksplicitno konfigurirati spremište niti. U sljedećem ćemo odjeljku konfigurirati Brana za upotrebu prilagođenog spremišta niti.

5. Konfiguracija mola

Kada pokrenemo našu web aplikaciju u produkciji, možda bismo željeli prilagoditi način na koji poslužitelj Jetty obrađuje zahtjeve. To se postiže definiranjem spremišta niti i primjenom na naš Jetty poslužitelj.

Da bismo to učinili, imamo tri konfiguracijske postavke koje možemo postaviti:

  • maxThreads - Za određivanje maksimalnog broja niti koje Jetty može stvoriti i koristiti u spremištu
  • minTreads - Da biste postavili početni broj niti u spremištu koje će Jetty koristiti
  • idleTimeout - Ova vrijednost u milisekundama definira koliko dugo nit može mirovati prije nego što se zaustavi i ukloni iz spremišta niti. Broj preostalih niti u spremištu nikada neće pasti ispod minNit postavljanje

Pomoću njih možemo konfigurirati ugrađeni Brana poslužitelju programski prosljeđujući konfigurirano spremište niti na Poslužitelj konstruktor:

int maxThreads = 100; int minThred = 10; int idleTimeout = 120; QueuedThreadPool threadPool = novi QueuedThreadPool (maxThreads, minThreads, idleTimeout); poslužitelj = novi poslužitelj (threadPool);

Zatim, kad pokrenemo naš poslužitelj, on će koristiti niti iz određenog spremišta niti.

6. Zaključak

U ovom smo brzom vodiču vidjeli kako integrirati ugrađene poslužitelje s Jettyjem i testirali našu web aplikaciju.

Kao i uvijek, kôd je dostupan na GitHub-u.