Útmutató a NanoHTTPD-hez
1. Bemutatkozás
A NanoHTTPD egy nyílt forráskódú, könnyű, Java-ban írt webszerver.
Ebben az oktatóanyagban létrehozunk néhány REST API-t a funkcióinak feltárására.
2. Projekt beállítása
Adjuk hozzá a NanoHTTPD magfüggőséget a sajátunkhoz pom.xml:
org.nanohttpd nanohttpd 2.3.1
Egy egyszerű szerver létrehozásához bővítenünk kell NanoHTTPD és felülírja annak szolgál módszer:
public class App kiterjeszti a NanoHTTPD-t {public App () dobja az IOException-t {super (8080); start (NanoHTTPD.SOCKET_READ_TIMEOUT, hamis); } public static void main (String [] érvel) dobja az IOException {new App (); } @Orride public Response serve (IHTTPSession session) {return newFixedLengthResponse ("Hello world"); }}
A futó portunkat úgy definiáltuk 8080 és a kiszolgáló démonként működik (nincs olvasási időtúllépés).
Amint elindítjuk az alkalmazást, az URL-t // localhost: 8080 / visszaadja a Helló Világ üzenet. Használjuk NanoHTTPD # newFixedLengthResponse módszer, mint kényelmes módszer a NanoHTTPD. Válasz tárgy.
Próbáljuk ki projektünket a cURL segítségével:
> curl '// localhost: 8080 /' Hello világ
3. REST API
A HTTP-módszerek módján a NanoHTTPD lehetővé teszi a GET, POST, PUT, DELETE, HEAD, TRACE és még sok más használatát.
Egyszerűen fogalmazva, a metóduson keresztül megtalálhatjuk a támogatott HTTP igéket. Lássuk, hogyan játszik ez.
3.1. HTTP GET
Először vessünk egy pillantást a GET-re. Mondjuk például, hogy csak akkor akarunk tartalmat visszaadni, ha az alkalmazás GET-kérést kap.
A Java Servlet tárolóktól eltérően nincsenek doGet rendelkezésre álló módszer - ehelyett csak ellenőrizzük az értéket a getMethod:
@Orride public Response serve (IHTTPSession session) {if (session.getMethod () == Method.GET) {String itemIdRequestParameter = session.getParameters (). Get ("itemId"). Get (0); return newFixedLengthResponse ("Required itemId =" + itemIdRequestParameter); } return newFixedLengthResponse (Response.Status.NOT_FOUND, MIME_PLAINTEXT, "A kért erőforrás nem létezik"); }
Ez nagyon egyszerű volt, igaz? Futtassunk egy gyors tesztet az új végpontunk összegöngyölésével, és nézzük meg, hogy a kérés paraméter tárgy azonosító helyesen olvasható:
> curl '// localhost: 8080 /? itemId = 23Bk8' Kért elemId = 23Bk8
3.2. HTTP POST
Korábban reagáltunk egy GET-re, és beolvastunk egy paramétert az URL-ből.
A két legnépszerűbb HTTP módszer lefedése érdekében itt az ideje, hogy kezeljük a POST-ot (és így elolvassuk a kérelem törzsét):
@Orride public Response serve (IHTTPSession session) {if (session.getMethod () == Method.POST) {try {session.parseBody (new HashMap ()); String requestBody = session.getQueryParameterString (); return newFixedLengthResponse ("Request body =" + requestBody); } catch (IOException | ResponseException e) {// handle}} return newFixedLengthResponse (Response.Status.NOT_FOUND, MIME_PLAINTEXT, "A kért erőforrás nem létezik"); }
Figyelje meg, hogy korábban, amikor a kérő szervet kértük, először hívtuk a parseBody módszer. Ennek oka az volt, hogy be akartuk tölteni a kéréstestet későbbi visszakeresés céljából. Egy testet felveszünk a testünkbe becsavar parancs:
> curl -X POST -d 'deliveryAddress = Washington nr 4 & mennyiség = 5 "// localhost: 8080 /' Request body = deliveryAddress = Washington nr 4 & mennyiség = 5
A fennmaradó HTTP módszerek nagyon hasonló jellegűek, ezért ezeket kihagyjuk.
4. Eredetközi erőforrás-megosztás
A CORS használatával engedélyezzük a tartományok közötti kommunikációt. A leggyakoribb használati eset egy másik tartományból érkező AJAX-hívások. Az első megközelítés, amelyet használhatunk, a CORS engedélyezése az összes API-nkon. Használni a –-corsok argumentummal engedélyezzük az összes domainhez való hozzáférést. Meghatározhatjuk azt is, hogy mely domainekkel engedjük meg –Cors = ”// irányítópult.myApp.com //admin.myapp.com” . A második megközelítés a CORS engedélyezése az egyes API-k számára. Lássuk, hogyan kell használni addHeader elérni ezt:@Orride public Response serve (IHTTPSession session) {Response response = newFixedLengthResponse ("Hello world"); response.addHeader ("Access-Control-Allow-Origin", "*"); visszatérési válasz; }
Most, amikor mi becsavar, visszakapjuk a CORS fejlécünket:
> curl -v '// localhost: 8080' HTTP / 1.1 200 OK Tartalomtípus: text / html Dátum: Csütörtök, 2019. június 13., 03:58:14 GMT Hozzáférés-vezérlés-Engedélyezés-eredet: * Kapcsolat: életben marad Tartalom-hossz: 11 Helló világ
5. Fájl feltöltés
A NanoHTTPD külön függ a fájlfeltöltéstől, ezért adjuk hozzá a projektünkhöz:
org.nanohttpd nanohttpd-apache-fileupload 2.3.1 javax.servlet javax.servlet-api 4.0.1 biztosított
Felhívjuk figyelmét, hogy a servlet-api függőségre is szükség van (különben fordítási hibát kapunk).
Amit a NanoHTTPD kitesz, az egy úgynevezett osztály NanoFileUpload:
@Orride public Response serve (IHTTPSession session) {try {List fájlok = új NanoFileUpload (új DiskFileItemFactory ()). ParseRequest (munkamenet); int feltöltöttSzám = 0; for (FileItem fájl: fájlok) {próbálkozzon a {String fileName = file.getName (); bájt [] fileContent = file.get (); Files.write (Útvonalak.get (fájlnév), fileContent); uploadedCount ++; } catch (kivétel kivétel) {// handle}} return newFixedLengthResponse (Response.Status.OK, MIME_PLAINTEXT, "Feltöltött fájlok" + uploadedCount + "a" + files.size () -ből "; } catch (IOException | FileUploadException e) {dobjon új IllegalArgumentException-t ("Nem sikerült kezelni a fájlokat az API kérésből", e); } return newFixedLengthResponse (Response.Status.BAD_REQUEST, MIME_PLAINTEXT, "Hiba feltöltéskor"); }
Hé, próbáljuk ki:
> curl -F '[email protected] /pathToFile.txt' '// localhost: 8080' Feltöltött fájlok: 1
6. Több útvonal
A nanolet olyan, mint egy servlet, de nagyon alacsony a profilja. Használhatjuk őket egyetlen szerver által kiszolgált útvonalak meghatározására (ellentétben a korábbi, egy útvonalra vonatkozó példákkal).Először tegyük hozzá a szükséges függőséget nanoletek:
org.nanohttpd nanohttpd-nanolets 2.3.1
És most kibővítjük főosztályunkat a RouterNanoHTTPD, definiálja a futó portunkat, és a szervert démonként futtassa.
A addMappings módszer az, ahol meghatározzuk kezelőinket:
public class MultipleRoutesExample kiterjeszti RouterNanoHTTPD {public MultipleRoutesExample () dobja az IOException {super (8080); addMappings (); start (NanoHTTPD.SOCKET_READ_TIMEOUT, hamis); } @Orride public void addMappings () {// az útvonalak kitöltésével}}
A következő lépés a sajátunk meghatározása addMappings módszer. Adjunk meg néhány kezelőt.
Az első egy IndexHandler osztály „/” útvonalra. Ez az osztály a NanoHTTPD könyvtárral érkezik, és alapértelmezés szerint visszatér a Helló Világ üzenet. Felülírhatjuk a getText módszer, ha más választ akarunk:
addRoute ("/", IndexHandler.class); // az addMappings módszer belsejében
Az új útvonal teszteléséhez pedig megtehetjük:
> curl '// localhost: 8080' Helló Világ!
Másodszor hozzunk létre egy újat UserHandler osztály, amely kiterjeszti a meglévő DefaultHandler. Az útvonal lesz /felhasználók. Itt játszottunk a szöveggel, a MIME típusával és a visszaadott állapotkóddal:
public static class UserHandler kiterjeszti a DefaultHandler {@Orride public String getText () {return "UserA, UserB, UserC"; } @Orride public String getMimeType () {return MIME_PLAINTEXT; } @Orride public Response.IStatus getStatus () {return Response.Status.OK; }}
Ennek az útvonalnak a hívásához kiadjuk a becsavar parancs ismét:
> curl -X POST '// localhost: 8080 / felhasználók' UserA, UserB, UserC
Végül felfedezhetjük a Handler tábornok egy új StoreHandler osztály. A visszaküldött üzenetet módosítottuk a storeId szakasz az URL-t.
public static class StoreHandler kiterjeszti a GeneralHandler {@Orride public Response get (UriResource uriResource, Map urlParams, IHTTPSession session) {return newFixedLengthResponse ("Retrieving store for id =" + urlParams.get ("storeId")); }}
Ellenőrizzük az új API-t:
> curl '// localhost: 8080 / stores / 123' Az id = 123 tárolójának lekérése
7. HTTPS
A HTTPS használatához igazolásra lesz szükségünk. Részletesebb információkért olvassa el az SSL-ről szóló cikkünket.
Használhatunk olyan szolgáltatást, mint a Titkosítás, vagy egyszerűen előállíthatunk egy önaláírt tanúsítványt az alábbiak szerint:
> keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048 -ext SAN = DNS: localhost, IP: 127.0.0.1 -validity 9999
Ezután ezt másoljuk kulcstár.jks osztályhelyünkre, például mondjuk a src / main / resources egy Maven-projekt mappája.
Ezt követően hivatkozhatunk rá egy hívásban NanoHTTPD # makeSSLSocketFactory:
a HttpsExample nyilvános osztály kiterjeszti a NanoHTTPD-t {public HttpsExample () dobja az IOException {super (8080); makeSecure (NanoHTTPD.makeSSLSocketFactory ("/keystore.jks", "jelszó" .toCharArray ()), null); start (NanoHTTPD.SOCKET_READ_TIMEOUT, hamis); } // fő és kiszolgáló módszerek}
És most kipróbálhatjuk. Kérjük, vegye figyelembe a -bizonytalan paraméter, mert becsavar alapértelmezés szerint nem tudja ellenőrizni az önaláírt tanúsítványunkat:
> curl --insecure '// localhost: 8443' A HTTPS hívás sikeres
8. WebSockets
A NanoHTTPD támogatja a WebSocketeket.
Készítsük el a WebSocket legegyszerűbb megvalósítását. Ehhez ki kell terjesztenünk a NanoWSD osztály. Hozzá kell adnunk a NanoHTTPD a WebSocket függősége:
org.nanohttpd nanohttpd-websocket 2.3.1
A megvalósításhoz csak egy egyszerű szöveges terheléssel válaszolunk:
a WsdExample nyilvános osztály kiterjeszti a NanoWSD-t {public WsdExample () dobja az IOException-t {super (8080); start (NanoHTTPD.SOCKET_READ_TIMEOUT, hamis); } public static void main (String [] args) dobja az IOException {new WsdExample (); } @Orride védett WebSocket openWebSocket (IHTTPSession ihttpSession) {return new WsdSocket (ihttpSession); } privát statikus osztály A WsdSocket kiterjeszti a WebSocket-t {public WsdSocket (IHTTPSession handshakeRequest) {super (handshakeRequest); } // felülírja az onOpen, onClose, onPong és onException módszereket } catch (IOException e) {// fogantyú}}}}
Ahelyett becsavar ezúttal használjuk wscat:
> wscat -c localhost: 8080 szia sziasztok viszlát viszlát
9. Következtetés
Összefoglalva, létrehoztunk egy projektet, amely a NanoHTTPD könyvtárat használja. Ezután meghatároztuk a RESTful API-kat és további HTTP-vel kapcsolatos funkciókat tártunk fel. Végül egy WebSocket-et is megvalósítottunk.
Ezeknek a kivonatoknak a megvalósítása elérhető a GitHubon.