有没有一种方法可以仅使用Java SE API在Java中创建一个非常基本的HTTP服务器(仅支持GET / POST),而无需编写代码来手动解析HTTP请求和手动格式化HTTP响应? Java SE API很好地将HTTP客户端功能封装在HttpURLConnection中,但是HTTP服务器功能是否有类似物?做自己的请求解析/响应格式和错误处理,这很乏味,容易出错,而且不太全面,出于这些原因,我正尝试避免这种情况。

评论

嗯...简短的回答是不。如果您需要某种无需手动编写http头即可处理发布和获取请求的东西,则可以使用servlet。但这就是java ee。如果您不想使用类似的方法,那么套接字和手动解析是我所知道的唯一其他选择。

我知道这不是SO的精神,但我敦促您重新考虑您对Java EE API的厌恶。正如一些答案中提到的那样,有一些非常简单的实现,例如Jetty,允许您将Web服务器嵌入独立应用程序中,同时仍然利用Servlet API。如果您出于某种原因绝对不能使用Java EE API,请忽略我的评论:-)

“ Servlet”不是真正的“ Java EE”。它们只是编写插件的一种方式,周围的应用程序可以响应消息活动(这些日子,通常是HTTP请求)来调用这些插件。提供“仅使用Java SE API”的servlet托管环境正是Jetty和Tomcat所做的。当然,您可能希望消除不必要的复杂性,但随后可能需要确定GET / POST的允许属性和配置的子集。但是,除了特殊的安全性/嵌入式问题之外,这通常不值得。

在做出决定之前,可能值得浏览一下HTTP服务器列表。 java-source.net/open-source/web-servers

#1 楼

从Java SE 6开始,Sun Oracle JRE中内置了HTTP服务器。 com.sun.net.httpserver软件包摘要概述了涉及的类并包含示例。 ,这是一个复制粘贴,而不是我的复制粘贴,此外,除非原始来源中的引文没有更改,否则您永远不要编辑引文。您可以只在Java 6+上复制'n'paste'n'来运行它。


在他们的例子中不好,应该是response.length()。即使这样,response.getBytes().length方法也必须显式指定您在响应头中指定的字符集。 las,尽管误导了初学者,但这毕竟只是一个基本的启动示例。

执行它并转到http:// localhost:8000 / test,您将看到以下响应:


这是响应




关于使用getBytes()类,请注意,这与某些开发人员的想法完全相反众所周知的常见问题解答(FAQ)并未禁止开发人员为什么不编写调用“ sun”程序包的程序。该FAQ与Oracle JRE内部使用的com.sun.*软件包(例如sun.*)有关(因此,在其他JRE上运行该应用程序将杀死您的应用程序),而不是sun.misc.BASE64Encoder软件包。 Sun / Oracle像其他公司(例如Apache等)一样,也只是在Java SE API之上自己开发软件。仅当com.sun.*类涉及某个Java API的实现时才鼓励使用(但不禁止使用)此类,例如GlassFish(Java EE impl),Mojarra(JSF impl),Jersey(JAX-RS impl)等。 >

评论


@Waldheinz:就像@Software一样,您将sun。*与com.sun。*混淆了。例如,您是否看到任何sun。* API文档?在这里查看:java.sun.com/products/jdk/faq/faq-sun-packages.html它能说明com.sun。*吗? com.sun。*仅用于其自己的公共软件,而不是Java API的一部分。他们像其他公司一样,在Java API之上开发软件。

– BalusC
2011年1月10日10:37



我认为这是在集成测试案例中使用的非常不错的http服务器。感谢您的提示!

–安德烈亚斯·彼得森(Andreas Petersson)
2012年7月27日13:56

如果您使用的是Eclipse并收到类似“访问限制:由于必需的库限制而无法访问HttpExchange类型的错误”之类的错误,stackoverflow.com/a/10642163会告诉您如何禁用该访问检查。

– Samuli Pahaoja
2013年9月10日上午9:55

