410 Stimmen

Einfacher HTTP-Server in Java, der nur die Java SE API verwendet

Gibt es eine Möglichkeit, einen sehr einfachen HTTP-Server (der nur GET/POST unterstützt) in Java zu erstellen, indem man nur die Java SE API verwendet, ohne Code zu schreiben, um HTTP-Anfragen manuell zu parsen und HTTP-Antworten manuell zu formatieren? Die Java SE API kapselt die HTTP-Client-Funktionalität sehr gut in HttpURLConnection aber gibt es ein Analogon für die HTTP-Server-Funktionalität?

Nur um das klarzustellen: Das Problem, das ich mit einer Menge von ServerSocket Die Beispiele, die ich online gesehen habe, zeigen, dass sie ihre eigene Anfrageanalyse/Antwortformatierung und Fehlerbehandlung durchführen, was mühsam, fehleranfällig und wahrscheinlich nicht umfassend ist, und aus diesen Gründen versuche ich, es zu vermeiden.

579voto

BalusC Punkte 1034465

Seit Java SE 6 gibt es einen eingebauten HTTP-Server in Sonne Oracle JRE. Der Name des Java 9-Moduls lautet jdk.httpserver . Die com.sun.net.httpserver Paketzusammenfassung gibt einen Überblick über die beteiligten Klassen und enthält Beispiele.

Hier ein Beispiel für einen Startschuss kopiert aus ihren Dokumenten. Sie können es einfach kopieren, einfügen und unter Java 6+ ausführen.
<em>(an alle, die versuchen, es trotzdem zu bearbeiten, weil es ein hässliches Stück Code ist, bitte nicht, das ist ein Copy Paste, nicht von mir, außerdem sollte man Zitate nie bearbeiten, es sei denn, sie haben sich in der Originalquelle geändert)</em>

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();
        }
    }

}

Es ist zu beachten, dass die response.length() Teil in ihrem Beispiel schlecht ist, hätte es sein müssen response.getBytes().length . Selbst dann ist die getBytes() Methode muss explizit den Zeichensatz angeben, den Sie dann in der Kopfzeile der Antwort angeben. Leider ist dies nur ein einfaches Beispiel für den Einstieg, auch wenn es für Anfänger irreführend ist.

Führen Sie es aus und gehen Sie auf http://localhost:8000/test. Sie erhalten dann folgende Antwort:

Dies ist die Antwort


Was die Verwendung com.sun.* Klassen, beachten Sie, dass dies, im Gegensatz zu dem, was einige Entwickler denken, absolut nicht durch die bekannte FAQ verboten ist Warum Entwickler keine Programme schreiben sollten, die 'sun'-Pakete aufrufen . Diese FAQ betrifft die sun.* Paket (wie z.B. sun.misc.BASE64Encoder ) für die interne Verwendung durch die Oracle JRE (die somit Ihre Anwendung beenden würde, wenn Sie sie unter einer anderen JRE ausführen), nicht die com.sun.* Paket. Sun/Oracle entwickeln auch selbst Software auf der Java SE API, wie jedes andere Unternehmen auch, wie z.B. Apache usw. Außerdem ist dieses spezielle HttpServer muss in jedem JDK vorhanden sein, so dass es absolut kein "Portabilitäts"-Problem gibt, wie es bei sun.* Paket. Verwendung von com.sun.* Klassen ist nur entmutigt (aber nicht Verbotene ), wenn es sich um eine Umsetzung einer bestimmten Java-API, wie z. B. GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), usw.

52voto

letronje Punkte 8683

Überprüfen Sie NanoHttpd

NanoHTTPD ist ein leichtgewichtiger HTTP-Server, der für die Einbettung in andere Anwendungen entwickelt wurde und unter einer modifizierten BSD-Lizenz veröffentlicht wird.

Es wird auf Github entwickelt und verwendet Apache Maven für Builds und Unit-Tests.

33voto

gruenewa Punkte 1608

