• HttpServer:JDK 内置的轻量级 HTTP 服务器


    1. 概述

    官方https://docs.oracle.com/javase/9/docs/api/com/sun/net/httpserver/package-summary.html

    HttpServer 是 JDK 1.6 以后内置的一个轻量级 HTTP 服务器(在 rt.jar 包中的 com.sun.net.httpserver 包下)。

    一个 HttpServer 实例被绑定到一个IP地址和端口号,并监听来自该地址的客户端TCP连接。

    其子类 HttpsServer 实现了 HTTPS 服务,还能处理 HTTPS 请求。

    一个简单的 HTTP 服务器:

    // 创建 http 服务器, 绑定本地 8080 端口
    HttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 0);
    
    // 创建上下文监听, "/" 表示匹配所有 URI 请求
    httpServer.createContext("/", new HttpHandler() {
        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            /*
             * PS: 必须按顺序设置响应: 添加响应头, 发送响应码和内容长度, 写出响应内容, 关闭处理器
             */
            // 响应内容
            byte[] respContents = "Hello World".getBytes("UTF-8");
    
            // 设置响应头
            httpExchange.getResponseHeaders().add("Content-Type", "text/html; charset=UTF-8");
            // 设置响应code和内容长度
            httpExchange.sendResponseHeaders(200, respContents.length);
    
            // 设置响应内容
            httpExchange.getResponseBody().write(respContents);
    
            // 关闭处理器, 同时将关闭请求和响应的输入输出流(如果还没关闭)
            httpExchange.close();
        }
    });
    
    // 启动服务
    httpServer.start();

    浏览器访问: http://localhost:8080,输出: Hello World

    使用 HttpServer 实现一个 HTTP 服务器主要涉及下面几个类:

    HttpServer: 表示一个服务器实例
    HttpContext: 服务器监听器的上下文
    HttpHandler: 上下文对应的 http 请求处理器
    HttpExchange: 对 http 请求和响应的数据封装

    2. 服务器: HttpServer
    创建 HttpServer 实例:

    /**
     * 创建 HttpServer 实例, 参数说明:
     *     addr: 服务绑定的地址端口
     *     backlog: TCP连接最大并发数, 传 0 或负数表示使用默认值
     */
    HttpServer httpServer = HttpServer.create​(InetSocketAddress addr, int backlog);

    HttpServer 常用方法:

    // 重新绑定地址和端口
    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)

    3. 上下文: HttpContext
    HTTP 上下文,实际上就是对请求的 URI 根路径匹配的监听,可以创建多个 HttpContext,一个 HttpContext 对应一个 HttpHandler,不同的 URI 请求,根据添加的 HttpContext 监听器,分配到对应的 HttpHandler 处理请求。

    PS: 一个 HTTP 请求只会被一个“最匹配”的 HttpContext 处理。

    创建 HTTP 上下文监听器:

    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 的请求
        }
    });

    请求 URI 的根路径匹配关系:

    4. 处理器: HttpHandler ( HttpExchange )
    HttpHandler 是 HttpContext 对应的请求处理监听器,监听器回调时传入的HttpExchange对象封装了对 http 请求和响应的所有数据操作。

    HttpExchange 与 请求 相关的方法:

    // 获取请求的 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​()

    HttpExchange 与 响应 相关的方法:

    // 获取响应头的 Map, 要添加头, 获取到 headers 后调用 add(key, value) 方法添加
    Headers getResponseHeaders​()
    
    // 发送响应头, 并指定 响应code 和 响应内容的长度
    void sendResponseHeaders​(int rCode, long responseLength)
    
    // 获取响应内容的输出流, 响应内容写到该流
    OutputStream getResponseBody​()

    HttpExchange 其他方法:

    // 关闭处理器, 同时将关闭请求和响应的输入输出流(如果还没关闭)
    void close​()
    
    // 获取此请求对应的上下文对象
    HttpContext getHttpContext​()
    
    // 获取收到请求的本地地址
    InetSocketAddress getLocalAddress​()

    5. 代码实例

    import com.sun.net.httpserver.HttpExchange;
    import com.sun.net.httpserver.HttpHandler;
    import com.sun.net.httpserver.HttpServer;
    
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.nio.charset.StandardCharsets;
    
    /**
     * JDK原生HttpServer
     *
     * @author FelixZh
     */
    public class JDKHttpServer {
        public static void main(String[] args) throws Exception {
            InetSocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getByName("localhost"), 8080);
            HttpServer httpServer = HttpServer.create(inetSocketAddress, 0);
    
            //监听上下文.指定匹配url
            httpServer.createContext("/", new MyHttpHandler());
            httpServer.createContext("/hello", new MyHttpHandler());
    
            //启动服务
            httpServer.start();
            System.out.println("Start...");
        }
    }
    
    class MyHttpHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            System.out.println(httpExchange.getRemoteAddress());
            System.out.println(httpExchange.getProtocol());
            System.out.println(httpExchange.getRequestMethod());
            System.out.println(httpExchange.getRequestURI());
    
            byte[] resp = "FelixZh".getBytes(StandardCharsets.UTF_8);
            //设置响应头
            httpExchange.getResponseHeaders().add("Content-Type", "text/html; charset=UTF-8");
            //设置响应code和内容长度
            httpExchange.sendResponseHeaders(200, resp.length);
            //设置响应内容
            httpExchange.getResponseBody().write(resp);
    
            //关闭处理器
            httpExchange.close();
        }
    }
  • 相关阅读:
    Mysql中Unsigned和Zerofill数据型的使用
    laravel Excel导入导出
    saas的资料
    Mysql的row_format(fixed与dynamic)
    第七节 css3动画之transform位移
    第六节 css3动画之transform变换
    第五节 css3动画之图片说明滑入效果
    第四节 css3动画之transition
    第三节 css3动画之透明
    第二节 css3动画之圆角
  • 原文地址:https://www.cnblogs.com/felixzh/p/16442933.html
Copyright © 2020-2023  润新知