是否有一种方法可以使用Java SE API在Java中创建一个非常基本的HTTP服务器(只支持GET/POST),而不需要编写代码手动解析HTTP请求和手动格式化HTTP响应?Java SE API在HttpURLConnection中很好地封装了HTTP客户机功能,但是是否有类似的HTTP服务器功能呢?

需要明确的是,我在网上看到的许多ServerSocket示例的问题是,它们自己进行请求解析/响应格式化和错误处理,这很乏味,容易出错,而且不太全面,出于这些原因,我试图避免使用它。


当前回答

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

其他回答

试试这个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;
}

以上所有的回答关于单主线程请求处理器的细节。

设置:

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

从Java SE 6开始,在Sun Oracle JRE中有一个内置的HTTP服务器。Java 9模块名称为jdk.httpserver。httpserver包摘要概述了涉及的类并包含示例。

这里有一个从他们的文档复制粘贴的启动示例。你可以复制,粘贴,然后在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(); } } }

应该注意的是,他们示例中的response.length()部分是坏的,它应该是response.getBytes().length。即使这样,getBytes()方法也必须显式地指定在响应头中指定的字符集。唉,尽管对初学者有误导,但毕竟这只是一个基本的启动示例。

执行它并访问http://localhost:8000/test,你将看到以下响应:

这是反应


As to using com.sun.* classes, do note that this is, in contrary to what some developers think, absolutely not forbidden by the well known FAQ Why Developers Should Not Write Programs That Call 'sun' Packages. That FAQ concerns the sun.* package (such as sun.misc.BASE64Encoder) for internal usage by the Oracle JRE (which would thus kill your application when you run it on a different JRE), not the com.sun.* package. Sun/Oracle also just develop software on top of the Java SE API themselves like as every other company such as Apache and so on. Moreover, this specific HttpServer must be present in every JDK so there is absolutely no means of "portability" issue like as would happen with sun.* package. Using com.sun.* classes is only discouraged (but not forbidden) when it concerns an implementation of a certain Java API, such as GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), etc.

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

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

因此,如果在非嵌入式方法中,你的webapp内置到WAR文件中,并部署到一些外部服务器(Tomcat / Jetty / etc),在嵌入式Jetty中,你在相同的代码库中编写webapp并实例化Jetty服务器。

一个嵌入式Jetty Java服务器的例子,你可以git克隆和使用:https://github.com/stas-slu/embedded-jetty-java-server-example

查看NanoHttpd

NanoHTTPD是一个轻量级的HTTP服务器,设计用于嵌入其他应用程序,在Modified BSD许可下发布。

它正在Github开发,并使用Apache Maven进行构建和单元测试。”