FWIW也存在于OpenJDK中。

–杰森C
2015年2月6日下午6:37

此处引用的类标记为@jdk。在OpenJDK源代码中导出,这意味着该API被认为是公共的,并且将在Java 9上可用(由于Project Jigsaw,某些其他com.sun。*软件包将变得不可用)。

–法律
2015年8月5日13:02

#2 楼

查看NanoHttpd

NanoHTTPD是一种轻量级HTTP服务器,专为嵌入其他应用程序而设计,是在经过修改的BSD许可下发布的。

它是由Github开发并使用Apache用于构建和单元测试的Maven”

评论


一个警告:NanoHTTPD可能没有针对树走攻击的保护措施-您应该检查它是否将在公共地址上使用。我的意思是攻击,其中发出诸如GET /../../blahblah http / 1.1之类的请求,并且服务器从网站根目录之上进入系统文件区域,提供可用于破坏或远程攻击系统的文件,就像密码文件一样。

–劳伦斯·多尔(Lawrence Dol)
2010-09-17 4:51

这似乎是固定的。当前版本会生成403 if(uri.startsWith(“ ..”)|| uri.endsWith(“ ..”)|| uri.indexOf(“ ../”)> = 0)。

–莱娜·西默尔(Lena Schimmel)
2012年5月4日,9:23

我不明白这是如何解决这个问题的。

– kimathie
17年9月20日在8:31

#3 楼

com.sun.net.httpserver解决方案不能跨JRE移植。最好使用javax.xml.ws中的官方webservices API来引导最小的HTTP服务器...。

上面的代码看起来像Groovy之类。这是我测试过的Java翻译:

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)


评论


+1便于携带。太糟糕了,您无法设置响应内容类型,因为它是text / xml。

–icza
2014年9月5日在12:23

