(Java) 模拟http请求调用远程接口

该博客为转载内容,涉及Java、Python和前端领域,但未提供具体信息。

 

package com.vcgeek.hephaestus.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能描述
 *
 * @author: zyu
 * @description:
 * @date: 2019/3/22 11:10
 */
public class HttpClientUtil {

    /**
     * 发送GET请求
     *
     * @param url        目的地址
     * @param parameters 请求参数,Map类型。
     * @return 远程响应结果
     */
    public static String sendGet(String url, Map<String, String> parameters) {
        String result = "";
        BufferedReader in = null;// 读取响应输入流
        StringBuffer sb = new StringBuffer();// 存储参数
        String params = "";// 编码之后的参数
        try {
            // 编码请求参数
            if (parameters.size() == 1) {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8"));
                }
                params = sb.toString();
            } else {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8")).append("&");
                }
                String temp_params = sb.toString();
                params = temp_params.substring(0, temp_params.length() - 1);
            }
            String full_url = url + "?" + params;
            System.out.println(full_url);
            // 创建URL对象
            java.net.URL connURL = new java.net.URL(full_url);
            // 打开URL连接
            java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL
                    .openConnection();
            // 设置通用属性
            httpConn.setRequestProperty("Accept", "*/*");
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("User-Agent",
                    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
            // 建立实际的连接
            httpConn.connect();
            // 响应头部获取
            Map<String, List<String>> headers = httpConn.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : headers.keySet()) {
                System.out.println(key + "\t:\t" + headers.get(key));
            }
            // 定义BufferedReader输入流来读取URL的响应,并设置编码方式
            in = new BufferedReader(new InputStreamReader(httpConn
                    .getInputStream(), "UTF-8"));
            String line;
            // 读取返回的内容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送POST请求
     *
     * @param url        目的地址
     * @param parameters 请求参数,Map类型。
     * @return 远程响应结果
     */
    public static String sendPost(String url, Map<String, String> parameters) {
        String result = "";// 返回的结果
        BufferedReader in = null;// 读取响应输入流
        PrintWriter out = null;
        StringBuffer sb = new StringBuffer();// 处理请求参数
        String params = "";// 编码之后的参数
        try {
            // 编码请求参数
            if (parameters.size() == 1) {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8"));
                }
                params = sb.toString();
            } else {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8")).append("&");
                }
                String temp_params = sb.toString();
                params = temp_params.substring(0, temp_params.length() - 1);
            }
            // 创建URL对象
            java.net.URL connURL = new java.net.URL(url);
            // 打开URL连接
            java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL
                    .openConnection();
            // 设置通用属性
            httpConn.setRequestProperty("Accept", "*/*");
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("User-Agent",
                    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
            // 设置POST方式
            httpConn.setDoInput(true);
            httpConn.setDoOutput(true);
            // 获取HttpURLConnection对象对应的输出流
            out = new PrintWriter(httpConn.getOutputStream());
            // 发送请求参数
            out.write(params);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应,设置编码方式
            in = new BufferedReader(new InputStreamReader(httpConn
                    .getInputStream(), "UTF-8"));
            String line;
            // 读取返回的内容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

}

 

转载于:https://www.cnblogs.com/zyulike/p/10579116.html

<think>我们要在Java调用远程接口,每次请求后让线程睡眠3秒。根据引用的内容,我们可以参考引用[3]中的实现方式,它使用了Thread.sleep()方法。在引用[3]的代码中,有一个循环,每次循环中调用服务接口后,使用Thread.sleep(2*1000)让当前线程睡眠2秒。我们可以类似地使用Thread.sleep(3000)来实现睡眠3秒。实现步骤:1.在调用远程接口的代码之后,直接使用Thread.sleep(3000)让当前线程睡眠3秒(注意:sleep方法可能会抛出InterruptedException,需要处理异常)。2.注意,sleep方法会使当前线程暂停执行指定的时间,单位是毫秒。以下是一个简单的示例代码:```javapublicclassRemoteServiceCaller{publicstaticvoidmain(String[]args){//假设我们有一个远程服务接口需要调用for(inti=0;i<5;i++){//调用远程接口callRemoteService(i);//每次请求后睡眠3秒try{//睡眠3秒(3000毫秒)Thread.sleep(3000);}catch(InterruptedExceptione){//处理中断异常e.printStackTrace();//在中断异常中,通常我们会重新设置中断标志,因为中断信号被捕获了Thread.currentThread().interrupt();}}}privatestaticvoidcallRemoteService(intrequestNum){//实际调用远程接口的代码,这里用打印模拟System.out.println("调用远程接口请求编号:"+requestNum+",时间:"+newDate());}}```上述代码中,我们循环调用远程接口5次,每次调用后睡眠3秒。注意事项:-Thread.sleep()方法会阻塞当前线程,因此在多线程环境下,如果每个线程都需要在调用后睡眠,那么每个线程都会独立睡眠,互不影响。-如果是在多线程并发调用中,每个线程在完成一次调用后都睡眠3秒,那么需要将睡眠代码放在每个线程的执行逻辑中(具体可参考引用[2]和引用[4]的多线程处理方式)。-使用Thread.sleep()可能会导致性能下降,因为它会阻塞线程。但在需要控制请求频率的场景下(如避免频繁请求远程接口),这是常见的做法。另外,引用[4]中提到了一些优化方案,比如使用重试机制和线程池配置。如果我们的调用需要重试,可以结合重试机制(如使用GuavaRetrying),并在每次重试之间添加等待时间(例如指数退避策略),但这里的需求是每次请求后固定睡眠3秒,所以直接使用Thread.sleep(3000)即可。问题:如何避免多线程环境下睡眠造成的线程管理问题?答:在多线程中,每个线程的睡眠是独立的。我们可以使用线程池来管理线程,并在每个任务(Runnable或Callable)中执行完远程调用后睡眠。但需要注意的是,睡眠会占用线程池的线程资源,如果同时有很多请求,会导致线程池中的线程被大量占用(因为都在睡眠),可能会影响性能。因此,在并发量大的情况下,可以考虑使用调度线程池(ScheduledExecutorService)来调度任务,将请求任务按照时间间隔执行,而不是在任务内部睡眠。但是,用户的问题是在每次请求后睡眠3秒,并不一定是多线程。如果是多线程并发,而且每个线程都需要在每次请求后睡眠,那么上述方法仍然可用,但需要考虑线程池的资源。总结:根据需求,我们可以使用Thread.sleep(3000)来实现每次请求后线程睡眠3秒。</think> 根据您的需求,在Java中实现每次调用远程接口后线程休眠3秒,以下是推荐实现方案: ### 推荐实现代码 ```java public class RemoteServiceCaller { private static final int SLEEP_TIME_MS = 3000; // 3秒休眠时间 public void callWithDelay(String endpoint) { try { // 1. 调用远程接口 String response = callRemoteService(endpoint); System.out.println("接口响应: " + response); // 2. 请求后固定休眠3秒 Thread.sleep(SLEEP_TIME_MS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态[^4] System.err.println("线程休眠被中断: " + e.getMessage()); } } private String callRemoteService(String url) { // 实际调用远程API的实现 // 可使用HttpClient或RestTemplate等工具[^1][^2] return "调用结果"; } // 多线程场景示例 public void concurrentCalls(List<String> endpoints) { ExecutorService executor = Executors.newFixedThreadPool(5); for (String endpoint : endpoints) { executor.submit(() -> { callWithDelay(endpoint); System.out.println(Thread.currentThread().getName() + " 完成请求"); }); } executor.shutdown(); } } ``` ### 关键实现点 1. **固定休眠实现** ```java Thread.sleep(3000); // 精确休眠3秒(3000毫秒) ``` 2. **多线程控制** - 使用 `Thread.sleep()` 会阻塞当前线程但**不影响其他线程**[^2] - 线程池中每个线程独立休眠[^4] 3. **中断处理** ```java catch (InterruptedException e) { Thread.currentThread().interrupt(); // 最佳实践:恢复中断标志 } ``` ### 使用场景 1. 接口限流:避免触发远程服务的速率限制 2. 过载保护:防止自身系统资源耗尽[^4] 3. 顺序调用:确保请求间隔稳定(如旧系统兼容) ### 注意事项 1. 考虑使用 `ScheduledExecutorService` 实现更精确的定时调度[^4] ```java ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(() -> callRemoteService(api), 0, 3, TimeUnit.SECONDS); ``` 2. 在异步编程中(如CompletableFuture),使用: ```java CompletableFuture.runAsync(() -> { callRemoteService(); Thread.sleep(3000); }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值