semplice server HTTP in Java utilizzando solo l'API Java SE


333

Esiste un modo per creare un server HTTP di base (che supporta solo GET / POST) in Java utilizzando solo l'API Java SE, senza scrivere codice per analizzare manualmente le richieste HTTP e formattare manualmente le risposte HTTP? L'API Java SE incapsula perfettamente la funzionalità del client HTTP in HttpURLConnection, ma esiste un analogo per la funzionalità del server HTTP?

Per essere chiari, il problema che ho riscontrato con molti esempi di ServerSocket che ho visto online è che eseguono le proprie richieste di analisi / formattazione della risposta e gestione degli errori, che è noioso, soggetto a errori e probabilmente non completo, e sto cercando di evitarlo per questi motivi.

Come esempio della manipolazione HTTP manuale che sto cercando di evitare:

http://java.sun.com/developer/technicalArticles/Networking/Webserver/WebServercode.html


3
Umm ... la risposta breve è no. Se si desidera qualcosa che gestisca i post e riceva richieste senza scrivere manualmente le intestazioni http, è possibile utilizzare i servlet. Ma questo è java ee. Se non vuoi usare qualcosa del genere, le prese e l'analisi manuale sono l'unica altra opzione che conosco.
Matt Phillips,

3
So che questo non è nello spirito di SO, ma ti esorto a riconsiderare il tuo disgusto per le API Java EE. Come alcune delle risposte hanno menzionato, ci sono alcune implementazioni molto semplici come Jetty che ti permettono di incorporare un server web nella tua applicazione stand-alone pur sfruttando l'api servlet. Se non riesci assolutamente a utilizzare l'API Java EE per qualche motivo, ignora il mio commento :-)
Chris Thompson,

1
I "servlet" non sono in realtà "Java EE". Sono solo un modo per scrivere plugin che possono essere chiamati dall'applicazione circostante in risposta all'attività dei messaggi (oggigiorno, generalmente richieste HTTP). Fornire un ambiente di hosting servlet "usando solo l'API Java SE" è esattamente ciò che fanno Jetty e Tomcat. Naturalmente potresti voler eliminare complessità indesiderate, ma potresti dover decidere un sottoinsieme degli attributi e delle configurazioni consentite di GET / POST. Tuttavia, spesso non ne vale la pena, ad eccezione di speciali problemi di sicurezza / incorporati.
David Tonhofer,

1
Potrebbe valere la pena consultare questo elenco di server http prima di prendere una decisione. java-source.net/open-source/web-servers
ThreaT

Risposte:


469

Da Java SE 6, c'è un server HTTP integrato in Sun Oracle JRE. Il com.sun.net.httpserverriepilogo del pacchetto delinea le classi coinvolte e contiene esempi.

Ecco un esempio di kick-cop copiato dai loro documenti (a tutte le persone che cercano comunque di modificarlo, perché è un brutto pezzo di codice, per favore no, questa è una copia incolla, non la mia, inoltre non dovresti mai modificare le citazioni a meno che non siano cambiate nella fonte originale). Puoi semplicemente copiarlo e incollarlo su Java 6+.

