servidor HTTP simples em Java usando apenas a API Java SE

333

Existe uma maneira de criar um servidor HTTP muito básico (suportando apenas GET / POST) em Java usando apenas a API Java SE, sem escrever código para analisar manualmente solicitações HTTP e formatar manualmente respostas HTTP? A API do Java SE encapsula bem a funcionalidade do cliente HTTP no HttpURLConnection, mas existe um analógico para a funcionalidade do servidor HTTP?

Só para esclarecer, o problema que tenho com muitos exemplos de ServerSocket que eu vi on-line é que eles fazem sua própria formatação de análise / resposta de solicitação e manipulação de erros, o que é tedioso, propenso a erros e provavelmente não é abrangente, e estou tentando evitá-lo por esses motivos.

Como um exemplo da manipulação manual de HTTP que estou tentando evitar:

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

asker
fonte
3
Umm ... a resposta curta é não. Se você deseja algo que lida com postagens e solicitações sem gravar manualmente os cabeçalhos http, use servlets. Mas isso é java ee. Se você não quiser usar algo assim, os soquetes e a análise manual são a única outra opção que conheço.
Matt Phillips
3
Sei que isso não está no espírito do SO, mas exortaria você a reconsiderar sua aversão pelas APIs Java EE. Como algumas das respostas mencionaram, existem algumas implementações muito diretas, como o Jetty, que permitem incorporar um servidor da Web em seu aplicativo independente enquanto ainda aproveitam a API do servlet. Se você absolutamente não pode usar a API Java EE por algum motivo que desconsidere o meu comentário :-)
Chris Thompson
1
"Servlets" não são realmente "Java EE". Eles são apenas uma maneira de escrever plug-ins que podem ser chamados pelo aplicativo ao redor em resposta à atividade da mensagem (atualmente, geralmente solicitações HTTP). Fornecer um ambiente de hospedagem de servlet "usando apenas a API Java SE" é exatamente o que o Jetty e o Tomcat fazem. Obviamente, você pode querer descartar a complexidade indesejada, mas pode ser necessário decidir sobre um subconjunto dos atributos e configurações permitidos do GET / POST. Muitas vezes, porém, não vale a pena, exceto por problemas especiais de segurança / incorporados.
David Tonhofer
1
Pode valer a pena examinar esta lista de servidores http antes de tomar uma decisão. java-source.net/open-source/web-servers
ThreaT

Respostas:

469

Desde o Java SE 6, há um servidor HTTP interno no Sun Oracle JRE. O com.sun.net.httpserverresumo do pacote descreve as classes envolvidas e contém exemplos.

Aqui está um exemplo de kickoff copiado de seus documentos (para todas as pessoas que tentam editá-lo, no entanto, porque é um pedaço feio de código, por favor, não, esta é uma pasta de cópia, não minha, além disso, você nunca deve editar citações, a menos que elas tenham sido alteradas na fonte original). Você pode simplesmente copiá-lo e executá-lo no 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();
        }
    }

}

Deveria ser notado que a response.length()parte no exemplo deles é ruim, deveria ter sido response.getBytes().length. Mesmo assim, o getBytes()método deve especificar explicitamente o conjunto de caracteres que você especifica no cabeçalho da resposta. Infelizmente, apesar de mal orientado para os iniciantes, é apenas um exemplo básico de kickoff.

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

Esta é a resposta


Quanto ao uso de com.sun.*classes, observe que isso é, ao contrário do que alguns desenvolvedores pensam, absolutamente proibido pela FAQ bem conhecida Por que os desenvolvedores não devem escrever programas que chamam de pacotes 'sun' . Essa FAQ refere-se ao sun.*pacote (como sun.misc.BASE64Encoder) para uso interno pelo Oracle JRE (que mataria seu aplicativo quando você o executasse em um JRE diferente), não ao com.sun.*pacote. A Sun / Oracle também acaba de desenvolver software sobre a API Java SE, como qualquer outra empresa, como Apache e assim por diante. O uso de com.sun.*classes é desencorajado (mas não proibido) quando se trata da implementação de uma determinada API Java, como GlassFish ( implemento Java EE), Mojarra (impl JSF), Jersey (impl JAX-RS), etc.

