Servidor HTTP simples em Java usando apenas a API Java SE

Existe uma forma de criar um Servidor HTTP muito básico (suportando apenas o GET/POST) em Java usando apenas a API Java SE, sem escrever código para processar manualmente os pedidos HTTP e formatar manualmente as respostas HTTP? A API Java SE encapsula bem a funcionalidade do cliente HTTP em HttpURLConnection, mas existe um análogo para a funcionalidade do Servidor HTTP?

Só para que fique claro, o problema que tenho com muitos exemplos de ServerSocket que vi online é que eles fazem o seu próprio pedido. processamento/resposta formatação e manipulação de erros, que é tedioso, propenso a erros, e não é provável que seja abrangente, e estou tentando evitá-lo por essas razões.

como um exemplo da manipulação HTTP manual que estou a tentar evitar:

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

Author: BalusC, 2010-09-17

17 answers

Desde Java SE 6, há um Servidor HTTP builtin em Sun Oracle JRE. O com.sun.net.httpserver Resumo do pacote descreve as classes envolvidas e contém exemplos.

Aqui está um exemplo copipado de seus documentos, você pode apenas copiá-lo em 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();
        }
    }

}

Note-se que a parte response.length() no seu exemplo é má, deveria ter sido response.getBytes().length. Mesmo assim, o método getBytes() deve especificar explicitamente a codificação que você então indique no cabeçalho da resposta. Infelizmente, embora enganando-se a começar, é, afinal, apenas um exemplo básico de pontapé de saída.

Execute-o e vá para http://localhost:8000/test e verá a seguinte resposta:

Esta é a resposta


Quanto ao uso das classes com.sun.*, note que isto é, ao contrário do que alguns programadores pensam, absolutamente não proibido pela conhecida FAQ porque os programadores não devem escrever programas que chamam 'sun' Pacotes . Essa FAQ diz respeito ao pacote sun.* (como sun.misc.BASE64Encoder) para uso interno pelo Oracle JRE (que assim mataria a sua aplicação quando a executasse num JRE diferente), não ao pacote com.sun.*. Sun / Oracle também apenas desenvolver software em cima do Java SE API, como todas as outras empresas, como o Apache e assim por diante. A utilização de com.sun.* classes só é desencorajada (mas não proibida) quando diz respeito a uma implementação de uma determinada API Java, como o GlassFish (Java EE impl), Mojarra( JSF impl), Jersey (JAX-RS impl), etc.

 401
Author: BalusC, 2017-10-19 06:58:46

Check out NanoHttpd

"NanoHTTPD é um Servidor HTTP de peso leve concebido para incorporar noutras aplicações, lançado sob uma licença BSD modificada.

Está a ser desenvolvido no Github e utiliza o Apache Maven para o teste do builds & unit "

 41
Author: letronje, 2017-01-03 16:04:44

A solução com.sun.net.httpserver não é portátil entre JREs. É melhor usar a API dos webservices oficiais em javax.xml.ws para iniciar um 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: isto realmente funciona! O código acima parece fixe ou algo assim. Aqui está uma tradução para Java que eu testei:

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
Author: gruenewa, 2014-07-07 13:30:53
Veja o servidor Web "Jetty". Excelente pedaço de software de código aberto que parece atender todos os seus requisitos. Se insistes em filmar os teus próprios, dá uma vista de olhos na aula de "httpMessage".
 19
Author: James Anderson, 2015-07-23 13:11:38

Gosto desta pergunta porque esta é uma área onde há inovação contínua e há sempre a necessidade de ter um servidor de luz especialmente quando se fala de servidores embutidos em pequenos(er) dispositivos. Penso que as respostas se dividem em dois grandes grupos.

  1. Thin-server : conteúdo estático do servidor com processamento mínimo, processamento de contexto ou sessão.
  2. Small-server : ostensivamente a tem muitas qualidades de servidor tipo httpD com uma pegada tão pequena quanto você pode sair impune.

