是否有一种方法可以使用Java SE API在Java中创建一个非常基本的HTTP服务器(只支持GET/POST),而不需要编写代码手动解析HTTP请求和手动格式化HTTP响应?Java SE API在HttpURLConnection中很好地封装了HTTP客户机功能,但是是否有类似的HTTP服务器功能呢?
需要明确的是,我在网上看到的许多ServerSocket示例的问题是,它们自己进行请求解析/响应格式化和错误处理,这很乏味,容易出错,而且不太全面,出于这些原因,我试图避免使用它。
是否有一种方法可以使用Java SE API在Java中创建一个非常基本的HTTP服务器(只支持GET/POST),而不需要编写代码手动解析HTTP请求和手动格式化HTTP响应?Java SE API在HttpURLConnection中很好地封装了HTTP客户机功能,但是是否有类似的HTTP服务器功能呢?
需要明确的是,我在网上看到的许多ServerSocket示例的问题是,它们自己进行请求解析/响应格式化和错误处理,这很乏味,容易出错,而且不太全面,出于这些原因,我试图避免使用它。
当前回答
这个代码比我们的代码更好,你只需要添加2个库:javax. servlet .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);
}
}
}
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();
}
}
其他回答
一个非常基本的HTTP服务器在TCP套接字级别的例子:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class NaiveHttpServer {
public static void main(String[] args) throws IOException {
String hostname = InetAddress.getLocalHost().getHostName();
ServerSocket serverSocket = new ServerSocket(8089);
while (true) {
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String s = in.readLine();
System.out.println(s);
while ("\r\n".equals(in.readLine()));
if ("GET /hostname HTTP/1.1".equals(s)) {
out.println("HTTP/1.1 200 OK");
out.println("Connection: close");
out.println("Content-Type: text/plain");
out.println("Content-Length:" + hostname.length());
out.println();
out.println(hostname);
} else {
out.println("HTTP/1.1 404 Not Found");
out.println("Connection: close");
out.println();
}
out.flush();
}
}
}
该示例提供计算机的主机名。
曾经有一段时间,我正在寻找类似的东西——一个轻量级但功能齐全的HTTP服务器,我可以轻松地嵌入和定制。我发现了两种可能的解决方案:
不是那么轻量级或简单的完整服务器(对于轻量级的极端定义)。 真正的轻量级服务器不是HTTP服务器,而是华丽的ServerSocket示例,甚至不远程兼容rfc,不支持通常需要的基本功能。
所以…我开始编写JLHTTP——Java轻量级HTTP服务器。
您可以将它作为单个(如果相当长)源文件嵌入到任何项目中,或者作为一个~50K的jar (~35K剥离),没有依赖关系。它努力与rfc兼容,包括大量的文档和许多有用的特性,同时将膨胀保持在最低限度。
Features include: virtual hosts, file serving from disk, mime type mappings via standard mime.types 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 or annotations, parameter parsing (query string or x-www-form-urlencoded body), etc.
我希望其他人会觉得有用:-)
从Java 18开始,你可以用Java标准库创建简单的web服务器:
class Main {
public static void main(String[] args) {
var port = 8000;
var rootDirectory = Path.of("C:/Users/Mahozad/Desktop/");
var outputLevel = OutputLevel.VERBOSE;
var server = SimpleFileServer.createFileServer(
new InetSocketAddress(port),
rootDirectory,
outputLevel
);
server.start();
}
}
默认情况下,这将显示指定根目录的目录列表。您可以将index.html文件(以及CSS和JS文件等其他资产)放在该目录中来显示它们。
示例(我把这些放在桌面上,上面指定为我的根目录):
index . html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Java 18 Simple Web Server</title>
<link rel="stylesheet" href="styles.css">
<style>h1 { color: blue; }</style>
<script src="scripts.js" defer>
let element = document.getElementsByTagName("h1")[0];
element.style.fontSize = "48px";
</script>
</head>
<body>
<h1>I'm <i>index.html</i> in the root directory.</h1>
</body>
</html>
旁注
对于Java标准库HTTP客户端,请参阅Java 11新HTTP客户端API。
试试这个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;
}
httpserver解决方案不能跨jre移植。最好使用javax.xml.ws中的官方webservices API来引导一个最小的HTTP服务器…
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)
编辑:这实际上是工作!上面的代码看起来像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)
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);
}
}