serveur HTTP simple en Java utilisant uniquement L'API Java SE

y a-t-il un moyen de créer un serveur HTTP très basique (supportant seulement GET/POST) en Java en utilisant uniquement L'API Java SE, sans écrire de code pour analyser manuellement les requêtes HTTP et formater manuellement les réponses HTTP? L'API Java SE encapsule bien les fonctionnalités du client HTTP dans HttpURLConnection, mais y a-t-il une fonctionnalité analogue pour le serveur HTTP?

juste pour être clair, le problème que j'ai avec beaucoup D'exemples de ServerSocket que j'ai vu en ligne est qu'ils font leur propre analyse de la demande / formatage de la réponse et la gestion des erreurs, ce qui est fastidieux, sujet aux erreurs, et peu susceptible d'être complet, et j'essaie de l'éviter pour ces raisons.

comme exemple de manipulation HTTP manuelle que j'essaie d'éviter:

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

273
demandé sur BalusC 2010-09-17 05:29:04

17 réponses

depuis Java SE 6, Il y a un serveur HTTP intégré dans Sun Oracle JRE. Le com.sun.net.httpserver sommaire du paquet décrit les classes concernées et contient des exemples.

voici un exemple de coup d'envoi copypasted à partir de leurs docs, vous pouvez simplement copier ' past'n'run it sur 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();
        }
    }

}

devrait être noté que la partie response.length() dans leur exemple est mauvais, il ça aurait dû être response.getBytes().length . Même alors, la méthode getBytes() doit explicitement spécifier le jeu de caractères que vous spécifiez alors dans l'en-tête de réponse. Hélas, même si c'est un mauvais début, ce n'est après tout qu'un exemple élémentaire de coup d'envoi.

exécutez-le et passez à http://localhost:8000/test et vous verrez la réponse suivante:

C'est la réponse


quant à l'utilisation des classes com.sun.* , notez que, contrairement à ce que pensent certains développeurs, ce N'est absolument pas interdit par la FAQ bien connue pourquoi les développeurs ne devraient pas écrire des programmes qui appellent " sun "paquets . Cette FAQ concerne le paquet sun.* (tel que sun.misc.BASE64Encoder ) pour usage interne par L'Oracle JRE (qui tuerait donc votre application lorsque vous l'exécutez sur un JRE différent), pas le paquet com.sun.* . Sun / Oracle aussi il suffit de développer des logiciels sur L'API Java SE eux-mêmes comme toutes les autres entreprises comme Apache et ainsi de suite. L'utilisation des classes com.sun.* n'est découragée (mais pas interdite) que lorsqu'il s'agit d'une implémentation d'une certaine API Java, telle que GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), etc.

401
répondu BalusC 2017-10-19 06:58:46

Check out NanoHttpd

" NanoHTTPD est un serveur HTTP léger conçu pour être intégré à d'autres applications, publié sous licence BSD modifiée.

il est développé chez Github et utilise Apache Maven pour les tests de construction et d'unité "

41
répondu letronje 2017-01-03 16:04:44

the com.sun.net.httpserver solution n'est pas portable à travers JREs. Il est préférable d'utiliser l'API webservices officielle dans javax.xml.ws pour démarrer un serveur HTTP minimal...

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: cela fonctionne réellement! Le code ci-dessus ressemble à Groovy ou quelque chose. Voici une traduction en Java que j'ai testé:

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);
    }
}
25
répondu gruenewa 2014-07-07 13:30:53

Avoir un coup d'oeil à la "Jetée" serveur web Jetée . Superbe pièce de logiciel libre qui semblerait répondre à tous vos besoins.

si vous insistez pour rouler le vôtre, regardez la classe "httpMessage".

19
répondu James Anderson 2015-07-23 13:11:38

j'aime cette question parce qu'il s'agit d'un domaine où il y a une innovation continue et il y a toujours un besoin d'avoir un serveur léger surtout quand on parle de serveurs intégrés dans les petits(er) appareils. Je pense que les réponses se divisent en deux grands groupes.

  1. Thin-server : contenu statique avec un traitement minimal du traitement, du contexte ou de la session.
  2. Petit serveur : apparemment un possède de nombreuses qualités de serveur de type httpD avec une empreinte aussi faible que possible.