package com.stackoverflow.q3732109;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class Test {

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
        server.createContext("/test", new MyHandler());
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

Notato che la response.length()parte nel loro esempio è cattiva, avrebbe dovuto essere response.getBytes().length. Anche in questo caso, il getBytes()metodo deve specificare esplicitamente il set di caratteri che si specifica quindi nell'intestazione della risposta. Ahimè, anche se fuorviante per i principianti, dopo tutto è solo un semplice esempio di calcio d'inizio.

Eseguilo e vai su http: // localhost: 8000 / test e vedrai la seguente risposta:

Questa è la risposta


Per quanto riguarda l'utilizzo delle com.sun.*classi, si noti che questo, contrariamente a quanto pensano alcuni sviluppatori, non è assolutamente vietato dalla nota FAQ Perché gli sviluppatori non dovrebbero scrivere programmi che chiamano pacchetti 'sun' . Quelle FAQ riguardano il sun.*pacchetto (come sun.misc.BASE64Encoder) per l'uso interno da parte di Oracle JRE (che quindi ucciderebbe l'applicazione quando la si esegue su un JRE diverso), non il com.sun.*pacchetto. Sun / Oracle sviluppano anche software sopra l'API Java SE come ogni altra azienda come Apache e così via. L'uso delle com.sun.*classi è scoraggiato (ma non proibito) quando riguarda l' implementazione di una determinata API Java, come GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), ecc.


19
@Waldheinz: come come @Software stai confondendo sun.*con com.sun.*. Ad esempio, vedi qualche documentazione sun.*dell'API? Guarda qui: java.sun.com/products/jdk/faq/faq-sun-packages.html Racconta qualcosa com.sun.*? Il com.sun.*è solo utilizzato per il proprio software di pubblico che non fa parte della API Java. Sviluppano anche software sull'API Java, come ogni altra azienda.
BalusC

4
penso che questo sia un server http molto bello da usare nei casi di test di integrazione. grazie per il suggerimento!
Andreas Petersson,

13
Se si utilizza Eclipse e si riceve un errore del tipo "Limitazione dell'accesso: il tipo HttpExchange non è accessibile a causa della restrizione sulla libreria richiesta ...", stackoverflow.com/a/10642163 indica come disabilitare tale controllo dell'accesso.
Samuli Pahaoja,

13
FWIW questo è presente anche in OpenJDK.
Jason C,

6
Le classi indicate qui sono contrassegnate @jdk.Exportednel codice sorgente OpenJDK, il che significa che l'API è considerata pubblica e sarà disponibile su Java 9 (alcuni altri com.sun.*pacchetti non saranno disponibili a causa di Project Jigsaw).
Jules il

42

Dai un'occhiata a NanoHttpd

"NanoHTTPD è un server HTTP leggero progettato per essere incorporato in altre applicazioni, rilasciato con una licenza BSD modificata.

È stato sviluppato presso Github e utilizza Apache Maven per build e unit test "


4
Un avvertimento: è probabile che NanoHTTPD non disponga di protezione contro gli attacchi agli alberi: dovresti verificarlo se verrà pubblicato su un indirizzo pubblico. Con questo intendo attacchi in cui GET /../../blahblah http/1.1viene emessa una richiesta simile e il server cammina sopra la radice del sito Web e entra nel file di sistema, offrendo file che possono essere utilizzati per compromettere o attaccare in remoto il sistema, come un file di password.
Lawrence Dol,

7
Sembra risolto. La versione corrente genera un 403 if (uri.startsWith ("..") || uri.endsWith ("..") || uri.indexOf ("../")> = 0).
Lena Schimmel,

5
Non capisco come questa sia una risposta a questa domanda.
Kimathie,

28

La soluzione com.sun.net.httpserver non è portatile su tutti i JRE. È meglio usare l'API dei servizi Web ufficiali in javax.xml.ws per avviare un server HTTP minimo ...

import java.io._
import javax.xml.ws._
import javax.xml.ws.http._
import javax.xml.transform._
import javax.xml.transform.stream._

@WebServiceProvider
@ServiceMode(value=Service.Mode.PAYLOAD) 
class P extends Provider[Source] {
  def invoke(source: Source) = new StreamSource( new StringReader("<p>Hello There!</p>"));
}

val address = "http://127.0.0.1:8080/"
Endpoint.create(HTTPBinding.HTTP_BINDING, new P()).publish(address)

println("Service running at "+address)
println("Type [CTRL]+[C] to quit!")

Thread.sleep(Long.MaxValue)

EDIT: questo funziona davvero! Il codice sopra sembra Groovy o qualcosa del genere. Ecco una traduzione in Java che ho testato:

import java.io.*;
import javax.xml.ws.*;
import javax.xml.ws.http.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

@WebServiceProvider
@ServiceMode(value = Service.Mode.PAYLOAD)
public class Server implements Provider<Source> {

    public Source invoke(Source request) {
        return  new StreamSource(new StringReader("<p>Hello There!</p>"));
    }

    public static void main(String[] args) throws InterruptedException {

        String address = "http://127.0.0.1:8080/";
        Endpoint.create(HTTPBinding.HTTP_BINDING, new Server()).publish(address);

        System.out.println("Service running at " + address);
        System.out.println("Type [CTRL]+[C] to quit!");

        Thread.sleep(Long.MAX_VALUE);
    }
}

1
+1 per essere portatile. Peccato che non sia possibile impostare il tipo di contenuto della risposta così com'è text/xml.
Icza,

1
Penso che potresti fare il <code> server di classe implementa il provider <DataSource> {</code> ... e quindi specificare il Content-Type all'interno del metodo <code> getContentType () </code> di DataSource. Inoltre puoi anche iniettare WebServiceContext: <code> @Resource WebServiceContext ctx; </code> per impostare altre intestazioni e leggere i parametri di richiesta. Purtroppo l'impostazione del tipo di contenuto tramite WebServiceContext non funziona.
Gruenewa,

4
Potresti spiegare perché com.sun.net.HttpServer non è portatile su JRE per favore?
javabeangrinder,

3
No, non la penso così. Non funzionerà sull'implementazione Java di IBM e forse anche su altri. E anche se funziona ora, le API interne possono cambiare. Perché non usare semplicemente l'API ufficiale?
Gruenewa,

1
Questo link: docs.oracle.com/javase/9/docs/api/java.xml.ws-summary.html afferma che il modulo java.xml.ws è obsoleto da Java 9.
Erel Segal-Halevi,

23

Mi piace questa domanda perché questa è un'area in cui c'è una continua innovazione e c'è sempre la necessità di avere un server leggero soprattutto quando si parla di server integrati in piccoli dispositivi (er). Penso che le risposte rientrino in due grandi gruppi.

  1. Thin server : contenuto statico su server con elaborazione minima, contesto o elaborazione di sessione.
  2. Piccolo server : apparentemente a ha molte qualità di server simili a httpD con il minimo ingombro possibile.

Mentre mi potrebbe prendere in considerazione HTTP librerie come: Molo , Apache Http Componenti , Netty e gli altri ad essere più simile a un prime impianti di trasformazione HTTP. L'etichettatura è molto soggettiva e dipende dal tipo di cose che sei stato invitato a fornire per piccoli siti. Faccio questa distinzione nello spirito della domanda, in particolare l'osservazione su ...

  • "... senza scrivere codice per analizzare manualmente le richieste HTTP e formattare manualmente le risposte HTTP ..."

Questi strumenti grezzi ti consentono di farlo (come descritto in altre risposte). Non si prestano davvero a uno stile pronto per la realizzazione di un server leggero, integrato o mini-server. Un mini-server è qualcosa che può darti funzionalità simili a un server web completo (come dire Tomcat ) senza campane e fischietti, basso volume, buone prestazioni il 99% delle volte. Un thin server sembra più vicino al fraseggio originale solo un po 'più che grezzo, forse con una funzionalità di sottoinsieme limitata, abbastanza per farti apparire bene il 90% delle volte. La mia idea di raw mi farebbe apparire bene il 75% - 89% delle volte senza design e codifica extra. Penso che se / quando si raggiunge il livello dei file WAR, abbiamo lasciato il "piccolo" per i server bonsi che assomiglia a tutto ciò che un server di grandi dimensioni fa più piccolo.

Opzioni thin server

Opzioni mini-server:

  • Spark Java ... Le cose buone sono possibili con molti costrutti di supporto come filtri, modelli, ecc.
  • MadVoc ... mira ad essere bonsai e potrebbe anche essere tale ;-)

Tra le altre cose da considerare, includerei l'autenticazione, la validazione, l'internazionalizzazione, usando qualcosa come FreeMaker o altri strumenti di template per rendere l'output della pagina. Altrimenti, è probabile che la gestione della modifica e della parametrizzazione HTML faccia sembrare il lavoro con HTTP come noughts-n-crosses. Naturalmente tutto dipende da quanto devi essere flessibile. Se si tratta di una macchina FAX basata su menu, può essere molto semplice. Più interazioni, più " spesso " deve essere il tuo framework. Buona domanda, buona fortuna!


21

Dai un'occhiata al web server "Jetty" Jetty . Superbo pezzo di software Open Source che sembrerebbe soddisfare tutti i tuoi requisiti.

Se insisti a fare il tuo, dai un'occhiata alla classe "httpMessage".


Penso che il molo api dipenda dal servlet.
irreversibile il

4
@Irreputable: No, Jetty è un server web altamente modulare, che ha un contenitore servlet come uno dei suoi moduli opzionali.
Lawrence Dol,

"è un analogo per la funzionalità server" - sì, è l'API "servlet". Il contenitore servlet chiama la tua classe dopo aver analizzato le intestazioni, i cookie ecc.
James Anderson,

1
Solo per la cronaca - Jetty arriva con la propria implementazione dell'API Servlet e funziona perfettamente con Java SE
James Anderson,

4
Jetty è troppo grande e presenta una curva di apprendimento eccessiva prima che l'effettivo utilizzo della produzione diventi una possibilità.
ThreaT

18

Una volta stavo cercando qualcosa di simile: un server HTTP leggero ma perfettamente funzionante che potessi facilmente incorporare e personalizzare. Ho trovato due tipi di potenziali soluzioni:

  • Server completi che non sono poi così leggeri o semplici (per un'estrema definizione di leggero).
  • Server veramente leggeri che non sono abbastanza server HTTP, ma esempi glorificati di ServerSocket che non sono nemmeno conformi a RFC in remoto e non supportano le funzionalità di base comunemente necessarie.

Quindi ... ho deciso di scrivere JLHTTP - Java Lightweight HTTP Server .

Puoi incorporarlo in qualsiasi progetto come un singolo file sorgente (se piuttosto lungo) o come un vaso ~ 50K (~ 35K rimosso) senza dipendenze. Si sforza di essere conforme a RFC e include un'ampia documentazione e molte funzioni utili, mantenendo al minimo il gonfiore.

Le caratteristiche includono: host virtuali, file che serve da disco, mappature del tipo mime tramite file mime.types standard, generazione dell'indice di directory, file di benvenuto, supporto per tutti i metodi HTTP, ETags condizionali e supporto dell'intestazione If- *, codifica di trasferimento in blocchi, gzip / deflate compressione, HTTPS di base (come fornito dalla JVM), contenuto parziale (continuazione del download), gestione multipart / form dei dati per upload di file, gestori di più contesti tramite API o annotazioni, analisi dei parametri (stringa di query o x-www-form-urlencoded corpo), ecc.

Spero che altri lo trovino utile :-)


Il metodo principale è un buon esempio di utilizzo di base e la FAQ include molti dettagli. Se hai suggerimenti per migliorare i documenti esistenti, non esitare a contattarmi direttamente!
Amichair,



8

È possibile creare un httpserver che fornisce supporto di base per servlet J2EE con solo JDK e API servlet in poche righe di codice.

L'ho trovato molto utile per i servlet di test delle unità, poiché inizia molto più velocemente di altri contenitori leggeri (utilizziamo il molo per la produzione).

La maggior parte degli httpserver molto leggeri non fornisce supporto per i servlet, ma ne abbiamo bisogno, quindi ho pensato di condividere.

L'esempio seguente fornisce il supporto servlet di base, oppure genera e UnsupportedOperationException per elementi non ancora implementati. Utilizza com.sun.net.httpserver.HttpServer per il supporto http di base.

import java.io.*;
import java.lang.reflect.*;
import java.net.InetSocketAddress;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

@SuppressWarnings("deprecation")
public class VerySimpleServletHttpServer {
    HttpServer server;
    private String contextPath;
    private HttpHandler httpHandler;

    public VerySimpleServletHttpServer(String contextPath, HttpServlet servlet) {
        this.contextPath = contextPath;
        httpHandler = new HttpHandlerWithServletSupport(servlet);
    }

    public void start(int port) throws IOException {
        InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
        server = HttpServer.create(inetSocketAddress, 0);
        server.createContext(contextPath, httpHandler);
        server.setExecutor(null);
        server.start();
    }

    public void stop(int secondsDelay) {
        server.stop(secondsDelay);
    }

    public int getServerPort() {
        return server.getAddress().getPort();
    }

}

final class HttpHandlerWithServletSupport implements HttpHandler {

    private HttpServlet servlet;

    private final class RequestWrapper extends HttpServletRequestWrapper {
        private final HttpExchange ex;
        private final Map<String, String[]> postData;
        private final ServletInputStream is;
        private final Map<String, Object> attributes = new HashMap<>();

        private RequestWrapper(HttpServletRequest request, HttpExchange ex, Map<String, String[]> postData, ServletInputStream is) {
            super(request);
            this.ex = ex;
            this.postData = postData;
            this.is = is;
        }

        @Override
        public String getHeader(String name) {
            return ex.getRequestHeaders().getFirst(name);
        }

        @Override
        public Enumeration<String> getHeaders(String name) {
            return new Vector<String>(ex.getRequestHeaders().get(name)).elements();
        }

        @Override
        public Enumeration<String> getHeaderNames() {
            return new Vector<String>(ex.getRequestHeaders().keySet()).elements();
        }

        @Override
        public Object getAttribute(String name) {
            return attributes.get(name);
        }

        @Override
        public void setAttribute(String name, Object o) {
            this.attributes.put(name, o);
        }

        @Override
        public Enumeration<String> getAttributeNames() {
            return new Vector<String>(attributes.keySet()).elements();
        }

        @Override
        public String getMethod() {
            return ex.getRequestMethod();
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            return is;
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }

        @Override
        public String getPathInfo() {
            return ex.getRequestURI().getPath();
        }

        @Override
        public String getParameter(String name) {
            String[] arr = postData.get(name);
            return arr != null ? (arr.length > 1 ? Arrays.toString(arr) : arr[0]) : null;
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return postData;
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return new Vector<String>(postData.keySet()).elements();
        }
    }

    private final class ResponseWrapper extends HttpServletResponseWrapper {
        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        final ServletOutputStream servletOutputStream = new ServletOutputStream() {

            @Override
            public void write(int b) throws IOException {
                outputStream.write(b);
            }
        };

        private final HttpExchange ex;
        private final PrintWriter printWriter;
        private int status = HttpServletResponse.SC_OK;

        private ResponseWrapper(HttpServletResponse response, HttpExchange ex) {
            super(response);
            this.ex = ex;
            printWriter = new PrintWriter(servletOutputStream);
        }

        @Override
        public void setContentType(String type) {
            ex.getResponseHeaders().add("Content-Type", type);
        }

        @Override
        public void setHeader(String name, String value) {
            ex.getResponseHeaders().add(name, value);
        }

        @Override
        public javax.servlet.ServletOutputStream getOutputStream() throws IOException {
            return servletOutputStream;
        }

        @Override
        public void setContentLength(int len) {
            ex.getResponseHeaders().add("Content-Length", len + "");
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public void sendError(int sc, String msg) throws IOException {
            this.status = sc;
            if (msg != null) {
                printWriter.write(msg);
            }
        }

        @Override
        public void sendError(int sc) throws IOException {
            sendError(sc, null);
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return printWriter;
        }

        public void complete() throws IOException {
            try {
                printWriter.flush();
                ex.sendResponseHeaders(status, outputStream.size());
                if (outputStream.size() > 0) {
                    ex.getResponseBody().write(outputStream.toByteArray());
                }
                ex.getResponseBody().flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                ex.close();
            }
        }
    }

    public HttpHandlerWithServletSupport(HttpServlet servlet) {
        this.servlet = servlet;
    }

    @SuppressWarnings("deprecation")
    @Override
    public void handle(final HttpExchange ex) throws IOException {
        byte[] inBytes = getBytes(ex.getRequestBody());
        ex.getRequestBody().close();
        final ByteArrayInputStream newInput = new ByteArrayInputStream(inBytes);
        final ServletInputStream is = new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return newInput.read();
            }
        };

        Map<String, String[]> parsePostData = new HashMap<>();

        try {
            parsePostData.putAll(HttpUtils.parseQueryString(ex.getRequestURI().getQuery()));

            // check if any postdata to parse
            parsePostData.putAll(HttpUtils.parsePostData(inBytes.length, is));
        } catch (IllegalArgumentException e) {
            // no postData - just reset inputstream
            newInput.reset();
        }
        final Map<String, String[]> postData = parsePostData;

        RequestWrapper req = new RequestWrapper(createUnimplementAdapter(HttpServletRequest.class), ex, postData, is);

        ResponseWrapper resp = new ResponseWrapper(createUnimplementAdapter(HttpServletResponse.class), ex);

        try {
            servlet.service(req, resp);
            resp.complete();
        } catch (ServletException e) {
            throw new IOException(e);
        }
    }

    private static byte[] getBytes(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        while (true) {
            int r = in.read(buffer);
            if (r == -1)
                break;
            out.write(buffer, 0, r);
        }
        return out.toByteArray();
    }

    @SuppressWarnings("unchecked")
    private static <T> T createUnimplementAdapter(Class<T> httpServletApi) {
        class UnimplementedHandler implements InvocationHandler {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                throw new UnsupportedOperationException("Not implemented: " + method + ", args=" + Arrays.toString(args));
            }
        }

        return (T) Proxy.newProxyInstance(UnimplementedHandler.class.getClassLoader(),
                new Class<?>[] { httpServletApi },
                new UnimplementedHandler());
    }
}