我认为您可以做 class服务器实现Provider { ... ...,然后在DataSource的 getContentType()方法中指定Content-Type。此外,您还可以注入WebServiceContext: @Resource WebServiceContext ctx; 来设置其他标头和读取请求参数。不幸的是,通过WebServiceContext设置内容类型无效。

– gruenewa
2014年9月12日20:09



您能否解释为什么com.sun.net.HttpServer无法跨JRE移植?

–javabeangrinder
2014年11月19日15:56

不,我不这么认为。它不适用于IBM的Java实现,也可能不适用于其他实现。即使现在可以使用,也可以更改内部API。为什么不只使用官方API?

– gruenewa
2014年11月26日下午5:58

此链接:docs.oracle.com/javase/9​​/docs/api/java.xml.ws-summary.html说,从Java 9开始不推荐使用java.xml.ws模块。

– Erel Segal-Halevi
17-10-12在22:49

#4 楼

我喜欢这个问题,因为这是一个不断创新的领域,总是需要一台轻巧的服务器,尤其是在谈论小型设备中的嵌入式服务器时。我认为答案可以分为两大类。 >小型服务器:表面上看,它具有许多类似httpD的服务器质量,并且占用的空间尽可能小。

我可能会考虑使用HTTP库,例如Jetty,Apache Http Components,Netty和其他的则更像是原始的HTTP处理工具。标签是非常主观的,并且取决于您要求为小型站点提供的内容。我本着问题的精神进行区分,尤其是关于...


“ ...的注释,而无需编写代码来手动解析HTTP请求和手动格式化HTTP响应... “

这些原始工具可让您做到这一点(如其他答案所述)。他们并没有真正采用现成的制作轻型,嵌入式或小型服务器的风格。小型服务器可以为您提供与功能齐全的Web服务器(例如Tomcat)相似的功能,而无需花哨的时间,小巧的性能和99%的性能。瘦服务器似乎比原始措辞更接近原始措辞,也许具有有限的子集功能,但足以使您90%的时间看起来不错。我的原始想法是让我在没有额外设计和编码的情况下,看起来75%-89%的时间看起来不错。我认为,如果/当您达到WAR文件的级别时,我们将bonsi服务器的位置“小”了,看起来像大型服务器的所有功能都变小了。

瘦服务器选项



灰熊

UniRest(多种语言)

NanoHTTPD(仅一个文件)

Mini -server选项:



Spark Java ...可以使用很多辅助构造(如过滤器,模板等)来实现美好的事情。 br />除其他事项外,我还包括身份验证,验证,国际化,使用FreeMaker或其他模板工具来呈现页面输出。否则,管理HTML编辑和参数化可能会使使用HTTP看起来像noughts-n-crosses。自然,这一切都取决于您需要具备的灵活性。如果它是菜单驱动的传真机,则可能非常简单。交互越多,您的框架就需要越“厚实”。好问题,祝你好运!

#5 楼

看看“ Jetty” Web服务器Jetty。精湛的开源软件,似乎可以满足您的所有要求。

评论


我认为码头API取决于servlet。

–信誉不佳
2010-09-17在3:00

@Irreputable:不,Jetty是一个高度模块化的Web服务器,它具有Servlet容器作为其可选模块之一。

–劳伦斯·多尔(Lawrence Dol)
2010-09-17 4:43

“这是服务器功能的模拟” –是的是“ Servlet” API。 servlet容器在解析了标头,cookie等之后调用您的类。

–詹姆斯·安德森(James Anderson)
2010-09-17 8:06

仅作记录-Jetty带有自己的Servlet API实现,并且可以与Java SE一起正常工作

–詹姆斯·安德森(James Anderson)
2013年9月12日下午0:21

码头太大,在实际生产使用成为可能之前,学习曲线太多。

–威胁
2014年3月19日10:54



#6 楼

曾几何时,我一直在寻找类似的东西-一种轻巧而功能齐全的HTTP服务器,我可以轻松地嵌入和自定义它。我发现了两种潜在的解决方案:



并非全部都是轻量级或简单的全服务器(对于轻量级的极端定义。)
不是真正的轻量级服务器相当多的HTTP服务器,但是美化了ServerSocket示例,这些示例甚至都不是远程RFC兼容的,并且不支持常用的基本功能。 。

您可以将其作为单个(如果相当长的话)源文件或不依赖项的〜50K jar(剥离后〜35K)嵌入任何项目中。它努力符合RFC的要求,并包含大量文档和许多有用的功能,同时将膨胀降至最低。功能包括:虚拟主机,从磁盘提供文件,通过标准mime.types文件进行mime类型映射,目录索引生成,欢迎文件,对所有HTTP方法的支持,条件ETag和If- *标头支持,分块传输编码,gzip / deflate压缩,基本HTTPS(由JVM提供),部分内容(下载继续),多部分/ form-data处理文件上传,通过API或批注的多个上下文处理程序,参数解析(查询字符串或x-www-form-urlencoded正文)等。

我希望其他人觉得它有用: -)

评论


主要方法是基本用法的一个很好的例子,并且FAQ涉及许多细节。如果您有改进现有文档的建议,请随时直接与我联系!

–amichair
19年4月11日在6:15

最后,是一种实用的工作服务器,能够将ISO映像用作虚拟介质,以普通用户的身份通过iLO引导服务器。 Python的http.server或派生类无法完整或大块地提供如此大的文件;这个人没有使用sudo就完成了这项工作。感谢分享!

–user3076105
昨天



#7 楼

Spark是最简单的,这是快速入门指南:http://sparkjava.com/

评论


哇小而干净:)

– Shamshirsaz.Navid
20-11-30在21:28

#8 楼

只需几行代码,就可以创建一个httpserver来提供对J2EE servlet的基本支持,而只需JDK和servlet api。

我发现这对于单元测试servlet非常有用,因为它的启动速度比其他轻量级容器快得多(我们使用码头生产)。

大多数非常轻量级的httpserver都不提供对servlet的支持,但是我们需要它们,所以我想与大家分享。和UnsupportedOperationException用于尚未实现的内容。它使用com.sun.net.httpserver.HttpServer获得基本的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());
    }
}