alors que je pourrais considérer les bibliothèques HTTP comme: Jetty , Apache composants Http , Netty et d'autres pour être plus comme une installation de traitement HTTP brute. L'étiquetage est très subjectif, et dépend du genre de chose que vous avez été d'appeler à offrir pour les petits sites. Je fais cette distinction dans l'esprit de la question, en particulier la remarque...

  • "...sans code d'écriture pour analyser manuellement les requêtes HTTP et formater manuellement les réponses HTTP..."

ces outils bruts vous permettent de le faire (comme décrit dans d'autres réponses). Ils ne se prêtent pas vraiment à un style prêt à l'emploi consistant à faire une lumière, un embedded ou un mini-serveur. Un mini-serveur est quelque chose qui peut vous donner des fonctionnalités similaires à une fonction complète serveur web (comme say, Tomcat ) sans cloches et sifflets, faible volume, bonne performance 99% du temps. Un serveur fin semble plus proche du phrasé original juste un peu plus que brut peut-être avec une fonctionnalité de sous-ensemble limitée, assez pour vous faire bien paraître 90% du temps. Mon idée de raw serait me rend bonne 75% - 89% du temps sans conception supplémentaire et de codage. Je pense que si/quand vous atteignez le niveau des fichiers de guerre, nous avons laissé le" petit " pour les serveurs bonsi qui ressemble tout à un gros serveur n'est plus petit.

"151900920 Minces" options du serveur

Mini-options du serveur:

  • Étincelle De Java ... De bonnes choses sont possible avec beaucoup de constructions helper comme des filtres, des gabarits,etc.
  • MadVoc ... objectifs être bonsai et pourrait bien être tel; -)

parmi les autres choses à considérer, je voudrais inclure l'authentification, la validation, l'internationalisation, en utilisant quelque chose comme FreeMaker ou un autre outil de modèle pour rendre la sortie de page. Sinon, la gestion de l'édition et du paramétrage HTML est susceptible de faire travailler avec HTTP ressemble à des noughts-n-croix. Naturellement, tout dépend de la souplesse dont vous avez besoin. S'il s'agit d'un télécopieur à menu, cela peut être très simple. Le plus d'interactions, le ' plus épais ' votre cadre doit être. Bonne question, bonne chance!

16
répondu will 2014-09-04 15:05:18

il était une fois que je cherchais quelque chose de similaire - un serveur HTTP léger mais entièrement fonctionnel que je pouvais facilement intégrer et personnaliser. J'ai trouvé deux types de solutions possibles:

  • serveurs complets qui ne sont pas que légers ou simples (pour une définition extrême de léger.)
  • serveurs vraiment légers qui ne sont pas tout à fait des serveurs HTTP, mais des exemples de ServerSocket glorifiés qui ne sont même pas à distance Conforme à la RFC et ne prend pas en charge les fonctionnalités de base généralement nécessaires.

So... J'ai entrepris d'écrire JLHTTP - le Java Lightweight HTTP Server .

vous pouvez l'intégrer dans n'importe quel projet en tant que fichier source unique (si assez long), ou en tant que Jarre ~50K (~35K dépouillé) sans dépendances. Il s'efforce d'être conforme à la RFC et comprend une vaste documentation et de nombreuses fonctionnalités utiles tout en gardant bloat au minimum.

caractéristiques comprennent: hôtes virtuels, fichier servant à partir du disque, mime type mappings via mime standard.types de fichiers, génération d'index de répertoires, fichiers de bienvenue, prise en charge de toutes les méthodes HTTP, ETags conditionnels et prise en charge de l'en-tête If -*, encodage de transfert fractionné, compression gzip/deflate, HTTPS de base (tel que fourni par la JVM), contenu partiel (suite du téléchargement), gestion de données multipart/form pour les téléchargements de fichiers, gestionnaires de contexte multiples via API ou annotations, parsing de paramètres (chaîne de requête) ou x-www-form-urlencoded corps), etc.

j'espère que d'autres le trouvent utile :-)

12
répondu amichair 2018-06-01 08:43:45
8
répondu Nikos 2014-01-18 22:47:28

Spark est le plus simple, voici un guide de démarrage rapide: http://sparkjava.com/

8
répondu Laercio Metzner 2015-06-22 12:32:46

