加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 如何发送并行GET请求并等待结果响应?

发布时间:2020-12-14 05:34:51 所属栏目:Java 来源:网络整理
导读:我在 spring mvc 3.2.2中使用apache http客户端,如图所示同步发送5个get请求. 如何异步(并行)发送所有这些异常并等待请求返回,以便从所有GET请求返回解析的有效负载字符串? public String myMVCControllerGETdataMethod(){ // Send 1st request HttpClient
我在 spring mvc 3.2.2中使用apache http客户端,如图所示同步发送5个get请求.

如何异步(并行)发送所有这些异常并等待请求返回,以便从所有GET请求返回解析的有效负载字符串?

public String myMVCControllerGETdataMethod()
{
   // Send 1st request 
   HttpClient httpclient = new DefaultHttpClient();
   HttpGet httpget = new HttpGet("http://api/data?type=1");   
   ResponseHandler<String> responseHandler = new BasicResponseHandler();
   String responseBody = httpclient.execute(httpget,responseHandler);

   // Send 2st request 
   HttpClient httpclient2 = new DefaultHttpClient();
   HttpGet httpget2 = new HttpGet("http://api/data?type=2");   
   ResponseHandler2<String> responseHandler2 = new BasicResponseHandler();
   String responseBody2 = httpclient.execute(httpget,responseHandler2);

   // o o o more gets here

   // Perform some work here...and wait for all requests to return
   // Parse info out of multiple requests and return
   String results = doWorkwithMultipleDataReturned();

   model.addAttribute(results,results);
   return "index";

}

解决方法

通常,您需要将您的工作单元封装在Runnable或java.util.concurrent.Callable中,并通过java.util.concurrent.Executor(或org.springframework.core.task.TaskExecutor)执行它们.这允许每个单元的工作单独执行,通常以异步方式执行(取决于执行程序的实现).

所以对于你的具体问题,你可以这样做:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    //inject this
    private Executor executor;

    @RequestMapping("/your/path/here")
    public String myMVCControllerGETdataMethod(Model model) {
        //define all async requests and give them to injected Executor
        List<GetRequestTask> tasks = new ArrayList<GetRequestTask>();
        tasks.add(new GetRequestTask("http://api/data?type=1",this.executor));
        tasks.add(new GetRequestTask("http://api/data?type=2",this.executor));
        //...
        //do other work here
        //...
        //now wait for all async tasks to complete
        while(!tasks.isEmpty()) {
            for(Iterator<GetRequestTask> it = tasks.iterator(); it.hasNext();) {
                GetRequestTask task = it.next();
                if(task.isDone()) {
                    String request = task.getRequest();
                    String response = task.getResponse();
                    //PUT YOUR CODE HERE
                    //possibly aggregate request and response in Map<String,String>
                    //or do something else with request and response
                    it.remove();
                }
            }
            //avoid tight loop in "main" thread
            if(!tasks.isEmpty()) Thread.sleep(100);
        }
        //now you have all responses for all async requests

        //the following from your original code
        //note: you should probably pass the responses from above
        //to this next method (to keep your controller stateless)
        String results = doWorkwithMultipleDataReturned();
        model.addAttribute(results,results);
        return "index";
    }

    //abstraction to wrap Callable and Future
    class GetRequestTask {
        private GetRequestWork work;
        private FutureTask<String> task;
        public GetRequestTask(String url,Executor executor) {
            this.work = new GetRequestWork(url);
            this.task = new FutureTask<String>(work);
            executor.execute(this.task);
        }
        public String getRequest() {
            return this.work.getUrl();
        }
        public boolean isDone() {
            return this.task.isDone();
        }
        public String getResponse() {
            try {
                return this.task.get();
            } catch(Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    //Callable representing actual HTTP GET request
    class GetRequestWork implements Callable<String> {
        private final String url;
        public GetRequestWork(String url) {
            this.url = url;
        }
        public String getUrl() {
            return this.url;
        }
        public String call() throws Exception {
            return new DefaultHttpClient().execute(new HttpGet(getUrl()),new BasicResponseHandler());
        }
    }
}

请注意,此代码尚未测试.

对于您的Executor实现,请查看Spring’s TaskExecutor和task:executor namespace.您可能需要一个可重用的线程池用于此用例(而不是每次都创建一个新线程).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读