首页 > 编程笔记 > Java笔记 阅读:146

Java HTTPClient用法详解(附带实例)

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

Java 9 开始引入了一个处理 HTTP 请求的 HTTP Client API,该 API 支持同步和异步,在 Java 11 中已经进入正式可用状态,开发人员可以在 java.net 包中找到这个 API。

有人说,HttpClient 不就是一个浏览器嘛!可能不少人对 HttpClient 会产生这种误解,他们的观点是,既然 HttpClient 是一个 HTTP 客户端编程工具,那它就相当于一个浏览器,无非是不能把 HTML 渲染出页面而已。

其实,HttpClient 不是浏览器,它是一个 HTTP 通信库、一个工具包,因此它只提供一个通用浏览器应用程序所期望的功能子集。

HttpClient 与浏览器最根本的区别是,HttpClient 中没有用户界面,而浏览器需要一个渲染引擎来显示页面,并解释用户输入。HttpClient 只能以编程的方式通过其 API 用于传输和接收 HTTP 消息,它对内容也是完全不可知的。

HTTPClient API 的主要类及接口如下:
HTTPClient API 具有如下特性:

Java HTTPClient发送同步GET请求

使用 HTTPClient 发送请求的步骤如下:
接下来,通过案例来演示如何发送 GET 请求。
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class Demo {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建HttpClient对象
        HttpClient httpClient = HttpClient.newBuilder().build();
        // 创建HttpRequest对象
        HttpRequest request = HttpRequest.newBuilder()
            // 设置请求的URL地址和参数
            .uri(URI.create("http://118.190.158.17:10520/student/findAllStudent?page=1&limit=10"))
            // 设置请求方式为GET请求
            .GET().build();
        // 将服务器响应转换成字符串
        HttpResponse.BodyHandler<String> bh = HttpResponse.BodyHandlers.ofString();
        // 发送请求,获取服务器响应
        HttpResponse<String> response = httpClient.send(request, bh);
        System.out.println("响应的状态码:" + response.statusCode());
        System.out.println("响应头:" + response.headers());
        System.out.println("响应体:" + response.body());
    }
}
程序的运行结果如下:

   响应的状态码:200
   响应头:java.net.http.HttpHeaders@c84bfd11 { {content-type=[application/json], date = [Wed,
19 May 2021 02:19:48 GMT], transfer-encoding=[chunked]} }
   响应体:{"code":0,"msg":null,"count":1,"data":[{"id":11,"name":"陈建","age":37,"phone":
"18538062907","school":"C语言中文网","createTime":"2021-05-18 09:58:37"}]}

Java HTTPClient发送带请求体的请求

上面的程序演示了如何发送 GET 请求,此外 HTTPClient 还可以发送 POST、DELETE 等方式的请求。

