http方式调用接口服务方法

一、使用步骤

调用其他服务方法时,除了dubbo、rmq等方式外,还可以采取http方式调取对方服务的url,获取响应数据,可以采用HttpClient或CloseableHttpClient等接口实现http调用请求

使用HttpClient发送请求的一般步骤 ,如下所示:

(1)进行http连接配置,包括请求超时时间、读取响应时间、重试次数,最大请求数等配置

(2)根据请求方式和参数创建对应的http对象。有HttpPost、HttpGet创建请求方式方法,对于HttpPost对象而言,可调用setEntity(HttpEntity entity)方法来设置请求参数,HttpGet参数需要设置在url上

(3)创建HttpClient/CloseableHttpClient对象发送Http请求。调用HttpClient/CloseableHttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

(4) 创建HttpResponse/CloseableHttpResponse对象接受返回对象。

(5)解析返回对象HttpResponse/CloseableHttpResponse参数。调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse/CloseableHttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。 (6)释放连接。无论执行方法是否成功,都必须释放连接

下面分别介绍使用HTTPClient和CloseableHTTPClient进行Get和Post请求的方式。

二、使用方法

1.准备条件

创建HttpClientUtil工具类,加载http连接配置文件

public static final String                                encoding;
    private static final PoolingHttpClientConnectionManager    connectionManager;
    private static final CloseableHttpClient                httpClient;
    private static RequestConfig                            defaultRequestConfig;
    private static final int                                defaultConnectTimeout;
    private static final int                                defaultSocketTimeout;
    
    static {
        Properties p = new Properties();
        InputStream inputStream = null;
        try {
            inputStream = HttpClientUtil.class.getClassLoader().getResourceAsStream("config/httputil.properties");
            log.info("获取到http连接配置");
            p.load(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
        //获取编码方式
        encoding = p.getProperty("http.content.encoding");
        //每个http请求连接接超时时间,可自己配置
        defaultConnectTimeout = Integer.valueOf(p.getProperty("http.connection.timeout"));
        //读取数据超时时间
        defaultSocketTimeout = Integer.valueOf(p.getProperty("http.so.timeout"));
        connectionManager = new PoolingHttpClientConnectionManager();
        // http最大连接数
        connectionManager.setMaxTotal(Integer.parseInt(p.getProperty("http.max.total.connections")));
        // 每个路由基础的最大连接
connectionManager.setDefaultMaxPerRoute(Integer.parseInt(p.getProperty("http.default.max.connections.per.host")));
        SocketConfig defaultSocketConfig = SocketConfig.custom().setSoTimeout(defaultSocketTimeout)
                .setTcpNoDelay(Boolean.parseBoolean(p.getProperty("http.tcp.no.delay"))).build();
        connectionManager.setDefaultSocketConfig(defaultSocketConfig);
        //设置重试次数。默认为3次
        httpClient = HttpClients.custom().setConnectionManager(connectionManager)
                .setRetryHandler(new DefaultHttpRequestRetryHandler(Integer.parseInt(p.getProperty("retryCount")), false)).build();
        defaultRequestConfig = RequestConfig.custom().setSocketTimeout(defaultSocketTimeout).setConnectTimeout(defaultConnectTimeout)
                .setConnectionRequestTimeout(defaultConnectTimeout).build();
    }

配置文件httputil.properties如下所示:

# \u8FDE\u63A5\u8D85\u65F6
http.connection.timeout=10000
# \u5E94\u7B54\u8D85\u65F6
http.so.timeout=50000
# \u7F51\u7EDC\u53C2\u6570
http.stale.check.enabled=true
http.tcp.no.delay=true
http.default.max.connections.per.host=100
http.max.total.connections=1000
# \u5B57\u7B26\u96C6
http.content.encoding=utf-8
retryCount=3

2.post方式传递参数

1)创建HttpPost对象

再添加连接超时时间配置,然后将请求参数根据编码方式封装在Entity里面。NameValuePair接收参数。用于http封装请求参数,将map中name-value转换为NameValuePair数组对象,然后通过UrlEncodedFormEntity将之转换为HttpEntity对象

public static String post(String httpUrl, Map<String, String> maps, String encoding, int socketTimeout) throws IOException {
   // 创建httpPost
   HttpPost httpPost = new HttpPost(httpUrl);
    //网络超时设置
   addHttpRequestConfig(httpPost, socketTimeout);

   // 创建参数队列
   List<NameValuePair> nameValuePairs = Lists.newArrayList();
   for (String key : maps.keySet()) {
      nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
   }
    //将参数转换为固定格式
   httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, encoding));

   return sendHttpPost(httpPost);
}

