#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 楼
查看NanoHttpdNanoHTTPD是一种轻量级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
评论
嗯...简短的回答是不。如果您需要某种无需手动编写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