Java中的简单HTTP服务器,仅使用Java SE API

ask*_*ker 318 java http httpserver

有没有办法只使用Java SE API在Java中创建一个非常基本的HTTP服务器(仅支持GET/POST),而无需编写代码来手动解析HTTP请求并手动格式化HTTP响应?Java SE API很好地将HTTP客户端功能封装在HttpURLConnection中,但是有一个用于HTTP服务器功能的模拟吗?

为了清楚起见,我在网上看到的很多ServerSocket示例的问题是他们自己做了请求解析/响应格式化和错误处理,这很乏味,容易出错,而且不太全面,我出于这些原因试图避免它.

作为我试图避免的手动HTTP操作的示例:

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

Bal*_*usC 451

从Java SE 6开始,Sun Oracle JRE中就有一个内置的HTTP服务器.该com.sun.net.httpserver包的摘要概述了参与类和包含的例子.

这是一个从他们的文档中复制的启动示例(尽管如此,所有人都试图编辑它,因为它是一段丑陋的代码,请不要,这是复制粘贴,不是我的,而且你永远不应该编辑引用,除非它们已经改变在原始来源).你可以在Java 6+上复制'n'paste'n'run它.

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

}
Run Code Online (Sandbox Code Playgroud)

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

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

这是回应


至于使用com.sun.*类,请注意,这与一些开发人员的想法相反,绝对不会被众所周知的常见问题所禁止,为什么开发人员不应该编写称为"sun"软件包的程序.该FAQ涉及Oracle JRE内部使用的sun.*软件包(例如sun.misc.BASE64Encoder)(当您在不同的JRE上运行时会破坏您的应用程序),而不是com.sun.*软件包.Sun/Oracle也只是在Java SE API之上开发软件,就像Apache等所有其他公司一样.com.sun.*当涉及某个Java API 的实现时,不鼓励(但不禁止)使用类,例如GlassFish(Java EE impl),Mojarra(JSF impl),Jersey(JAX-RS impl)等.

  • @Waldheinz:就像@Software一样,你在混淆`sun.*`和`com.sun.*`.例如,您是否看到了`sun.*`API的任何文档?看这里:http://java.sun.com/products/jdk/faq/faq-sun-packages.html它能说出关于`com.sun.*`的任何信息吗?`com.sun.*`仅用于他们自己的公共软件,它不是Java API的一部分.他们还在Java API之上开发软件,就像其他公司一样. (19认同)
  • FWIW这也存在于OpenJDK中. (13认同)
  • 如果您正在使用Eclipse并收到类似"访问限制:由于对所需库的限制而无法访问HttpExchange类型..."的错误,请http://stackoverflow.com/a/10642163说明如何禁用该访问检查. (12认同)
  • 这里提到的类在OpenJDK源代码中被标记为"@ jdk.Exported",这意味着API被认为是公共的,并且将在Java 9上可用(其他一些`com.sun.*`包将因Project而变得不可用拼图). (6认同)
  • 我认为这是一个非常好的http服务器,用于集成测试用例.谢谢你的暗示! (3认同)
  • @Waldheinz:您不是唯一概括这两个软件包的人。想一想:) (2认同)
  • 我将窃取您在问题 ID 后命名包的方式。到目前为止,我所见过的组织答案的最佳方式。 (2认同)

let*_*nje 41

查看NanoHttpd

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

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

  • 这似乎是固定的.当前版本生成403 if(uri.startsWith("..")|| uri.endsWith("..")|| uri.indexOf("../")> = 0). (7认同)
  • 一个警告:NanoHTTPD可能没有防止树木行走攻击的保护 - 你应该检查它是否会在公共地址上服务.我指的是发出诸如"GET /../../blahblah http/1.1"之类的请求并且服务器遍布网站根目录并进入系统文件域的攻击,提供可用于危害或远程攻击的文件系统,就像密码文件一样. (4认同)
  • 我不明白这是怎么回答这个问题的. (4认同)

gru*_*ewa 25

com.sun.net.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)
Run Code Online (Sandbox Code Playgroud)

编辑:这实际上有效!上面的代码看起来像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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下为什么com.sun.net.HttpServer不能在JRE上移植吗? (4认同)
  • 此链接:http://docs.oracle.com/javase/9​​/docs/api/java.xml.ws-summary.html 说 java.xml.ws 模块自 Java 9 以来已弃用。 (4认同)
  • 不,我不这么认为.它不适用于IBM的Java实现,也可能适用于其他人.即使它现在有效,内部API也可以更改.为什么不使用官方API? (3认同)
  • 引用另一篇文章的评论:“这里提到的类在 OpenJDK 源代码中被标记为@jdk.Exported,这意味着该 API 被认为是公共的,并且将在 Java 9 上可用” (3认同)
  • +1 便于携带。太糟糕了,您无法设置响应内容类型,因为它是“text/xml”。 (2认同)

Jam*_*son 21

看看"Jetty"网络服务器Jetty.精湛的开源软件,似乎满足您的所有要求.

如果你坚持自己滚动,那么看看"httpMessage"类.

  • @Irreputable:不,Jetty是一个高度模块化的Web服务器,它有一个servlet容器作为它的可选模块之一. (4认同)
  • Jetty太大了,在实际生产使用成为可能之前有太多的学习曲线. (4认同)
  • 只是为了记录 -- Jetty 附带了自己的 Servlet API 实现,并且与 Java SE 一起工作得很好 (2认同)