En com.sun.net.httpserver Lösung ist nicht über JREs hinweg portierbar. Es ist besser, die offizielle Webservices-API in javax.xml.ws um einen minimalen HTTP-Server zu booten...

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: Das funktioniert tatsächlich! Der obige Code sieht aus wie Groovy oder so. Hier ist eine Übersetzung in Java, die ich getestet habe:

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);
    }
}

29voto

will Punkte 4398

Diese Frage gefällt mir, weil es sich hier um einen Bereich handelt, in dem es ständige Innovationen gibt und immer ein Bedarf an leichten Servern besteht, insbesondere wenn es um eingebettete Server in kleinen Geräten geht. Ich denke, die Antworten fallen in zwei große Gruppen.

  1. Thin-Server : Server-up statische Inhalte mit minimaler Verarbeitung, Kontext- oder Sitzungsverarbeitung.
  2. Kleiner Server : hat angeblich viele httpD-ähnliche Serverqualitäten mit so wenig Platzbedarf, wie man nur haben kann.

Ich könnte zwar HTTP-Bibliotheken wie: Steg , Apache-Http-Komponenten , Netty und andere, die eher einer rohen HTTP-Verarbeitungsanlage entsprechen. Die Einstufung ist sehr subjektiv und hängt davon ab, was man für kleine Websites zu leisten hat. Ich mache diese Unterscheidung im Sinne der Frage, insbesondere der Bemerkung über...

  • "...ohne Code zu schreiben, um HTTP-Anfragen manuell zu parsen und HTTP-Antworten manuell zu formatieren..."

Mit diesen Rohdaten können Sie das tun (wie in anderen Antworten beschrieben). Sie eignen sich nicht wirklich für die Herstellung eines leichten, eingebetteten oder Mini-Servers. Ein Mini-Server ist etwas, das Ihnen eine ähnliche Funktionalität wie ein vollwertiger Webserver bietet (z. B., Tomcat ) ohne Schnickschnack, geringe Lautstärke, gute Leistung in 99 % der Zeit. Ein Thin-Server scheint näher an der ursprünglichen Formulierung nur ein bisschen mehr als raw vielleicht mit einer begrenzten Teilmenge Funktionalität, genug, um Sie gut aussehen 90% der Zeit. Meine Vorstellung von "raw" wäre, dass ich in 75% bis 89% der Fälle gut aussehe, ohne zusätzliches Design und Kodierung. Ich denke, wenn man die Ebene der WAR-Dateien erreicht, haben wir das "small" für Bonsi-Server, die wie alles aussehen, was ein großer Server macht, kleiner gelassen.

Thin-Server-Optionen

Mini-Server-Optionen:

  • Spark Java ... Mit vielen Hilfskonstrukten wie Filtern, Schablonen usw. sind gute Dinge möglich.
  • MadVoc ... will Bonsai sein und könnte auch ein solcher sein ;-)

Zu den anderen Dingen, die zu berücksichtigen sind, gehören Authentifizierung, Validierung, Internationalisierung, die Verwendung von etwas wie FreeMaker oder ein anderes Vorlagenwerkzeug zum Rendern der Seitenausgabe. Andernfalls wird die Verwaltung der HTML-Bearbeitung und -Parametrisierung die Arbeit mit HTTP wahrscheinlich wie ein Kinderspiel erscheinen lassen. Es hängt natürlich alles davon ab, wie flexibel Sie sein müssen. Wenn es sich um ein menügesteuertes FAX-Gerät handelt, kann es sehr einfach sein. Je mehr Interaktionen, desto ' dicker ' muss Ihr Rahmen sein. Gute Frage, viel Glück!

24voto

James Anderson Punkte 26827

Schauen Sie sich den "Jetty"-Webserver an Steg . Ein hervorragendes Stück Open-Source-Software, das alle Ihre Anforderungen zu erfüllen scheint.

Wenn Sie darauf bestehen, Ihre eigene Klasse zu entwickeln, sollten Sie sich die Klasse "httpMessage" ansehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X