Enquanto eu poderia considerar bibliotecas HTTP como: Jetty, componentes de Http Apache, Netty e outros para ser mais como uma unidade de processamento HTTP raw. A rotulagem é muito subjetiva, e depende do tipo de coisas que você tem sido chamado para entregar em locais pequenos. Faço esta distinção no espírito da pergunta, em particular a observação sobre o assunto...

  • "...sem gravar o código para processar manualmente os pedidos de HTTP e formatar manualmente as respostas HTTP..."

Estas ferramentas crus permitem-lhe fazer isso (como descrito em outras respostas). Eles realmente não se prestam a um estilo pronto-set-go de fazer uma luz, embutido ou mini-servidor. Um mini-servidor é algo que pode lhe dar uma funcionalidade semelhante a um servidor web de função plena (como say, Tomcat) sem sinos e assobios, baixo volume, bom desempenho 99% do tempo. Um thin-server parece mais próximo do fraseado original apenas um pouco mais do que raw talvez com uma funcionalidade de subconjunto limitada, o suficiente para fazer você parecer bom 90% do tempo. A minha ideia de raw seria fazer - me parecer bem 75% - 89% do tempo sem design extra e codificação. Eu acho que se / quando você atingir o nível de arquivos de guerra, nós deixamos o "pequeno" para os servidores bonsi que se parece com tudo o que um servidor grande faz menor.

Opções do servidor fino

Opções do Mini-servidor:

  • Spark Java ... Coisas boas são possíveis com muitas construções auxiliares como filtros, modelos, etc.
  • MadVoc ... objectivos ser bonsai e poderia muito bem ser tal; -)

Entre as outras coisas a considerar, eu incluiria autenticação, validação, internacionalização, usando algo como FreeMaker ou outra ferramenta de modelo para renderizar a saída da página. Gerir de outro modo o HTML edição e parametrização é provável que o trabalho com HTTP pareça com Noughts-n-crosses. Naturalmente, tudo depende de quão flexível você precisa ser. Se é uma máquina de FAX em menu, pode ser muito simples. Quanto mais interações, o ' mais espesso ' seu framework precisa ser. Boa pergunta, boa sorte!

 16
Author: will, 2014-09-04 15:05:18
[[1]}era uma vez que eu estava à procura de algo semelhante - um Servidor HTTP leve mas totalmente funcional que eu poderia facilmente incorporar e personalizar. Encontrei dois tipos de soluções potenciais:
  • servidores completos que não são assim tão leves ou simples (para uma definição extrema de lightweight.)
  • servidores verdadeiramente leves que não são servidores HTTP, mas exemplos glorificados ServerSocket que não são nem remotamente compatíveis com RFC e não suportam o que é normalmente necessário funcionalidade básica.
Então..... Decidi escrever JLHTTP - o Java Lightweight HTTP Server .

Pode incorporá-lo em qualquer projecto como um único ficheiro de código (se bem que longo), ou como um jar ~50K (~35K despojado) sem dependências. Ele se esforça para ser compatível com o RFC e inclui extensa documentação e muitas características úteis, mantendo o bloat ao mínimo.

As funcionalidades incluem: máquinas virtuais, ficheiros que servem a partir do disco, mapeamentos do tipo mime através do mime normal.tipo file, directory index generation, welcome files, support for all HTTP methods, conditional ETags and If-* header support, chunked transfer encoding, gzip/deflate compression, basic HTTPS (as provided by the JVM), partial content (download continuation), multipart/form-data handling for file uploads, multiple context handlers via API ou annotations, parameter parsing (query string or x-www-form-urlencoded body), etc.

Espero que outros achem útil.
 12
Author: amichair, 2018-06-01 08:43:45

Um servidor web básico muito escrito em java pode ser encontrado aqui http://library.sourcerabbit.com/v/?id=19

 8
Author: Nikos, 2014-01-18 22:47:28

Faísca é o mais simples, aqui está um guia de arranque rápido: http://sparkjava.com/

 8