BalusC
fonte
19
@Waldheinz: Assim como @Software você está confundindo sun.*com com.sun.*. Por exemplo, você vê alguma documentação da sun.*API? Veja aqui: java.sun.com/products/jdk/faq/faq-sun-packages.html Ele diz alguma coisa com.sun.*? O com.sun.*é usado apenas para seu próprio software público, que não faz parte da API Java. Eles também desenvolvem software sobre a API Java, como qualquer outra empresa.
precisa saber é o seguinte
4
Eu acho que este é um servidor http muito bom para usar em casos de teste de integração. obrigado pela dica!
Andreas Petersson
13
Se você estiver usando o Eclipse e receber um erro como "Restrição de acesso: o tipo HttpExchange não está acessível devido à restrição na biblioteca necessária ...", stackoverflow.com/a/10642163 informa como desativar essa verificação de acesso.
Samuli Pahaoja
13
FWIW, isso também está presente no OpenJDK.
Jason C
6
As classes mencionadas aqui são marcadas @jdk.Exportedno código-fonte do OpenJDK, o que significa que a API é considerada pública e estará disponível no Java 9 (alguns outros com.sun.*pacotes ficarão indisponíveis devido ao Project Jigsaw).
Jules
42

Confira o NanoHttpd

"O NanoHTTPD é um servidor HTTP leve projetado para incorporação em outros aplicativos, lançado sob uma licença BSD modificada.

Ele está sendo desenvolvido no Github e usa o Apache Maven para compilações e testes de unidade "

letronje
fonte
4
Um cuidado: é provável que o NanoHTTPD não tenha proteção contra ataques de árvores - você deve verificar isso se estiver servindo em um endereço público. Com isso, quero dizer ataques em que uma solicitação como GET /../../blahblah http/1.1é emitida e o servidor caminha acima da raiz do site e entra no arquivo de sistema, servindo arquivos que podem ser usados ​​para comprometer ou atacar remotamente o sistema, como um arquivo de senha.
Lawrence Dol
7
Isso parece estar consertado. A versão atual gera 403 se (uri.startsWith ("..") || uri.endsWith ("..") || uri.indexOf ("../")> = 0))
Lena Schimmel
5
Eu não entendo como isso é uma resposta a esta pergunta.
precisa saber é o seguinte
28

A solução com.sun.net.httpserver não é portátil entre os JREs. É melhor usar a API oficial de serviços da web em javax.xml.ws para inicializar 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)