接下来,通过案例来演示如何发送带请求体参数的 POST 请求。
import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Demo {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建HttpClient对象
        HttpClient httpClient = HttpClient.newBuilder().build();
        // 创建HttpRequest对象
        HttpRequest request = HttpRequest.newBuilder()
            // 设置请求的URL地址和参数
            .uri(URI.create("http://118.190.158.17:10520/student/findAllStudent"))
            // 设置已提交表单的方式编码请求体
            .headers("Content-Type", "application/x-www-form-urlencoded")
            // 设置请求方式为POST请求,并设置请求参数
            .POST(HttpRequest.BodyPublishers.ofString("page=1&limit=10")).build();
        // 将服务器响应转换成字符串
        HttpResponse.BodyHandler<String> bh = HttpResponse.BodyHandlers.ofString();
        // 发送请求,获取服务器响应
        HttpResponse<String> response = httpClient.send(request, bh);
        System.out.println("响应的状态码:" + response.statusCode());
        System.out.println("响应头:" + response.headers());
        System.out.println("响应体:" + response.body());
        System.out.println("程序运行结束");
    }
}
程序的运行结果如下:

   响应的状态码:200
   响应头:java.net.http.HttpHeaders@d4d4ce68 { {content-type=[application/json], date= [Wed,
19 May 2021 02:51:10 GMT], transfer-encoding=[chunked]} }
   响应体:{"code":0,"msg":null,"count":2,"data":[{"id":11,"name":"陈建","age":37,"phone":
"18538062907","school":"C语言中文网","createTime":"2021-05-18 09:58:37"},{"id":16,"name":"
张三", "age":20,"phone":"123456","school":"C语言中文网","createTime":"2021-05-19
10:35:57"}]}
   程序运行结束

前面两个实例程序的响应头结果相同,原因是两个案例发送的请求地址相同,请求参数相同。两个案例的不同点在于请求的方式不同:

具体使用哪种请求方式,以服务器接口定义规则为准。

Java HTTPClient发送异步请求

在现实网络中,网络环境千差万别,只要发送网络请求,就会不可避免地存在网络延迟,并且服务器处理请求也需要等待时间。那么通过 send() 方法发送同步请求时,在服务器返回响应之前,该方法会一直处于阻塞状态,效率比较低。

为了提升程序效率,可以使用 sendAsync() 方法发送异步请求。异步请求不存在阻塞,会返回一个 CompletableFuture 对象,它代表一个将要完成的任务(但是具体何时完成,尚不确定),因此程序要为 CompletableFuture 设置消费监听器,当 CompletableFuture 代表的任务结束时监听器被触发执行。

接下来,通过案例来演示如何发送异步 POST 请求。
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

public class Demo {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 创建HttpClient对象
        HttpClient httpClient = HttpClient.newBuilder().build();
        // 创建HttpRequest对象
        HttpRequest request = HttpRequest.newBuilder()
            // 设置请求的URL地址和参数
            .uri(URI.create("http://118.190.158.17:10520/student/findAllStudent"))
            // 设置已提交表单的方式编码请求体
            .headers("Content-Type", "application/x-www-form-urlencoded")
            // 设置请求方式为POST请求,并设置请求参数
            .POST(HttpRequest.BodyPublishers.ofString("page=1&limit=10")).build();
        // 将服务器响应转换成字符串
        HttpResponse.BodyHandler<String> bh = HttpResponse.BodyHandlers.ofString();
        // 发送异步请求,获取服务器响应
        httpClient.sendAsync(request, bh).thenApply(resp -> new Object[] {resp.statusCode(), resp.body()})
            .thenAccept(rt -> {
                System.out.println("响应的状态码:" + rt[0]);
                System.out.println("响应体:" + rt[1]);
            });
        System.out.println("程序运行结束");
        // 程序休眠3秒
        Thread.sleep(3000);
    }
}
程序的运行结果如下:

   程序运行结束
   响应的状态码:200
   响应体:{"code":0,"msg":null,"count":2,"data":[{"id":11,"name":"陈建","age":37,"phone":
"18538062907","school":"C语言中文网","createTime":"2021-05-18 09:58:37"},{"id":16,"name": "
张三","age":20,"phone":"123456","school":"C语言中文网","createTime":"2021-05-19
10:35:57"}]}

和本节第 2 个实例程序的运行结果对比可以发现,“程序运行结束”的打印位置发生了变化,其原因是:

Java WebSocket接口

WebSocket 接口类似普通的 Socket,只不过它是 Web 应用之间的 Socket 连接,通常以异步方式进行通信。

通过 Java 来实现 WebSocket 客户端非常简单,只需要以下两个步骤:
接下来,通过案例来演示如何构建 WebSocket 客户端。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.util.concurrent.CompletionStage;

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        // 定义一个WebSocketListener监听器对象,根据需要重写该监听器中的指定方法
        WebSocket.Listener listener = new WebSocket.Listener() {
            // 服务器端打开连接时触发该方法
            @Override
            public void onOpen(WebSocket webSocket) {
                System.out.println("打开连接");
                webSocket.sendText("我是C语言中文网的严站长", true);
                webSocket.request(1);
            }
            // 接收到服务器端返回的消息时触发该方法
            @Override
            public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
                System.out.println(data);
                webSocket.request(1);
                return null;
            }
        };
        // 传入监听器作为参数,创建WebSocket客户端
        HttpClient httpClient = HttpClient.newHttpClient();
        // 与服务器建立异步通信
        httpClient.newWebSocketBuilder()
            .buildAsync(URI.create("ws://127.0.0.1:10520/mySocket"), listener);
        Thread.sleep(5000);
    }
}

程序中创建了一个 WebSocket 客户端。虽然有了客户端,但是还缺少服务器端。接下来,通过案例来演示如何构建 WebSocket 服务器端:
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

// 注解ServerEndpoint标识该类作为WebSocket服务器端
@ServerEndpoint(value = "/mySocket")
@Component
public class Demo {
    // 注解OnOpen修饰的方法将会在客户端连接时触发
    @OnOpen
    public void start(Session session) {
        System.out.println("客户端连接进来了。sessionId: " + session.getId());
    }
    // 注解OnMessage修饰的方法将会在客户端消息到达时触发
    @OnMessage
    public void message(Session session, String message) {
        System.out.println("接收到消息: " + message);
        RemoteEndpoint.Basic remote = session.getBasicRemote();
        try {
            remote.sendText("收到信息,欢迎来到AAA软件学院");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 注解OnClose修饰的方法将会在客户端关闭时触发
    @OnClose
    public void end(Session session) {
        System.out.println("客户端关闭了。sessionId: " + session.getId());
    }
    // 注解OnError修饰的方法将会在客户端连接出错时触发
    @OnError
    public void error(Session session, Throwable throwable) {
        System.out.println("客户端出错了。sessionId: " + session.getId());
    }
}
服务器端程序需要首先运行,然后再运行客户端程序。客户端运行结果如下:

打开连接
收到信息,欢迎来到C语言中文网


服务器端运行结果如下:

客户端连接进来了。sessionId:0
接收到消息:我是C语言中文网的严站长
客户端出错了。sessionId:0
客户端关闭了。sessionId:0

相关文章