也可以使用json方式请求,创建StringEntity对象,存放json类型的字符串数据

public static String postJson(String httpUrl, String json, int socketTimeout) throws IOException {
   // 创建httpPost
   HttpPost httpPost = new HttpPost(httpUrl);

   addHttpRequestConfig(httpPost, socketTimeout);

   // 设置参数
   StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);

   httpPost.setEntity(stringEntity);
   return sendHttpPost(httpPost);
}

2)发送http请求

封装好数据和定义好请求方式后,创建CloseableHttpClient或Httpclient对象来执行http连接,通过CloseableHttpResponse对象来接受返回对象

private static String sendHttpPost(HttpPost httpPost) throws IOException {
   CloseableHttpResponse response = null;
   String responseContent = null;
   try {
      // 执行请求
      response = httpClient.execute(httpPost);

      responseContent = extractReponseContent(response);
   } finally {
           //关闭请求连接
             if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                log.error( "关闭连接失败");
            }
        }
   }
   return responseContent;
}

3)解析请求返回数据

private static String extractReponseContent(CloseableHttpResponse response) throws IOException {
   HttpEntity entity;
   int statusCode = response.getStatusLine().getStatusCode();
   if (200 != statusCode) {
      throw new RuntimeException("请求错误,statusCode:" + statusCode);
   }
   entity = response.getEntity();
   return EntityUtils.toString(entity, encoding);
}

3.Get方式请求

1)创建HttpGet对象

有参数的话需要封装在url里面

public static String get(String url, Map<String, String> paramMap, String encoding, int socketTimeout)
      throws IOException, URISyntaxException {
   // 创建参数队列
   List<NameValuePair> nameValuePairs = Lists.newArrayList();
   for (String key : paramMap.keySet()) {
      nameValuePairs.add(new BasicNameValuePair(key, paramMap.get(key)));
   }
   // Get请求
   HttpGet httpGet = new HttpGet(url);

   // 设置参数
   addHttpRequestConfig(httpGet,socketTimeout);

   // 设置参数
   String str = EntityUtils.toString(new UrlEncodedFormEntity(nameValuePairs, encoding));
   httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + str));

   return sendHttpGet(httpGet);
}

2)发送HttpGet请求和解析请求同2.2、2.3

 

三、实验测试

前提需要开通http请求接口的服务

创建请求参数并发送http请求

这里使用post方式传递参数,并用json格式传递,读取超时时间为5000ms

@Test
public void testHttpClient(){

    UserQueryReqVO reqVO=new UserQueryReqVO();
    reqVO.setAccount("11119844");
    final String jsonReqVO= JSON.toJSONString(reqVO);

    int timeoutSeconds=5;
    log.info("开始http调用");
    String response = null;
    String url="http://10.45.40.199:8080/user/query";
    long startTime = System.currentTimeMillis();
    try {
        //注意调用的http请求方法,get用get请求方式,post用post或者postJson方式,视请求方式和参数而定,返回的数据已拆分为纯数据
        response = HttpClientUtil.postJson(url,jsonReqVO,timeoutSeconds * SystemConstant.ONE_SECOND_MILLISECONDS);
    }catch (Exception e){
        long endTime = System.currentTimeMillis();
        log.error("调用http接口超时,耗时=[{}]",endTime-startTime,e);
        throw new BizException(ResponseCode.CONNECTION_TIMEOUT);
    }

    Response res=JsonUtil.toObject(response,Response.class);
    log.info("数据:{}",JsonUtil.toJsonString(res));
    List<User> list=null;
    if (res.getCode().equals("0")){
        System.out.println("获取数据成功!"+JsonUtil.toJsonString(res));
        list=( List<User>)res.getData();
        System.out.println("数据为:"+list);
    }else {
        log.error("未获取到http数据");
        System.out.println("获取数据失败"+JsonUtil.toJsonString(res));
    }
}

 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值