EDIT: isso realmente funciona! O código acima se parece com Groovy 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);
    }
}
gruenewa
fonte
1
+1 por ser portátil. Pena que você não pode definir o tipo de conteúdo da resposta como está text/xml.
icza 5/09/14
1
Eu acho que você poderia fazer a <code> classe Server implementa o Provedor <DataSource> {</code> ... e depois especificar o Tipo de Conteúdo dentro do método <code> getContentType () </code> do DataSource. Além disso, você também pode injetar o WebServiceContext: <code> @Resource WebServiceContext ctx; </code> para definir outros cabeçalhos e ler os parâmetros de solicitação. Infelizmente, a configuração do tipo de conteúdo via WebServiceContext não funciona.
gruenewa
4
Você poderia explicar por que o com.sun.net.HttpServer não é portátil nos JREs, por favor?
Javabeangrinder
3
Não, acho que não. Não funcionará na implementação Java da IBM e talvez também em outras. E mesmo que funcione agora, as APIs internas podem mudar. Por que não usar apenas a API oficial?
gruenewa
1
Este link: docs.oracle.com/javase/9/docs/api/java.xml.ws-summary.html diz que o módulo java.xml.ws está obsoleto desde o Java 9.
Erel Segal-Halevi
23

Gosto dessa pergunta porque é uma área em que há inovação contínua e sempre é necessário ter um servidor leve, especialmente quando se fala em servidores incorporados em dispositivos pequenos. Eu acho que as respostas se enquadram em dois grandes grupos.

  1. Servidor thin : conteúdo estático de servidor com processamento mínimo, processamento de contexto ou sessão.
  2. Servidor pequeno : ostensivamente a possui muitas qualidades de servidor do tipo httpD, com a menor pegada possível.

Embora eu possa considerar bibliotecas HTTP como: Jetty , Apache Http Components , Netty e outras mais como um recurso de processamento HTTP bruto. A rotulagem é muito subjetiva e depende do tipo de coisa que você solicitou para entregar em sites pequenos. Faço essa distinção no espírito da pergunta, particularmente a observação sobre ...

  • "... sem escrever código para analisar manualmente solicitações HTTP e formatar manualmente respostas HTTP ..."

Essas ferramentas brutas permitem fazer isso (conforme descrito em outras respostas). Eles realmente não se prestam a um estilo pronto para criar um servidor leve, incorporado ou mini. Um minisservidor é algo que pode oferecer funcionalidade semelhante a um servidor da Web com todas as funções (como, por exemplo, Tomcat ), sem sinos e assobios, baixo volume, bom desempenho 99% do tempo. Um servidor thin parece mais próximo do fraseado original um pouco mais do que bruto, talvez com uma funcionalidade de subconjunto limitada, o suficiente para fazer você parecer bem 90% do tempo. Minha idéia de matéria-prima seria me faz ficar bem 75% - 89% do tempo sem design e codificação extras. Acho que se / quando você atingir o nível dos arquivos WAR, deixamos o "pequeno" para os servidores bonsi que se parece com tudo o que um grande servidor faz menor.

Opções de servidor thin

Opções de mini-servidor:

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

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. Caso contrário, o gerenciamento da edição e parametrização HTML provavelmente fará com que o trabalho com HTTP pareça noughts-n-crosses. Naturalmente, tudo depende de quão flexível você precisa ser. Se for uma máquina de fax baseada em menus, pode ser muito simples. Quanto mais interações, mais ' espessa ' sua estrutura precisa ser. Boa pergunta, boa sorte!

vai
fonte
21

Dê uma olhada no servidor da web "Jetty" Jetty . Excelente peça de software de código aberto que parece atender a todos os seus requisitos.

Se você insistir em criar o seu próprio, dê uma olhada na classe "httpMessage".

James Anderson
fonte
Eu acho que a API do jetty depende do servlet.
irreputável
4
@ Irreputável: Não, o Jetty é um servidor da Web altamente modular, que possui um contêiner de servlet como um dos seus módulos opcionais.
Lawrence Dol
"existe um analógico para a funcionalidade do servidor" - sim, é a API "servlet". O contêiner de servlet chama sua classe depois de analisar os cabeçalhos, os cookies etc.
James Anderson
1
Apenas para o registro - Jetty vem com sua própria implementação do Servlet API e funciona muito bem com Java SE
James Anderson
4
O jetty é muito grande e possui muita curva de aprendizado antes que o uso real da produção se torne uma possibilidade.
Ameaça
18

Era uma vez, eu estava procurando por algo semelhante - um servidor HTTP leve, mas totalmente funcional, que eu pudesse incorporar e personalizar facilmente. Encontrei dois tipos de possíveis soluções:

  • Servidores completos que não são tão leves ou simples (para uma definição extrema de leve).
  • Servidores verdadeiramente leves que não são servidores HTTP, mas exemplos glorificados de ServerSocket que nem são remotamente compatíveis com RFC e não oferecem suporte à funcionalidade básica comumente necessária.

Então ... eu decidi escrever JLHTTP - O Java HTTP Lightweight Server .

Você pode incorporá-lo em qualquer projeto como um único arquivo de origem (se bem longo) ou como um frasco de ~ 50K (~ 35K despojado) sem dependências. Ele se esforça para ser compatível com RFC e inclui extensa documentação e muitos recursos úteis, mantendo o mínimo de inchaço.

Os recursos incluem: hosts virtuais, serviço de arquivo do disco, mapeamentos do tipo MIME via arquivo mime.types padrão, geração de índice de diretório, arquivos de boas-vindas, suporte para todos os métodos HTTP, ETags condicional e suporte ao cabeçalho If- *, codificação de transferência em pedaços, gzip / deflate compactação, HTTPS básico (conforme fornecido pela JVM), conteúdo parcial (continuação do download), manipulação de dados de várias partes / formulário para upload de arquivos, manipuladores de contexto múltiplos via API ou anotações, análise de parâmetros (string de consulta ou x-www-form-urlencoded corpo), etc.

Espero que outros achem útil :-)

amichair
fonte
O método principal é um bom exemplo de uso básico, e as perguntas frequentes entram em muitos detalhes. Se você tiver sugestões para melhorar os documentos existentes, entre em contato comigo diretamente!
Amichair 11/04/19
10

O Spark é o mais simples, aqui está um guia de início rápido: http://sparkjava.com/

Laercio Metzner
fonte
8

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

Achei isso muito útil para servlets de teste de unidade, pois ele é iniciado muito mais rapidamente do que outros contêineres leves (usamos jetty para produção).