评论


这缺少ServletOutputStream和ServletInputStream上的某些方法

–HomeIsWhereThePcIs
19年11月20日在11:14

较新版本的servlet api,适用于3.0及以下版本。只需根据需要将缺少的方法添加到示例中

–f.carlsen
20 Mar 19 '20 at 5:55

#9 楼

您还可以查看一些NIO应用程序框架,例如:


Netty:http://jboss.org/netty

Apache Mina:http: //mina.apache.org/或其子项目AsyncWeb:http://mina.apache.org/asyncweb/



#10 楼

该代码比我们的代码更好,您只需要添加2个库:javax.servelet.jar和org.mortbay.jetty.jar。

类码头:

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

    }
} 


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


评论


这个问题要求一个纯粹的Java SE解决方案。您会发现jetty实现了Java EE API。

– Sridhar
2012年9月17日下午15:58

Jetty使用标准Java SE可以完美运行,因此符合要求。它实现了Java EE API的某些部分,不需要它。它们是有区别的。

– David Tonhofer
13年11月19日在17:24



这不符合条件。 “仅使用Java SE API”。 * .Servlet.jar和* .jetty.jar显然不是Java SE的一部分。

–icza
2014年9月5日12:54



我需要设置码头吗?还是可以只包含这两个jar并运行此文件?

– Paul Preibisch
15年3月23日在17:41

#11 楼

上面所有有关单主线程请求处理程序的答案的详细信息。

设置:

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


允许使用执行程序服务通过多个线程服务多个请求。

所以结束代码如下:

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


#12 楼

我强烈建议您研究Simple,尤其是在您不需要Servlet功能而只需要访问请求/响应对象的情况下。如果需要REST,则可以将Jersey置于其之上,如果需要输出HTML或类似内容,则可以使用Freemarker。我真的很喜欢您可以通过这种组合执行的操作,而且学习的API相对较少。

评论


+1。我喜欢Simple背后的想法。但是,尝试使用HTTPS时会出现问题,因为Mamba取消了Simple的“可嵌入”功能。

–威胁
2014年3月19日在11:40



#13 楼

结帐简单。它是一个非常简单的嵌入式服务器,内置了对多种操作的支持。我特别喜欢它的线程模型。.

#14 楼

签出takes。查看https://github.com/yegor256/takes以获取快速信息

#15 楼

Apache Commons HttpCore项目如何?

来自网站:...
HttpCore目标


最基本的HTTP传输方面的实现
平衡良好性能之间的平衡和
API的清晰性和表达性
(可预测的)小内存占用空间
自包含的库(JRE之外没有外部依赖项)


评论


那可能太低级了。除非有人想自己处理所有概念,例如分块,编码等,否则至少应该针对一种在servlet API级别上调用代码的解决方案。虽然这可能很有趣。

– David Tonhofer
13年11月19日在17:35

#16 楼

试试这个https://github.com/devashish234073/Java-Socket-Http-Server/blob/master/README.md

此API使用套接字创建了HTTP服务器。


它以文本形式从浏览器获取一个请求
对其进行解析以检索URL信息,方法,属性等。
使用定义的URL映射创建动态响应
将响应发送到浏览器。例如,这是Response.java类中的构造函数将原始响应转换为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;
}


#17 楼

您可以编写一个非常简单的嵌入式Jetty Java服务器。

嵌入式Jetty意味着服务器(Jetty)与应用程序一起提供,而不是在外部Jetty服务器上部署应用程序。

因此,如果以非嵌入式方式将您的Web应用程序内置到WAR文件中并部署到某个外部服务器(Tomcat / Jetty等)中,则在嵌入式Jetty中,您可以编写Webapp并在同一代码库中实例化Jetty服务器。 />
您可以git clone并使用嵌入式Jetty Java服务器的示例:https://github.com/stas-slu/embedded-jetty-java-server-example