Mancano alcuni metodi su ServletOutputStream e ServletInputStream
HomeIsWhereThePcIs

versione più recente di servlet api, sopra per 3.0 e sotto. Basta aggiungere methdos mancanti secondo necessità nell'esempio
f.carlsen

6

Consiglio vivamente di esaminare Simple , specialmente se non hai bisogno delle funzionalità Servlet ma accedi semplicemente agli oggetti richiesta / risposta. Se hai bisogno di REST puoi mettere Jersey al di sopra di esso, se hai bisogno di produrre HTML o simili c'è Freemarker. Adoro davvero cosa puoi fare con questa combinazione e c'è relativamente poca API da imparare.


+1. Mi piacciono le idee alla base di Simple. Tuttavia, si verificano problemi quando si tenta di utilizzare HTTPS perché Mamba toglie la funzione "incorporabile" da Semplice.
ThreaT

6

Questo codice è migliore del nostro, devi solo aggiungere 2 librerie: javax.servelet.jar e org.mortbay.jetty.jar .

Molo di classe:

package jetty;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.mortbay.http.SocketListener;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHttpContext;

public class Jetty {

    public static void main(String[] args) {
        try {
            Server server = new Server();
            SocketListener listener = new SocketListener();      

            System.out.println("Max Thread :" + listener.getMaxThreads() + " Min Thread :" + listener.getMinThreads());

            listener.setHost("localhost");
            listener.setPort(8070);
            listener.setMinThreads(5);
            listener.setMaxThreads(250);
            server.addListener(listener);            

            ServletHttpContext context = (ServletHttpContext) server.getContext("/");
            context.addServlet("/MO", "jetty.HelloWorldServlet");

            server.start();
            server.join();

        /*//We will create our server running at http://localhost:8070
        Server server = new Server();
        server.addListener(":8070");

        //We will deploy our servlet to the server at the path '/'
        //it will be available at http://localhost:8070
        ServletHttpContext context = (ServletHttpContext) server.getContext("/");
        context.addServlet("/MO", "jetty.HelloWorldServlet");

        server.start();
        */

        } catch (Exception ex) {
            Logger.getLogger(Jetty.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
} 

Classe servlet:

package jetty;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorldServlet extends HttpServlet
{
    @Override
    protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
    {
        String appid = httpServletRequest.getParameter("appid");
        String conta = httpServletRequest.getParameter("conta");

        System.out.println("Appid : "+appid);
        System.out.println("Conta : "+conta);

        httpServletResponse.setContentType("text/plain");
        PrintWriter out = httpServletResponse.getWriter();
        out.println("Hello World!");
        out.close();
    }
}

2
La domanda richiede una soluzione puramente Java SE. Scoprirai che il molo implementa l'API Java EE.
Sridhar,

Jetty funziona perfettamente con Java SE standard e quindi soddisfa i requisiti. Esso implementa le parti della API Java EE, ma non hanno bisogno di esso. C'è una differenza.
David Tonhofer,

1
Questo non si qualifica. "usando solo l'API Java SE" . *.Servlet.jare *.jetty.jarovviamente non fanno parte di Java SE.
Icza,

devo installare il molo? o posso semplicemente escludere quei due vasetti ed eseguire questo file?
Paul Preibisch,


4

Tutti i dettagli delle risposte sopra riportati su Gestore richieste con thread principale singolo.

ambientazione:

 server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());

Consente la pubblicazione di richieste multiple tramite più thread tramite il servizio di esecuzione.

Quindi il codice finale sarà simile al seguente:

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class App {
    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
        server.createContext("/test", new MyHandler());
        //Thread control is given to executor service.
        server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
        server.start();
    }
    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            long threadId = Thread.currentThread().getId();
            System.out.println("I am thread " + threadId );
            response = response + "Thread Id = "+threadId;
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }
}