A maioria dos httpservers muito leves não fornece suporte para servlets, mas precisamos deles, então pensei em compartilhar.

O exemplo abaixo fornece suporte básico ao servlet ou lança e UnsupportedOperationException para coisas ainda não implementadas. Ele usa o com.sun.net.httpserver.HttpServer para suporte básico a 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());
    }
}
f.carlsen
fonte
Faltam alguns métodos em ServletOutputStream e ServletInputStream
HomeIsWhereThePcIs
versão mais recente da API do servlet, acima se encaixa 3.0 e abaixo. Basta adicionar os métodos ausentes, conforme necessário no exemplo
f.carlsen 19/03
6

Eu recomendo fortemente a pesquisa no Simple , especialmente se você não precisar dos recursos do Servlet, mas simplesmente acessar os objetos de solicitação / resposta. Se você precisa do REST, pode colocar Jersey no topo, se precisar gerar HTML ou similar, há o Freemarker. Eu realmente amo o que você pode fazer com essa combinação e há relativamente pouca API para aprender.

Waldheinz
fonte
+1. Eu gosto das idéias por trás do Simple. No entanto, surgem problemas ao tentar usar HTTPS porque o Mamba retira o recurso "incorporável" do Simple.
ThreaT 19/03/14
6

Esse código é melhor que o nosso, você só precisa adicionar 2 libs: javax.servelet.jar e org.mortbay.jetty.jar .

Molhe 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 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();
    }
}
leandro
fonte
2
A pergunta pede uma solução puramente Java SE. Você verá que o jetty implementa a API Java EE.
Sridhar
O Jetty funciona perfeitamente bem usando o Java SE padrão e, portanto, atende aos requisitos. Ele implementa partes da API Java EE, não é necessário . Há uma diferença.
David Tonhofer
1
Isso não se qualifica. "usando apenas a API Java SE" . *.Servlet.jare *.jetty.jarobviamente não fazem parte do Java SE.
icza 5/09/14
preciso configurar o jetty? ou posso desclassificar esses dois jarros e executar este arquivo?
Paul Preibisch 23/03
4

Todas as respostas acima detalham detalhes sobre o único manipulador de solicitações encadeado principal.

configuração:

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

Permite que várias solicitações sejam veiculadas por meio de vários threads usando o serviço executor.

Portanto, o código final será algo como abaixo:

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();
        }
    }
}
Balu mallisetty
fonte
3

checkout Simples . é um servidor embutido bastante simples, com suporte integrado para diversas operações. Eu particularmente amo o seu modelo de rosqueamento ..

Surpreendente!

Olu Smith
fonte
2

E o projeto HttpCore do Apache Commons ?

A partir do site: ... Objetivos HttpCore

  • Implementação dos aspectos mais fundamentais do transporte HTTP
  • Equilíbrio entre bom desempenho e clareza e expressividade da API
  • Tamanho de memória pequeno (previsível)
  • Biblioteca independente (sem dependências externas além do JRE)
Iqbal
fonte
Provavelmente é um nível muito baixo. Deve-se pelo menos procurar uma solução que chame seu código no nível da API do servlet, a menos que se queira lidar com todos os conceitos como chunking, codificação etc. Pode ser divertido embora.
David Tonhofer
2

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

Esta API cria um servidor HTTP usando soquetes.

  1. Ele recebe uma solicitação do navegador como texto
  2. Analisa para recuperar informações de URL, método, atributos etc.
  3. Cria resposta dinâmica usando o mapeamento de URL definido
  4. Envia a resposta para o navegador.

Por exemplo, aqui está como o construtor na Response.javaclasse converte uma resposta bruta em uma resposta http:

public Response(String resp){
    Date date = new Date();
    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.length()+"\r\n";
    header+="\r\n";
    this.resp=start+header+resp;
}
Devashish Priyadarshi
fonte
1

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

Jetty incorporado significa que o servidor (Jetty) é enviado junto com o aplicativo, em vez de implantá-lo no servidor Jetty externo.

Portanto, se em uma abordagem não incorporada, seu aplicativo da Web foi incorporado ao arquivo WAR, implantado em algum servidor externo ( Tomcat / Jetty / etc), no Jetty incorporado, você escreve o aplicativo da Web e instancia o servidor do jetty na mesma base de código.

Um exemplo para o servidor Java Jetty incorporado, você pode clonar e usar o git : https://github.com/stas-slu/embedded-jetty-java-server-example

Johnny
fonte