JDK内置HttpServer服务器

阅读数:20 评论数:0

跳转到新版页面

分类

python/Java

正文

HttpServer是JAVA6以后内置的HTTP服务器,位于rt.jar的com.sun.net.httpserver包下。

一、涉及的主要类

1、HttpServer

表示一个服务器实例,需要绑定一个IP地址和端口号。(HttpsServer是其子类,处理https请求)。

// 重新绑定地址和端口
void bind​(InetSocketAddress addr, int backlog)
// 获取当前绑定的地址
InetSocketAddress getAddress​()

/**
 * 创建监听的上下文, 请求 URI 根路径的匹配, 根据不同的 URI 根路径选择不同的 HttpHandler 处理请求,
 * 路径必须以 "/" 开头。路径 "/" 表示匹配所有的请求 URI(没有其他更具体的匹配路径除外)。
 */
HttpContext createContext​(String path)
HttpContext createContext​(String path, HttpHandler handler)

// 移除上下文监听
void removeContext​(HttpContext context)
void removeContext​(String path)

// 设置请求的线程执行器, 设置为 null 表示使用默认的执行器
void setExecutor​(Executor executor)
Executor getExecutor​()

// 启动服务
void start​()
// 最长等待指定时间后停止服务
void stop​(int delay)

2、HttpContext

需要配置用于匹配URI的公共路径和用来处理请求的HttpHandler,可以创建多个HttpContext,一个HttpContext对应一个HttpHandler,不同的URI请求,根据添加的HttpContext,分配到对应的HttpHandler处理请求。

HttpServer httpServer = HttpServer.create(...);

/*
 * 上下文监听器对应的 URI 根路径,必须以 "/" 开头,
 * 表示以 "/xxx" 开头的 URI 请求都交给对应的 httpHandler 处理,
 * "/" 表示匹配所有的请求, 一个请求只会交给 path 最匹配的一个上下文去处理(不能重复处理)
 */
String path = "/xxx";

// 可以创建多个,以实现更细致的 URI 路径匹配来分开处理来自不同 URI 路径的请求
httpServer.createContext(path, new HttpHandler() {
    @Override
    public void handle(HttpExchange httpExchange) throws IOException {
        // 处理匹配当前上下文 path 的请求
    }
});

3、HttpHandler(HttpExchange)

http请求处理器。

// 获取请求的 URI, 请求链接除去协议和域名端口后的部分, 如: http://www.abc.com/aa/bb, URI 为 /aa/bb
URI getRequestURI​()

// 获取请求客户端的 IP 地址
InetSocketAddress getRemoteAddress​()

// 获取请求协议, 例如: HTTP/1.1
String getProtocol​()

// 获取请求的方法, "GET", "POST" 等
String getRequestMethod​()

// 获取所有的请求头
Headers getRequestHeaders​()

// 以输入流的方式获取请求内容
InputStream getRequestBody​()

// 获取响应头的 Map, 要添加头, 获取到 headers 后调用 add(key, value) 方法添加
Headers getResponseHeaders​()

// 发送响应头, 并指定 响应code 和 响应内容的长度
void sendResponseHeaders​(int rCode, long responseLength)

// 获取响应内容的输出流, 响应内容写到该流
OutputStream getResponseBody​()

// 关闭处理器, 同时将关闭请求和响应的输入输出流(如果还没关闭)
void close​()

// 获取此请求对应的上下文对象
HttpContext getHttpContext​()

// 获取收到请求的本地地址
InetSocketAddress getLocalAddress​()

4、HttpExchange

装了http请求和响应的所有数据操作。

(1)getRequestMethod()确定命令。

(2)getRequestHeaders()检查请求标头(如果需要)

(3)getRequestBody()返回InputStream以读取请求正文,读取请求主体后,流已关闭。

(4)getResponseHeaders()设置除content-length之外的任何响应头

(5)sendResponseHeaders(int,long) 发送响应头,必须在下一步之前调用。

(6)getResponseBody()获取OutputStream发送响应正文。写入响应主体后,必须关闭流以终止交换。

// 获取get请求参数
String queryParams = httpExchange.getRequestURI().getQuery();
System.out.println(queryParams);
// 获取非get请求参数
String paramStr = "";
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody(), "utf-8"));
StringBuilder requestBodyContent = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
        requestBodyContent.append(line);
}
paramStr = requestBodyContent.toString();

当请求InpuStream和响应OutputStream都关闭时,交换将终止。关闭OutputStream,隐式关闭InpuStream(如果它尚未关闭)。但是,建议在关闭之前使用InputStream中的所有数据,方法close()完成所有这些任务。在不消耗所有请求主体的情况下关闭交换不是错误,但可能使底层TCP连接无法用于后续交换。未能终止交换的效果未定义,但通常会导制资源无法释放或重用。

 

二、示例代码

package httpservice;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpServer;

public class MyHttpService {
//启动后访问:http://localhost:8888/test 
    public static void main(String[] args) throws Exception {
        *//创建http服务器,绑定本地8888端口*
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(8888), 0);
        *//创建上下文监听,拦截包含/test的请求*
        httpServer.createContext("/test", new TestHttpHandler());
        httpServer.start();
    }
}

package httpservice;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

public class TestHttpHandler implements HttpHandler {
    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String response = "test message";
        exchange.sendResponseHeaders(200, 0);
        OutputStream os = exchange.getResponseBody();
        os.write(response.getBytes("UTF-8"));
        os.close();
    }
}