Servidor HTTP simple en Java usando solo la API Java SE

Resuelto asker asked hace 14 años • 0 respuestas

¿Existe alguna manera de crear un servidor HTTP muy básico (que solo admita GET/POST) en Java usando solo la API de Java SE, sin escribir código para analizar manualmente las solicitudes HTTP y formatear manualmente las respuestas HTTP? La API de Java SE encapsula muy bien la funcionalidad del cliente HTTP en HttpURLConnection, pero ¿existe un análogo para la funcionalidad del servidor HTTP?

Para que quede claro, el problema que tengo con muchos ServerSocketejemplos que he visto en línea es que realizan su propio análisis de solicitudes/formateo de respuestas y manejo de errores, lo cual es tedioso, propenso a errores y probablemente no sea completo, y Estoy tratando de evitarlo por esas razones.

asker avatar Sep 17 '10 08:09 asker
Aceptado

Desde Java SE 6, hay un servidor HTTP integrado en Sun Oracle JRE. El nombre del módulo Java 9 es jdk.httpserver. El com.sun.net.httpserverresumen del paquete describe las clases involucradas y contiene ejemplos.

Aquí hay un ejemplo inicial copiado de sus documentos. Puede simplemente copiarlo, pegarlo y ejecutarlo en Java 6+.
(a todas las personas que intentan editarlo de todos modos, porque es un código feo, por favor no lo hagan, esto es copiar y pegar, no mío; además, nunca deben editar las citas a menos que hayan cambiado en la fuente original)

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

}

Cabe señalar que la response.length()parte de su ejemplo es mala, debería haberlo sido response.getBytes().length. Incluso entonces, el getBytes()método debe especificar explícitamente el juego de caracteres que luego especificará en el encabezado de respuesta. Desgraciadamente, aunque resulte engañoso para los principiantes, al fin y al cabo es sólo un ejemplo básico de saque inicial.

Ejecútelo y vaya a http://localhost:8000/test y verá la siguiente respuesta:

esta es la respuesta


En cuanto al uso de com.sun.*clases, tenga en cuenta que, al contrario de lo que piensan algunos desarrolladores, esto no está prohibido en absoluto en las conocidas preguntas frecuentes sobre por qué los desarrolladores no deberían escribir programas que llamen paquetes 'sun' . Esas preguntas frecuentes se refieren al sun.*paquete (como sun.misc.BASE64Encoder) para uso interno de Oracle JRE (lo que, por lo tanto, eliminaría su aplicación cuando la ejecute en un JRE diferente), no al com.sun.*paquete. Sun/Oracle también desarrolla software además de la API de Java SE, como cualquier otra empresa, como Apache, etc. Además, esto específico HttpServerdebe estar presente en cada JDK, por lo que no existe ningún problema de "portabilidad" como sucedería con sun.*el paquete. com.sun.*Solo se desaconseja (pero no se prohíbe ) el uso de clases cuando se trata de una implementación de una determinada API de Java, como GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), etc.

BalusC avatar Sep 17 '2010 02:09 BalusC

Echa un vistazo a NanoHttpd

NanoHTTPD es un servidor HTTP liviano diseñado para integrarse en otras aplicaciones, lanzado bajo una licencia BSD modificada.

Se está desarrollando en Github y utiliza Apache Maven para compilaciones y pruebas unitarias".

letronje avatar Sep 17 '2010 02:09 letronje

La solución com.sun.net.httpserver no es portátil entre JRE. Es mejor utilizar la API de servicios web oficial en javax.xml.ws para iniciar un servidor HTTP mínimo...

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)

EDITAR: ¡esto realmente funciona! El código anterior se parece a Groovy o algo así. Aquí hay una traducción a Java que probé:

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);
    }
}
gruenewa avatar Jun 08 '2014 07:06 gruenewa

Me gusta esta pregunta porque es un área donde hay innovación continua y siempre es necesario tener un servidor liviano, especialmente cuando se habla de servidores integrados en dispositivos más pequeños. Creo que las respuestas se dividen en dos grandes grupos.

  1. Servidor ligero : servidor de contenido estático con procesamiento mínimo, contexto o procesamiento de sesión.
  2. Servidor pequeño : aparentemente tiene muchas cualidades de servidor similares a httpD con el tamaño más pequeño posible.

Si bien podría considerar que las bibliotecas HTTP como: Jetty , Apache Http Components , Netty y otras se parecen más a instalaciones de procesamiento HTTP sin formato. El etiquetado es muy subjetivo y depende del tipo de cosas que se le ha pedido que entregue para sitios pequeños. Hago esta distinción en el espíritu de la pregunta, particularmente la observación sobre...

  • "...sin escribir código para analizar manualmente las solicitudes HTTP y formatear manualmente las respuestas HTTP..."

Estas herramientas sin procesar le permiten hacer eso (como se describe en otras respuestas). Realmente no se prestan a un estilo listo para usar de hacer un servidor liviano, integrado o mini. Un miniservidor es algo que puede brindarle una funcionalidad similar a un servidor web con todas las funciones (como, por ejemplo, Tomcat ) sin campanas ni silbidos, bajo volumen y buen rendimiento el 99% del tiempo. Un servidor delgado parece más cercano a la redacción original, solo un poco más que sin formato, tal vez con un subconjunto de funcionalidades limitado, suficiente para hacerte lucir bien el 90% del tiempo. Mi idea de raw sería hacerme lucir bien entre el 75% y el 89% del tiempo sin diseño ni codificación adicionales. Creo que si alcanzas el nivel de archivos WAR, hemos dejado el "pequeño" para los servidores bonsi que parecen todo lo que hace un servidor grande, más pequeño.

Opciones de servidor delgado

  • Oso pardo
  • UniRest (varios idiomas)
  • NanoHTTPD (solo un archivo)

Opciones de miniservidor:

  • Spark Java ... Es posible hacer cosas buenas con muchas construcciones auxiliares como filtros, plantillas, etc.
  • MadVoc ... pretende ser bonsái y bien podría serlo ;-)

Entre otras cosas a considerar, incluiría autenticación, validación, internacionalización y uso de algo como FreeMaker u otra herramienta de plantilla para representar la salida de la página. De lo contrario, es probable que la gestión de la edición y parametrización de HTML haga que trabajar con HTTP parezca una tontería. Naturalmente, todo depende de lo flexible que tengas que ser. Si se trata de una máquina de FAX basada en menús, puede ser muy sencillo. Cuantas más interacciones, más " grueso " debe ser su marco. ¡Buena pregunta, buena suerte!

will avatar Sep 04 '2014 15:09 will

Eche un vistazo al servidor web "Jetty" Jetty . Excelente pieza de software de código abierto que parece cumplir con todos sus requisitos.

Si insistes en crear el tuyo propio, echa un vistazo a la clase "httpMessage".

James Anderson avatar Sep 17 '2010 01:09 James Anderson