3

checkout Semplice . è un server embeddable piuttosto semplice con supporto integrato per una varietà di operazioni. Mi piace particolarmente il suo modello di threading ..

Sorprendente!



2

Che ne dici del progetto HttpCore di Apache Commons ?

Dal sito web: ... HttpCore Goals

  • Implementazione degli aspetti fondamentali del trasporto HTTP
  • Equilibrio tra buone prestazioni e chiarezza ed espressività dell'API
  • Ingombro di memoria ridotto (prevedibile)
  • Libreria autonoma (nessuna dipendenza esterna oltre JRE)

Questo è probabilmente di livello troppo basso. Uno dovrebbe almeno mirare a una soluzione che chiama il tuo codice a livello di API servlet, a meno che non si desideri affrontare da soli tutti i concetti come chunking, codifica ecc. Può essere divertente però.
David Tonhofer,

2

Prova questo https://github.com/devashish234073/Java-Socket-Http-Server/blob/master/README.md

Questa API ha creato un server HTTP utilizzando i socket.

  1. Riceve una richiesta dal browser come testo
  2. Analizza per recuperare informazioni URL, metodo, attributi, ecc.
  3. Crea una risposta dinamica usando la mappatura URL definita
  4. Invia la risposta al browser.

Ad esempio, ecco come il costruttore nella Response.javaclasse converte una risposta non elaborata in una risposta http:

public Response(String resp){
    Date date = new Date();
    String start = "HTTP/1.1 200 OK\r\n";
    String header = "Date: "+date.toString()+"\r\n";
    header+= "Content-Type: text/html\r\n";
    header+= "Content-length: "+resp.length()+"\r\n";
    header+="\r\n";
    this.resp=start+header+resp;
}

1

È possibile scrivere un server Java Jetty incorporato piuttosto semplice .

Embedded Jetty significa che il server (Jetty) è stato spedito insieme all'applicazione anziché distribuire l'applicazione su un server Jetty esterno.

Quindi se nell'approccio non incorporato la tua webapp è incorporata nel file WAR che è stato distribuito su un server esterno ( Tomcat / Jetty / ecc.), Nel molo incorporato, scrivi la webapp e crea un'istanza del server jetty nella stessa base di codice.

Un esempio per il server Java Jetty incorporato è possibile eseguire il clone e utilizzare: https://github.com/stas-slu/embedded-jetty-java-server-example

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.