Java发起同异步HTTP请求和处理数据

这篇具有很好参考价值的文章主要介绍了Java发起同异步HTTP请求和处理数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

📚专栏

「Java数据集成」专栏

  • 《Java发起HTTP请求并解析JSON返回数据》:下图简称为《请求和解析》
  • 《基于MyBatis实现依次、批量、分页增删改查操作》:下图简称为《依批分增删改查》
  • 《用Python根据JSON生成Java类代码和数据库建表SQL语句》:下图简称为《生成代码脚本》
  • 《基于SpringBoot+MyBatis的数据增删改查模板》:下图简称为《增删改查模板》
  • 《Java发起同异步HTTP请求和处理数据》:下图简称为《同异步请求和处理》
  • 《基于SpringBoot+MyBatis的数据集成模板》:下图简称为《数据集成模板》
  • 《JavaHTTP请求工具类HTTPUtils》:下图简称为《HTTP请求工具类》
  • 《JavaJSON处理工具类JSONUtils》:下图简称为《JSON处理工具类》
  • 《JavaXML处理工具类XMLUtils》:下图简称为《XML处理工具类》
  • 《用Python生成随机JSON数据》:下图简称为《生成随机数据脚本》

同步与异步概念辨析

同步(synchronous)和异步(asynchronous)通常用于描述在执行操作时是否需要等待某个操作完成,以及如何处理返回结果

  • 类比生活
    • 同步是接力跑:前一个人跑完了再轮到下一个人跑
    • 异步是齐跑:大家在起跑线同时起跑
  • 编程
    • 同步编程(synchronous programming):大多数编程都是同步编程。在同步编程中,任务是按顺序执行的,一个任务必须等待另一个任务完成后才能开始执行
    • 异步编程(asynchronous programming):同时处理多个任务
  • 请求
    • 同步请求(synchronous request):每个请求都必须按顺序进行,并且程序必须等待每个请求完成后才能继续执行下一个请求
    • 异步请求(asynchronous request):同时发起多个请求

此处再提两个相关但不同的概念,并发(concurrency)和并行(parallelism)

  • 并发是指看起来貌似在同时执行多个任务(如时间片轮转),但在微观上他们都是按一定顺序被处理的,也可以算是某种意义上的“同时”、“异步”,看你怎么理解
  • 并行则是指多个任务执行就在同一时刻发生,算是真正意义上的“同时”、“异步”

Java 中的 HTTP 请求

对于 Java 中发起 HTTP 请求而言,一样有同步异步之分。看本文剩余部分之前首先需要学习用 Java 发起 HTTP 请求,对应后文的 requestHTTPContent() ,意为请求后获取响应内容,并在此篇博客文章中有介绍,可以说是本文的基础

💬相关

本文前置基础博客文章《Java发起HTTP请求并解析JSON返回数据》

https://blog.csdn.net/weixin_42077074/article/details/128672130

笔者做了个简单的测试,测试方案如下,一个 JSON 对象对应数据表中的一条记录,对象含有两个键,取值分别为长度为 10 的和长度为 1000 的随机字符串,记录不同方案、不同请求量级下请求获取数据的耗时。

以下每项耗时数据至少测试三次并取平均值。 此外,测试数据是在较为理想的环境下测试获取的,而在实际使用场景中的数据应该会比测试数据略高。

请求数 依次同步请求耗时 批量异步请求耗时 分页异步请求耗时
10 115ms 25ms 31ms
1000 10.19s 1073ms 1106ms
100000 17m53.28s 2m55.20s 2m55.80s

为了更好描述同步与异步,以下给出一个示例场景,我想发起 10 次 HTTP 请求,每次请求都带有参数开始时间 startTimeendTime,为 2023 年 1 月 1 日至 2023 年 1 月 10 日十天中每日零点和下一日的零点,如第一次请求的参数为 2023-01-01 00:00:002023-01-02 00:00:00

依次同步请求

同步发请求无非就是直接调用或在 for 里调用 requestHTTPContent()

