que gui definicion java http httpserver

gui - servidor HTTP simple en Java usando solo API de Java SE



java http server (18)

¿Hay una manera de crear un servidor HTTP muy básico (que admita solo 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 ejemplos de ServerSocket que he visto en línea es que realizan su propio proceso de análisis / respuesta de solicitudes y manejo de errores, lo cual es tedioso, propenso a errores y no es probable que sea completo. Y estoy tratando de evitarlo por esas razones.

Como ejemplo de la manipulación HTTP manual que estoy tratando de evitar:

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


¿Qué HttpCore proyecto Apache Commons HttpCore ?

Desde el sitio web: ... HttpCore Goals

  • Implementación de los aspectos de transporte HTTP más fundamentales.
  • Equilibrio entre el buen rendimiento y la claridad y expresividad de la API
  • Huella de memoria pequeña (predecible)
  • Biblioteca autónoma (sin dependencias externas más allá de JRE)

Echa un vistazo a NanoHttpd

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

Se está desarrollando en Github y utiliza Apache Maven para las pruebas de construcción y unidades "



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

Si insiste en hacer rodar el suyo propio, eche un vistazo a la clase "httpMessage".


Es posible crear un httpserver que brinde soporte básico para los servlets J2EE con solo el JDK y la api del servlet en unas pocas líneas de código.

He encontrado esto muy útil para los servlets de prueba unitaria, ya que comienza mucho más rápido que otros contenedores livianos (usamos Jetty para la producción).

La mayoría de los httpservers muy ligeros no ofrecen soporte para servlets, pero los necesitamos, así que pensé que los compartiría.

El siguiente ejemplo proporciona soporte básico de servlet, o lanza y UnsupportedOperationException para cosas que aún no están implementadas. Utiliza el com.sun.net.httpserver.HttpServer para soporte básico de http.

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


Este código es mejor que el nuestro, solo necesita agregar 2 libs: javax.servelet.jar y org.mortbay.jetty.jar .

Clase embarcadero:

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

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


Hace mucho tiempo buscaba algo similar: un servidor HTTP ligero pero completamente funcional que pudiera integrar y personalizar fácilmente. Encontré dos tipos de soluciones potenciales:

  • Servidores completos que no son tan ligeros o simples (para una definición extrema de peso ligero).
  • Servidores realmente ligeros que no son servidores HTTP, pero ejemplos glorificados de ServerSocket que ni siquiera son compatibles de forma remota con RFC y no son compatibles con la funcionalidad básica más necesaria.

Entonces ... me propuse escribir JLHTTP - El servidor HTTP ligero de Java .

Puede incrustarlo en cualquier proyecto como un único archivo fuente (si es bastante largo), o como un jar de ~ 50K (~ 35K eliminado) sin dependencias. Se esfuerza por ser compatible con RFC e incluye documentación extensa y muchas características útiles, al mismo tiempo que reduce la cantidad al mínimo.

Las características incluyen: hosts virtuales, servicio de archivos desde el disco, mapeos de tipo mime a través del archivo mime.types estándar, generación de índices de directorio, archivos de bienvenida, soporte para todos los métodos HTTP, ETags condicionales y soporte de encabezado If- *, codificación de transferencia fragmentada, gzip / deflate Compresión, HTTPS básico (según lo proporciona la JVM), contenido parcial (continuación de la descarga), manejo de datos de múltiples partes / formularios para cargas de archivos, manejadores de múltiples contextos mediante API o anotaciones, análisis de parámetros (cadena de consulta o x-www-form-urlencoded) cuerpo), etc.

Espero que a otros les resulte útil :-)


La solución com.sun.net.httpserver no es portátil en todos los JRE. Es mejor usar la API de servicios web oficial en javax.xml.ws para arrancar 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)

EDIT: esto realmente funciona! El código anterior se parece a Groovy o algo así. Aquí hay una traducción a Java que he probado:

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


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

  1. Servidor ligero : contenido estático de servidor arriba con procesamiento mínimo, contexto o procesamiento de sesión.
  2. Servidor pequeño : aparentemente un servidor tiene muchas cualidades de servidor de tipo httpD con una huella tan pequeña como usted puede salirse con la suya.

Si bien podría considerar que las bibliotecas HTTP como: Jetty , Apache Http Components , Netty y otros se parecen más a las instalaciones de procesamiento HTTP en bruto. El etiquetado es muy subjetivo y depende de los tipos de cosas a las que se le haya pedido que envíen para sitios pequeños. Hago esta distinción en el espíritu de la pregunta, particularmente el comentario sobre ...

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