wil*_*ill 19

我喜欢这个问题,因为这是一个不断创新的领域,尤其是在谈论小型(呃)设备中的嵌入式服务器时,总是需要轻型服务器.我认为答案分为两大类.

  1. 瘦服务器:具有最少处理,上下文或会话处理的服务器静态内容.
  2. 小型服务器:表面上具有许多类似httpD的服务器质量,占用的空间小,可以随意使用.

虽然我可能会考虑像以下的HTTP库:Jetty,Apache Http Components,Netty和其他更像是原始HTTP处理设施.标签是非常主观的,取决于您为小型网站提供的服务种类.我在问题的精神上做出了这种区分,尤其是关于......的评论.

  • "...无需编写代码来手动解析HTTP请求并手动格式化HTTP响应......"

这些原始工具允许您这样做(如其他答案中所述).他们并没有真正适应制作轻型,嵌入式或迷你服务器的现成风格.迷你服务器可以为您提供类似功能的全功能Web服务器(比如说,Tomcat),没有花里胡哨,低音量,99%的时间都有良好的性能.瘦服务器似乎比原始语言更接近原始语言,可能只有有限的子集功能,足以让你在90%的时间看起来很好.我对raw的想法会让我看起来很好75% - 89%的时间没有额外的设计和编码.我认为,如果/当你达到WAR文件的级别时,我们已经为bonsi服务器留下了"小",看起来像大型服务器做得更小.

瘦服务器选项

迷你服务器选项:

  • Spark Java ...很多东西都可能有很多辅助构造,比如过滤器,模板等.
  • MadVoc ......旨在成为盆景,很可能就是这样;-)

在需要考虑的其他事项中,我将包括身份验证,验证,国际化,使用FreeMaker或其他模板工具来呈现页面输出.否则,管理HTML编辑和参数化可能会使HTTP看起来像noughts-n-crosses.当然,这一切都取决于你需要多么灵活.如果它是菜单驱动的传真机,它可以非常简单.交互越多,您的框架就越需要" 更厚 ".好问题,祝你好运!


ami*_*air 17

曾几何时我一直在寻找类似的东西 - 一个轻量级但功能齐全的HTTP服务器,我可以轻松地嵌入和定制.我找到了两种潜在的解决方案:

  • 完整的服务器,不是轻量级或简单的(对于轻量级的极端定义.)
  • 真正轻量级的服务器不是HTTP服务器,但是美化的ServerSocket示例甚至不符合远程RFC标准,并且不支持常用的基本功能.

所以......我开始编写JLHTTP - Java轻量级HTTP服务器.

您可以将它作为单个(如果相当长)源文件嵌入到任何项目中,或者作为~50K jar(~35K剥离)嵌入,没有依赖项.它力求符合RFC标准,并包含大量文档和许多有用的功能,同时将膨胀保持在最低限度.

功能包括:虚拟主机,从磁盘提供的文件,通过标准mime.types文件的mime类型映射,目录索引生成,欢迎文件,对所有HTTP方法的支持,条件ETag和If-*头支持,分块传输编码,gzip/deflate压缩,基本HTTPS(由JVM提供),部分内容(下载延续),文件上传的多部分/表单数据处理,通过API或注释的多个上下文处理程序,参数解析(查询字符串或x-www-form-urlencoded身体)等

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


Mah*_*zad 12

JEP 408:简单的 Web 服务器

从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();
    }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,这将显示您指定的根目录的目录列表。您可以在该目录中放置一个index.html文件(以及其他资源,如 CSS 和 JS 文件)来显示它们。

边注

对于 Java 标准库 HTTP客户端,请参阅Java 11后的新 HTTP 客户端 API以及JEP 321

  • @Naman 这个答案是 JDK 18 中的新方法。 (2认同)

Lae*_*ner 9

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


Bal*_*tty 9

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

环境:

 server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
Run Code Online (Sandbox Code Playgroud)

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

所以最终代码将如下所示:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


f.c*_*sen 8

可以创建一个http服务器,只需几行代码就可以使用JDK和servlet api为J2EE servlet提供基本支持.

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

大多数非常轻量级的http服务器都不提供对servlet的支持,但是我们需要它们,所以我想我会分享.

下面的示例为尚未实现的内容提供基本的servlet支持或throws和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());
    }
}
Run Code Online (Sandbox Code Playgroud)


Jur*_*raj 7

TCP 套接字级别的非常基本的 HTTP 服务器示例:

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();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

该示例提供计算机的主机名。


Wal*_*inz 6

我强烈建议您查看Simple,特别是如果您不需要Servlet功能但只需访问请求/响应对象.如果您需要REST,可以将Jersey置于其上,如果您需要输出HTML或类似的Freemarker.我真的很喜欢你能用这种组合做什么,并且学习的API相对较少.


小智 6

这段代码比我们的好,你只需要添加2个库:javax.servelet.jarorg.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);
        }

    }
} 
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个问题要求纯粹的Java SE解决方案.您会发现jetty实现了Java EE API. (2认同)
  • 这不符合条件。_“仅使用 Java SE API”_。`*.Servlet.jar` 和 `*.jetty.jar` 显然不是 Java SE 的一部分。 (2认同)

小智 5

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

  1. Netty:http://jboss.org/netty
  2. Apache Mina:http://mina.apache.org/或其子项目AsyncWeb:http://mina.apache.org/asyncweb/