// 设置请求头
Map<String, String> headers = new HashMap<String, String>(){{
    // 设置接收内容类型
    put("Accept","application/json");
    // 设置发送内容类型
    put("Content-Type","application/json;charset=UTF-8");
    // 设置字符集
    put("charset", "UTF-8");
    // 设置访问者系统引擎版本、浏览器信息的字段信息,此处伪装成用户通过浏览器访问
    put("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
}};

// 设置开始时间和结束时间
LocalDateTime startTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
LocalDateTime endTime = LocalDateTime.of(2023, 1, 2, 0, 0, 0);

// 创建一个数组来保存结果
String[] results = new String[10];

for (int i = 0; i < 10; i++) {
    // 格式化开始时间和结束时间
    String formattedTime1 = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    String formattedTime2 = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

    // 设置参数
    Map<String, String> params = new HashMap<String, String>(){{
        put("startTime", formattedTime1);
        put("endTime", formattedTime2);
    }};

    // 发送请求并获取响应
    results[i] = requestHTTPContent("http://www.example.com","GET", headers, params);

    // 更新开始时间和结束时间
    startTime = startTime.plusDays(1);
    endTime = endTime.plusDays(1);
}

// 输出结果
for (int i = 0; i < 10; i++) {
    System.out.println(results[i]);
}

批量异步请求

倘若请求量特别大,还按同步的方式进行,综合程序处理、网络延迟等因素,会非常地慢。

而对于异步而言,实现方式就比较多了,如 Java 11 中可以直接使用 java.net.http.HttpClient 类来创建异步 HTTP 客户端并使用 API,网上方法很多,此处不再赘述了

然而笔者处于兼容等各种考虑还是 Java8,Java8 并没有内置的异步 HTTP 客户端,要么调用第三方库来实现,如 Apache 的 HttpAsyncClient

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
    <version>4.1.4</version>
</dependency>

要么借助 Java 8 的标准库提供的基于 CompletableFuture 的异步编程来实现,笔者也是使用这个方案

注意, CompletableFuture 是并发而不是并行意义上的异步

// 创建 1000 个异步任务
CompletableFuture<String>[] futures = new CompletableFuture[1000];
LocalDateTime startTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
LocalDateTime endTime = LocalDateTime.of(2023, 1, 2, 0, 0, 0);

for (int i = 0; i < 1000; i++) {
    // 格式化开始时间和结束时间
    String formattedTime1 = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    String formattedTime2 = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

    // 设置参数
    Map<String, String> params = new HashMap<String, String>(){{
        put("startTime", formattedTime1);
        put("endTime", formattedTime2);
    }};

    // 设置异步请求
    futures[i] = asyncHTTPRequest("http://www.example.com","GET", headers, params);

    // 更新开始时间和结束时间
    startTime = startTime.plusDays(1);
    endTime = endTime.plusDays(1);
}

// 等待异步任务完成,超时时间为5秒
try {
    CompletableFuture.allOf(futures).get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
} catch (TimeoutException e) {
    System.out.println("请求超时");
    e.printStackTrace();
    return;
}

// 输出每个异步任务的结果
for (int i = 0; i < 1000; i++) {
    try {
        System.out.println(futures[i].get());
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}

其中的异步请求函数 asyncHTTPRequest()

public static CompletableFuture<String> asyncHTTPRequest(String strURL, String method, Map<String, ?> headers, Map<String, ?> params) {
    return CompletableFuture.supplyAsync(() -> {
        try {
            return requestHTTPContent(strURL, method, headers, params);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    });
}

批量异步请求 + 批量数据处理

为了更好说明,现在我们不单单是请求数据,还要请求完后处理数据,以下给出一个示例场景

  • HTTP 请求返回的 JSON 数据含有键 idkey1key2,如
{
    "code":"200",
    "msg":"success",
    "data":[
        {"id":"000001","key1":"5WoFrZxFR5ZXi6tA","key2":"0afba4s6HATkE9N4"},
        {"id":"000002","key1":"aKeHAyL10oGXYcB1","key2":"cG5SlzRavO2zMLkW"},
        {"id":"000003","key1":"O7zdMpEilsatFHRo","key2":"rKsqN0nOfU06vQ8E"},
        {"id":"000004","key1":"xD6s7KlaUQ9zY5pR","key2":"8oe1RTbDu8gH30Fn"},
        {"id":"000005","key1":"lkpnmv47rybG3hw2","key2":"rht3MhVvDOuaB9cQ"}
	]
}
  • 建立对应的 Java 类 Data,含有属性 idattr1attr2

让我们来批量异步请求 + 批量数据处理

💬相关

依次、批量、分页进行数据增删改查请查看

博客文章《基于Spring Boot + MyBatis的数据增删改查模板》,下文的 dataMapper 的 Mapper 层函数均出自于此

https://blog.csdn.net/weixin_42077074/article/details/128868655

博客文章《基于MyBatis实现依次、批量、分页增删改查操作》,下文的 dataMapper 的 Mapper 层函数的 MyBatis 实现部分出自于此

https://blog.csdn.net/weixin_42077074/article/details/129405833

public void batchRequestAndHandle() throws Exception {
    // 异步请求列表
    List<CompletableFuture<String>> futures = new ArrayList<>();

    // 设置开始时间和结束时间
    LocalDateTime startTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
    LocalDateTime endTime = LocalDateTime.of(2023, 1, 2, 0, 0, 0);
    
    for (int i = 0; i < 1000; i++) {
        // 格式化开始时间和结束时间
        String formattedTime1 = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String formattedTime2 = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 设置参数
        Map<String, String> params = new HashMap<String, String>(){{
            put("startTime", formattedTime1);
            put("endTime", formattedTime2);
        }};

        // 设置异步请求
        futures.add(batchHandleAsyncResult("http://www.example.com","GET", headers, params));

        // 更新开始时间和结束时间
        startTime = startTime.plusDays(1);
        endTime = endTime.plusDays(1);
    }
    // 批量处理异步请求结果
    batchHandleAsyncResult(futures);
}

其中批量处理异步请求结果函数 batchHandleAsyncResult()

public void batchHandleAsyncResult(List<CompletableFuture<String>> futures){
    // 等待异步任务完成,超时时间为 30 分钟
    try {
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(1800, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        System.out.println("请求超时");
        e.printStackTrace();
        return;
    }
    // 批量处理记录列表
    List<Data> dataList = new ArrayList<>();
    // 处理每个异步任务的结果
    for (CompletableFuture<String> future : futures) {
        try {
            JSONObject jsonObj = JSON.parseObject(future.get());// 将 JSON 字符串解析成 JSON 对象
            if (jsonObj != null){
                JSONArray jsonInfo = jsonObj.getJSONArray("data");//解析成 JSON 数组
                if (jsonInfo != null) for (int i = 0; i < jsonInfo.size(); i++) {// 遍历 JSON 数组依次取出 JSON 对象
                    JSONObject jsonDetailInfo = jsonInfo.getJSONObject(i);
                    dataList.add(new Data(
                            jsonDetailInfo.getString("id"),
                            jsonDetailInfo.getString("key1"),
                            jsonDetailInfo.getString("key2")
                    ));           
                }
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } 
    }
    // 批量插入或更新
    dataMapper.batchInsertOrUpdateData(dataList);
    futures.clear();
    return ;
}

分页异步请求

可以看到按照上文的异步请求的逻辑,是先将所有请求异步一次性发起,再将结果存进数组,随后统一处理

但是在统一处理之前,放进数组的返回结果会占着内存空间,倘若请求量大,响应信息多,那很容易内存溢出(笔者已经经历过几次了,因为返回结果对应在数据库的行数是百万及以上量级的)

这就需要将大量的请求进行分页,每次仅将一部分的异步请求发起并立即处理结果,随后再进行下一部分的

对于分页处理数据的思路而言,有一些常见的量需要先了解一下

  • 总量
    • totalRecords:总记录数,即数据表中的行数
    • totalFields:总字段数,即数据表中的列数
    • totalData:总数据量,即数据表中的行数 × 列数
  • 分页
    • pageSize:页面大小,即每页记录数
    • pageDataSize:页面数据量大小,即每页记录数 × 字段数
    • currentPage:当前页码
    • totalPages:总页数

一般是将众多记录拆成若干页,每页再挨个处理,一般很少见到拆字段的,所以也就很少见到“每页字段大小”(因为“每页字段大小”就是“总字段数”)

至于这个页大小多少合适,我觉得没有统一的答案,自己根据实际情况设定即可,要看客户机和服务器的硬件条件(CPU 处理速度,内存大小等)、网络延迟等诸多因素,笔者均经历过页太小速度极慢,页太大内存溢出等各种情况……

不过一般情况下,在进行处理完数据之前,我们可能只知道总字段数 totalFields,不知道总记录数 totalRecords,所以要计数

  • 计数
    • currentCount:当前记录数,当达到页面大小后就重置为 0
    • totalCount:总记录数,即数据表中的行数

分页异步请求 + 分页数据处理

其实分页和批量的实现是非常像的,只是多了将大量的请求及其结果进行分页的过程

异步请求分页的页面大小较大取决于服务器的硬件条件,而插入或更新数据分页的页面大小较大取决于客户机的硬件条件

一重分页——一次请求对应一条记录

如果恰好一次请求对应一条记录,那么二者的分页是相同的,可以说仅需一重分页

每次仅将一部分的异步请求发起并处理结果,一旦当前记录数达到页面大小就立即异步请求,随后将当前页所有异步请求的结果直接批量处理

一重分页涉及下面的变量

  • 总量
    • totalFields:总字段数,即数据表中的列数
  • 分页
    • pageSize:页面大小,即每页记录数
    • pageDataSize:页面数据量大小,即每页记录数 × 字段数
  • 计数
    • currentCount:当前记录数,当达到页面大小后就重置为 0
    • totalCount:总记录数,即数据表中的行数
public void pageRequestAndHandleData() throws Exception {

    int totalRequests = 1000; // 总请求数
    int requestPageSize = 300; // 请求页面大小,即每页请求数
    int currentRequestCount = 0; // 当前记录数,当达到数据页面大小后就重置为 0

    // 异步请求列表
    List<CompletableFuture<String>> futures = new ArrayList<>();

    // 设置开始时间和结束时间
    LocalDateTime startTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
    LocalDateTime endTime = LocalDateTime.of(2023, 1, 2, 0, 0, 0);

    for (int i = 0; i < totalRequests; i++) {
        // 格式化开始时间和结束时间
        String formattedTime1 = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String formattedTime2 = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 设置参数
        Map<String, String> params = new HashMap<String, String>(){{
            put("startTime", formattedTime1);
            put("endTime", formattedTime2);
        }};

        // 设置异步请求
        futures.add(asyncHTTPRequest("http://www.example.com","GET", headers, params));

        currentRequestCount ++;

        // 当记录数达到页面大小就进行处理,即分页处理
        if(currentRequestCount == requestPageSize){
            pageHandleAsyncResult(futures);
            currentRequestCount = 0;
        }

        // 更新开始时间和结束时间
        startTime = startTime.plusDays(1);
        endTime = endTime.plusDays(1);
    }
    // 处理最后一页
    if(!futures.isEmpty()){
        pageHandleAsyncResult(futures);
    }
}

其中批量处理异步请求结果函数 batchHandleAsyncResult() 和前文批量集成数据中的是一样的

二重分页——一次请求对应多条记录

然而, 大多数情况下,一次请求是对应多条记录的,返回内容中会有数组让你遍历,而且在你处理异步请求结果之前,你并不知道一个请求对应多少记录,也就未知总记录数

因此异步请求的分页和插入或更新数据的分页应该是分开的,可以说是需要二重分页

每次仅将一部分的异步请求发起并处理结果,一旦当前记录数达到页面大小就立即异步请求,随后将当前页所有异步请求的结果再分页处理

二重分页涉及下面的变量

  • 请求总量
    • totalRequests:总请求数
  • 请求分页
    • requestPageSize:请求页面大小,即每页请求数
  • 请求计数
    • currentRequestCount:当前请求数,当达到请求页面大小后就重置为 0
  • 数据总量
    • totalFields:总字段数,即数据表中的列数
  • 数据分页
    • recordPageSize:记录页面大小,即每页记录数
  • 数据计数
    • currentRecordCount:当前记录数,当达到数据页面大小后就重置为 0
    • totalRecordCount:总记录数,即数据表中的行数
public void pageRequestAndHandleData() throws Exception {

    int totalRequests = 1000; // 总请求数
    int requestPageSize = 300; // 请求页面大小,即每页请求数
    int currentRequestCount = 0; // 当前记录数,当达到数据页面大小后就重置为 0

    // 异步请求列表
    List<CompletableFuture<String>> futures = new ArrayList<>();

    // 设置开始时间和结束时间
    LocalDateTime startTime = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
    LocalDateTime endTime = LocalDateTime.of(2023, 1, 2, 0, 0, 0);

    for (int i = 0; i < totalRequests; i++) {
        // 格式化开始时间和结束时间
        String formattedTime1 = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String formattedTime2 = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        // 设置参数
        Map<String, String> params = new HashMap<String, String>(){{
            put("startTime", formattedTime1);
            put("endTime", formattedTime2);
        }};

        // 设置异步请求
        futures.add(asyncHTTPRequest("http://www.example.com","GET", headers, params));

        currentRequestCount ++;

        // 当记录数达到页面大小就进行处理,即分页处理
        if(currentRequestCount == requestPageSize){
            pageHandleAsyncResult(futures);
            currentRequestCount = 0;
        }

        // 更新开始时间和结束时间
        startTime = startTime.plusDays(1);
        endTime = endTime.plusDays(1);
    }
    // 处理最后一页
    if(!futures.isEmpty()){
        pageHandleAsyncResult(futures);
    }
}

其中分页处理异步请求结果函数 pageHandleAsyncResult()文章来源地址https://www.toymoban.com/news/detail-420581.html

public void pageHandleAsyncResult(List<CompletableFuture<String>> futures){

    int pageDataSize = 12000; // 页面数据量大小,即每页记录数 × 字段数
    int totalFields = Data.class.getDeclaredFields().length; // 总字段数,即数据表中的列数
    int pageRecordSize = pageDataSize / totalFields; // 页面大小,即每页记录数
    int currentRecordCount = 0; // 当前记录数,当达到页面大小后就重置为 0
    int totalRecordCount = 0; // 累积记录数,一直累积,不进行重置,最终就是总记录数


    // 等待异步任务完成,超时时间为 30 分钟
    try {
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get(1800, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        System.out.println("请求超时");
        e.printStackTrace();
        return;
    }
    // 批量处理记录列表
    List<Data> dataList = new ArrayList<>();
    // 处理每个异步任务的结果
    for (CompletableFuture<String> future : futures) {
        try {
            JSONObject jsonObj = JSON.parseObject(future.get());// 将 JSON 字符串解析成 JSON 对象
            if (jsonObj != null){
                JSONArray jsonInfo = jsonObj.getJSONArray("data");//解析成 JSON 数组
                if (jsonInfo != null) for (int i = 0; i < jsonInfo.size(); i++) {// 遍历 JSON 数组依次取出 JSON 对象
                    JSONObject jsonDetailInfo = jsonInfo.getJSONObject(i);
                    dataList.add(new Data(
                        jsonDetailInfo.getString("id"),
                        jsonDetailInfo.getString("key1"),
                        jsonDetailInfo.getString("key2")
                    ));
                    currentRecordCount ++;
                    totalRecordCount ++;
                    if(currentRecordCount == pageRecordSize){
                        dataMapper.batchInsertOrUpdateData(dataList);
                        dataList.clear();
                        currentRecordCount = 0;
                    }
                }
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
    if(totalRecordCount > 0) dataMapper.batchInsertOrUpdateData(dataList);
    futures.clear();
    return ;
}

到了这里,关于Java发起同异步HTTP请求和处理数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何发起一次完整的HTTP的请求流程

    目录 💡 预备知识 🔊 浏览器端发起 HTTP 请求流程 1、构建请求 2、查找缓存 3、准备IP地址和端口 4、等待TCP队列 5、建立TCP连接 6、发送HTTP请求 🔊 服务器端处理 HTTP 请求流程 1、返回请求 2、断开连接 3、重定向 HTTP 是一种允许浏览器向服务器获取资源的协议,是 Web 的基础

    2023年04月24日
    浏览(42)
  • Node.js 发起HTTP请求的5种方式

    HTTP(百度百科):   超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;         可以直接用这个模块来发起 HTT

    2024年02月21日
    浏览(40)
  • okhttp异步get和post请求,实现读取获取、增加http文件数据

    Okhttp类,封装方法 activity类 MainActivity

    2024年02月14日
    浏览(27)
  • Postman创建项目 对接口发起请求处理

    查看本文之前 您需要理解了解 Postman 的几个简单工作区 如果还没有掌握 可以先查看我的文章 简单认识 Postman界面操作 那么 掌握之后 我们就可以正式来开启我们的接口测试 我们先选择 Collections 我们点上面这个加号 多拉一个项目出来 然后 我们选我们刚加号点出来的项目 点

    2024年02月08日
    浏览(49)
  • golang 发起 http 请求,获取访问域名的 ip 地址(net, httptrace)

    今天碰到了个需求,我要知道程序对外访问的 http 请求域名的 ip 地址。 直接查看 golang 的 net/http 包,发现 Response 中并没有我想要的 ip 信息。 考虑到在 OSI 七层模型中, ip 是网络层协议,而 http 是应用层协议。去翻了下 net 包,发现了基础用法。 先提一下,域名访问服务器

    2024年02月02日
    浏览(50)
  • uniapp发起post和get请求——this.$http.get 和 this.$http.post传参

    main.js按照内容自行修改

    2024年02月15日
    浏览(50)
  • 【Java】数据交换 Json 和 异步请求 Ajax

     🎄欢迎来到@边境矢梦°的csdn博文,本文主要讲解Java 中 数据交换和异步请求 JsonAjax 的相关知识🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下 🫰🫰🫰 ,下次更新不迷路🎆 Ps: 月亮越亮说明知识点越重要 (重要性或者难度

    2024年02月13日
    浏览(47)
  • Java发起Post 、Get 各种请求整合

    java发起get请求和post请求的各种情况整合。具体看代码以及注释。其中Constants.UTF8本质是指\\\"UTF-8\\\"

    2024年02月04日
    浏览(48)
  • java http请求url有空格,通过unicode方法处理

    在Java中,可以通过Unicode编码来处理URL中的空格等特殊字符,将其转换为%xx的形式。下面是一个处理示例: 以上代码中,我们使用了URLEncoder.encode()方法将URL中的特殊字符进行编码,并将所有的+替换为%20,表示空格的编码。使用时,只需要传入需要编码的URL即可,例如: 输出

    2024年02月12日
    浏览(42)
  • HttpURLConnection发起请求中文数据乱码问题解决

    HttpURLConnection发送POST请求时,请求参数中有中文,且请求成功后,后端显示出现乱码 POST的form没有转码的问题,服务器数据将byte转成utf8,utf8编码是3个字节对应一个字符,但如果只读了一个字节或者不为3的倍数这样强转编码就会导致乱码出现 在POST方法初始化StringEntity时指定

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包