Estas herramientas en bruto le permiten hacer eso (como se describe en otras respuestas). Realmente no se prestan a un estilo listo para usar para hacer un mini servidor ligero o integrado. Un mini servidor es algo que le puede dar una funcionalidad similar a un servidor web con todas las funciones (por ejemplo, Tomcat ) sin alarmas, bajo volumen, buen rendimiento el 99% del tiempo. Un servidor delgado parece estar más cerca de las frases originales solo un poco más que sin formato, quizás con una funcionalidad limitada de subconjunto, lo suficiente para hacer que se vea bien el 90% del tiempo. Mi idea de lo crudo sería que me viera bien 75% - 89% del tiempo sin diseño y codificación adicionales. Creo que si / cuando alcanzas el nivel de los archivos WAR, hemos dejado el "pequeño" para los servidores bonsi que se parece a todo lo que un servidor grande hace más pequeño.

Opciones de servidor delgado

Opciones de miniservidor:

  • Spark Java ... Las cosas buenas son posibles con muchas construcciones de ayuda como filtros, plantillas, etc.
  • MadVoc ... aspira a ser bonsai y podría serlo ;-)

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


Pago Simple . es un servidor integrable bastante simple con soporte incorporado para una gran variedad de operaciones. Particularmente me encanta su modelo de roscado.

¡Increíble!


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

Este api ha creado un servidor http utilizando sockets. Detalles:
1. Se recibe solicitud de navegador como texto
2. Lo analiza para recuperar información de url, método, atributos, etc.
3. Crea una respuesta dinámica utilizando el mapeo de url definido
4.Envía la respuesta al navegador.

Por ejemplo, aquí está cómo el constructor en la clase "Response.java" convierte una respuesta en bruto en una respuesta http:


Respuesta pública (String resp) {
Fecha fecha = nueva fecha ();
Inicio de cadena = "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";
encabezado + = "/ r / n";
this.resp = start + header + resp;
}


Puedes escribir un servidor Jetty Java incrustado bastante simple.

Embedded Jetty significa que el servidor (Jetty) se envió junto con la aplicación en lugar de implementar la aplicación en un servidor Jetty externo.

Por lo tanto, si en la aplicación web incorporada no incorporada en el archivo WAR que se implementó en algún servidor externo ( Tomcat / Jetty / etc), en la aplicación Jetty integrada, escriba la aplicación web y cree una instancia del servidor Jetty en el mismo código base.

Un ejemplo para el servidor Jetty Java incorporado puede clonar y usar: https://github.com/stas-slu/embedded-jetty-java-server-example


Puedo recomendar encarecidamente que busque Simple , especialmente si no necesita las capacidades de Servlet, sino simplemente acceder a los objetos de solicitud / respuesta. Si necesita REST, puede poner Jersey por encima, si necesita generar HTML o similar, hay Freemarker. Realmente me encanta lo que puedes hacer con esta combinación, y hay relativamente poca API para aprender.




Todo lo anterior responde a los detalles sobre el Controlador de solicitudes de subproceso principal único.

ajuste:

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

Permite la solicitud de múltiples solicitudes a través de múltiples subprocesos utilizando el servicio de ejecutor.

Entonces el código final será algo como abajo:

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



Desde Java SE 6, hay un servidor HTTP incorporado en Sun Oracle JRE. El resumen del paquete com.sun.net.httpserver describe las clases involucradas y contiene ejemplos.

Aquí hay un ejemplo de inicio copiado desde sus documentos, puedes copiar y ejecutar en Java 6+.

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

Se debe tener en cuenta que la parte response.length() en su ejemplo es mala, debería haber sido response.getBytes().length . Incluso entonces, el método getBytes() debe especificar explícitamente el conjunto de caracteres que luego se especifica en el encabezado de la respuesta. Por desgracia, aunque sea un error para los principiantes, es, después de todo, solo un ejemplo básico de lanzamiento.

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

Esta es la respuesta.

En cuanto al uso de las clases com.sun.* , Tenga en cuenta que, al contrario de lo que piensan algunos desarrolladores, no está absolutamente prohibido por las conocidas Preguntas frecuentes sobre por qué los desarrolladores no deben escribir programas que llaman paquetes "sol" . Las preguntas frecuentes se refieren al paquete sun.* (Como sun.misc.BASE64Encoder ) para uso interno por parte de Oracle JRE (que de este modo anularía su aplicación cuando la ejecute en un JRE diferente), no al paquete com.sun.* . Sun / Oracle también acaba de desarrollar software sobre la API de Java SE como cualquier otra empresa, como Apache, etc. El uso de las clases com.sun.* Solo se desaconseja (pero no está prohibido) cuando se trata de una implementación de cierta API de Java, como GlassFish (Java EE impl.), Mojarra (JSF impl.), Jersey (JAX-RS impl.), Etc. .