il est possible de créer un serveur HTTPS qui fournit un support de base pour les servlets J2EE avec juste le JDK et l'api servlet dans quelques lignes de code.

j'ai trouvé cela très utile pour tester des servlets d'unité, car il démarre beaucoup plus vite que d'autres conteneurs légers (nous utilisons jetty pour la production).

la plupart des serveurs HTTPS très légers ne fournissent pas de support pour les servlets, mais nous en avons besoin, donc j'ai pensé que je partagerais.

l'exemple ci-dessous fournit un support de servlet de base, ou unsupportedoperationexception pour des choses qui n'ont pas encore été implémentées. Il utilise le com.sun.net.httpserver.HttpServer pour le support http de 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());
    }
}
7
répondu f.carlsen 2013-11-28 08:55:50

je peux fortement recommander de regarder dans Simple , surtout si vous n'avez pas besoin des capacités Servlet mais simplement l'accès aux objets request/reponse. Si vous avez besoin de repos, vous pouvez mettre Jersey sur le dessus de celui-ci, si vous avez besoin de sortie HTML ou similaire, Il ya Freemarker. J'aime vraiment ce que vous pouvez faire avec cette combinaison, et il y a relativement peu D'API à apprendre.

6
répondu Waldheinz 2010-09-17 18:29:40

vous pouvez également jeter un coup d'oeil à un cadre d'application du BNI tel que:

  1. Netty: http://jboss.org/netty
  2. Apache Mina: http://mina.apache.org / ou son sous-projet AsyncWeb: http://mina.apache.org/asyncweb /
5
répondu ThiamTeck 2010-09-18 12:04:57

ce code est meilleur que le nôtre, il vous suffit d'ajouter 2 libs: javax.servelet.jar et org.mortbay.jetée.jar .

Classe Jetée:

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();
    }
}
5
répondu leandro 2012-09-21 10:35:00

checkout Simple . son assez simple intégrable server avec support intégré pour toute une variété d'opérations. J'aime particulièrement son modèle de thread..

incroyable!

3
répondu Olu 2015-07-15 10:43:57

Check out takes . Regardez https://github.com/yegor256/takes pour info rapide

3
répondu George 2015-10-15 14:20:38

Que pensez-vous du projet Apache Commons HttpCore ?

à Partir du site web:... HttpCore Goals

  • la mise en Œuvre de la plupart des fondamentaux du transport HTTP aspects
  • équilibre entre la bonne performance et la clarté et l'expressivité de API
  • petite empreinte mémoire (prévisible)
  • bibliothèque autonome (pas de dépendances externes au-delà de JRE)
2
répondu I. Joseph 2013-02-11 21:52:42

vous pouvez écrire un assez simple embedded Jetty serveur Java.

Jetty embarquée signifie que le serveur (Jetty) expédié avec l'application au lieu de déployer l'application sur le serveur externe Jetty.

donc si dans l'approche non-embedded votre webapp intégré dans le fichier de guerre qui s'est déployé sur un serveur externe ( Tomcat / Jetty / etc), dans Jetty embedded, vous écrivez le webapp et instanciez le serveur jetty dans la même base de code.

un exemple de serveur Java Jetty intégré vous pouvez clone git et utiliser: https://github.com/stas-slu/embedded-jetty-java-server-example

0
répondu Stas 2017-06-29 11:14:44

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

cette api a créé un serveur http utilisant des sockets. Détail:

1.Il reçoit la demande du navigateur sous forme de texte

2.Le Parse pour récupérer l'information d'url, la méthode ,les attributs, etc.

3.Crée une réponse dynamique en utilisant la cartographie d'url définie

4.Envoie la réponse pour navigateur.

Par exemple, voici comment le constructeur dans la "Réponse.la classe java convertit une réponse brute en réponse http:



la Réaction du public(Chaîne de reee){

Date date = new Date();

String start =" HTTP / 1.1 200 OK\r\n";

en-tête de chaîne de caractères = "Date:" +date.toString ()+"\r\n";

en-tête+ = " Content-Type: text / html\r\n";

en-tête+= "Content-length: "+resp.longueur ()+"\r\n";

en-tête+="\r\n";

.resp=lance+tête+resp;

}

0
répondu Devashish Priyadarshi 2018-05-25 19:19:44