Author: Laercio Metzner, 2015-06-22 12:32:46

É possível criar um httpserver que fornece suporte básico para servlets J2EE com apenas o JDK e a API servlet em apenas algumas linhas de código.

[[[2]} eu achei isso muito útil para testes de unidades servlets, como ele começa muito mais rápido do que outros recipientes leves (nós usamos jetty para a produção).

A maioria dos receptores httpservers muito leves não fornecem suporte para servlets, mas nós precisamos deles, então eu pensei em compartilhar.

O exemplo que se segue fornece dados básicos apoio de servlet, ou lança e Excepçãodeoperação não apoiada para coisas ainda não implementadas. Ele usa o com. sun. net. httpserver.HttpServer para suporte http básico.

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
Author: f.carlsen, 2013-11-28 08:55:50

Posso recomendar vivamente que se Procure porSimple , especialmente se não precisar de capacidades de Servlet, mas simplesmente aceder aos objectos requisitados/reponse. Se você precisa de descanso você pode colocar Jersey em cima dele, se você precisa de output HTML ou similar há Freemarker. Eu realmente amo o que você pode fazer com esta combinação, e há relativamente pouca API para aprender.

 6
Author: Waldheinz, 2010-09-17 18:29:40

Pode também dar uma vista de olhos a uma estrutura de Aplicação NIO como:

  1. Netty: http://jboss.org/netty
  2. Apache Mina: http://mina.apache.org / ou o seu subprojecto AsyncWeb: http://mina.apache.org/asyncweb/
 5
Author: ThiamTeck, 2010-09-18 12:04:57

Este código é melhor do que o nosso, só precisas de adicionar 2 libs: javax.sergelet.jar e org.mortbay.CAL.jar .

Jacto Da 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();
    }
}
 5
Author: leandro, 2012-09-21 10:35:00

Checkout Simple . é um servidor embutido bastante simples com suporte incorporado para uma grande variedade de operações. Adoro particularmente o seu modelo de rosca..

Incrível!
 3
Author: Olu, 2015-07-15 10:43:57

Check out takes. Olha para https://github.com/yegor256/takes para informação rápida

 3
Author: George, 2015-10-15 14:20:38

Que tal Apache Commons HttpCore project?

A partir do site:... Objectivos Do HttpCore

  • implementação dos aspectos mais fundamentais do transporte HTTP
  • equilíbrio entre o bom desempenho e a clareza e expressividade do API
  • pequena (previsível) pegada de memória
  • biblioteca autónoma (sem dependências externas para além do JRE) {[[9]}
 2
Author: I. Joseph, 2013-02-11 21:52:42

Você pode escrever um servidor Java bastante simples embutido Jetty.

Jetty incorporado significa que o servidor (Jetty) enviado juntamente com a aplicação, em vez de implantar a aplicação no servidor de Jetty externo.

Por isso, se na aproximação não incorporada o seu webapp incorporado num ficheiro de guerra que foi enviado para algum servidor externo (Tomcat / Jetty / etc), no Jetty incorporado, você escreve o webapp e instancia o servidor de jetty na mesma base de código.

Exemplo para o servidor Jetty Java incorporado que você pode clone do git e usar: https://github.com/stas-slu/embedded-jetty-java-server-example

 0
Author: Stas, 2017-06-29 11:14:44

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

Esta api criou um Servidor http usando 'sockets'. Informacao:
1.It obtém o pedido do navegador como texto
2.Analisa-o para obter informações url, método ,atributos, etc.
3.Cria uma resposta dinâmica com o mapeamento de url definidos
4.Envia a resposta para o navegador.

Por exemplo, aqui está como o construtor na resposta.a classe java converte um raw resposta numa resposta http:


resposta pública (String resp){
Data = nova data ();
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.comprimento ()+ "\r\n";
header+= "\r\n"; Isto.resp=start+header+resp;
}

 0
Author: Devashish Priyadarshi, 2018-05-25 19:19:44