HttpClient发起http请求

  • Java发http请求
    收到添加依赖
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
</dependency>

HttpGet请求测试代码

public class HttpGetTest{
    public static void main(String[] args) throws IOException {
        //实例化HttpClient实例
        CloseableHttpClient client = HttpClients.createDefault();
        //请求url
        String url = "https://www.baidu.com";
        HttpGet httpGet = new HttpGet(url);
        //添加请求头
        httpGet.addHeader("Content-Type", "application/json");
        httpGet.addHeader("Accept", "application/json");

        //发起请求
        CloseableHttpResponse response = client.execute(httpGet);
        //获得请求状态码
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            //获得请求实体
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, "utf-8");
            System.out.println(result);
            //获得所有请求头
            Header[] allHeaders = response.getAllHeaders();
            for (Header header : allHeaders) {
                //请求头名称
                String name = header.getName();
                //请求头值
                String value = header.getValue();
                System.out.println(name + ":" + value);
            }
        }
    }
}

HttpPost请求

package fmx.test.httptest;

import net.sf.json.JSONObject;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * @author fmx
 * @version 1.0
 * @date 2020/9/3 22:40
 */
public class HttpPostTest {
    public static void main(String[] args) throws IOException {
        //实例化HttpClient实例
        CloseableHttpClient client = HttpClients.createDefault();
        //请求url
        String url = "https://www.baidu.com";
        HttpPost httpPost = new HttpPost(url);
        //添加请求头
        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("Accept", "application/json");
        //请求数据
        Map<String, Object> map = new HashMap<>();
        JSONObject x = JSONObject.fromObject(map);
        String body = x.toString();
        StringEntity strEntity = new StringEntity(body, Charset.forName("UTF-8"));
        strEntity.setContentType("application/json");
        httpPost.setEntity(strEntity);
        //设置超时时间按
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(80000).setConnectTimeout(80000).build();
        httpPost.setConfig(requestConfig);
        //发起请求
        CloseableHttpResponse response = client.execute(httpPost);
        //获得请求状态码
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            //获得请求实体
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, "utf-8");
            System.out.println(result);
            //获得所有请求头
            Header[] allHeaders = response.getAllHeaders();
            for (Header header : allHeaders) {
                //请求头名称
                String name = header.getName();
                //请求头值
                String value = header.getValue();
                System.out.println(name + ":" + value);
            }
        }
    }
}


  • 接收请求(以微信支付回调为例)
@PostMapping("/payNotify")
    public JSONObject wxNotify(HttpServletRequest request, HttpServletResponse response, @RequestHeader HttpHeaders headers) {

        //返回通知的应答报文,code(32):SUCCESS为清算机构接收成功;message(64):错误原因
        JSONObject responseJson = new JSONObject();
        responseJson.put("code", "FAIL");
        //支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx。
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        if (!headers.containsKey("Wechatpay-Serial") || !headers.containsKey("Wechatpay-Timestamp")
                || !headers.containsKey("Wechatpay-Nonce") || !headers.containsKey("Wechatpay-Signature")) {
            log.info("请求头丢失");
            responseJson.put("message", "回调请求header缺失");
            return responseJson;
        }
        String wechatpaySerial = headers.getFirst("Wechatpay-Serial");//平台证书序列号
        String wechatpayTimestamp = headers.getFirst("Wechatpay-Timestamp");//应答时间戳
        String wechatpayNonce = headers.getFirst("Wechatpay-Nonce");//应答随机串
        String wechatpaySignature = headers.getFirst("Wechatpay-Signature"); //应答签名
        if (!MyWxPayConfig.WECHAT_CERTIFICATR_SERIAL_NO.equals(wechatpaySerial)) {
            responseJson.put("message", "回调请求证书序列化不一致");
            return responseJson;
        }
        log.info("WechatpaySignature{}", wechatpaySerial);
        log.info("WechatpayTimestamp{}", wechatpayTimestamp);
        log.info("WechatpayNonce{}", wechatpayNonce);
        log.info("WechatpaySignature{}", wechatpaySignature);


        try {
            //获取微信POST过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            // post请求的密文数据
            ServletInputStream in = request.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String sReqData = "";
            String itemStr = "";//作为输出字符串的临时串,用于判断是否读取完毕
            while (null != (itemStr = reader.readLine())) {
                sReqData += itemStr;
            }
            log.info("resultData{}", sReqData);
            //验签
            byte[] signature = null;
            try {
                signature = Base64.getDecoder().decode(wechatpaySignature);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("响应签名Base64解码失败");
                responseJson.put("message", "响应签名Base64解码失败");
                return responseJson;
            }
            boolean verify = WxPayUtils.verify(wechatpayTimestamp, wechatpayNonce, sReqData, signature);
            if (!verify) {
                log.info("回调信息签名验证失败");
                responseJson.put("message", "回调信息签名验证失败");
                return responseJson;
            }

            JSONObject jsonObject = JSONObject.fromObject(sReqData);
            Map<String, Object> m = (Map) jsonObject;
            if (m.get("event_type") == null || !m.get("event_type").equals("TRANSACTION.SUCCESS")) {
                //补充处理部分
                response.setStatus(HttpServletResponse.SC_OK);
                responseJson.put("code", "SUCCESS");
                responseJson.put("message", "微信支付失败,商户处理成功");
            }

            String resource = m.get("resource").toString();
            JSONObject resourcejso = JSONObject.fromObject(resource);
            Map<Object, Object> mm = (Map) resourcejso;
            String nonce = mm.get("nonce").toString();
            String ciphertext = mm.get("ciphertext").toString();
            String assc = mm.get("associated_data").toString();

            String APIv3Key = MyWxPayConfig.API_V3_KEY;
            //解密回调信息
            byte[] key = APIv3Key.getBytes("UTF-8");
            WxAPIV3AesUtil aesUtil = new WxAPIV3AesUtil(key);
            String decryptToString = aesUtil.decryptToString(assc.getBytes("UTF-8"), nonce.getBytes("UTF-8"), ciphertext);
            JSONObject decryption = JSONObject.fromObject(decryptToString);
            Map<String, Object> decryptionMap = (Map) decryption;
            System.out.println(decryptionMap);

            if (decryptionMap.get("transaction_id") == null) {
                log.info("未接受到微信订单号");
                responseJson.put("message", "微信支付成功,未接受到微信订单号");
                return responseJson;
            }
            if (decryptionMap.get("out_trade_no") == null) {
                log.info("未接收到商家订单号");
                responseJson.put("message", "微信支付成功,未接收到商家订单号");
                return responseJson;
            }

            String outTradeNo = decryptionMap.get("out_trade_no").toString();
            List<Integer> status = partyPaymentRecordService.getPaymentStatusByoutTradeNo(outTradeNo);
            boolean flag = false;
            if (status != null) {
                for (Integer sta : status) {
                    if (sta != null && sta != 0) {
                        flag = true;
                        break;
                    }
                }
            }
            if (flag) {
                response.setStatus(HttpServletResponse.SC_OK);
                responseJson.put("code", "SUCCESS");
                responseJson.put("message", "微信支付成功");
                return responseJson;
            }
//            statusCode
            decryptionMap.put("statusCode", "200");
            partyPaymentRecordService.trackOrder(decryptionMap, null);

            System.out.println(decryptToString);

        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("微信支付成功");
        response.setStatus(HttpServletResponse.SC_OK);
        responseJson.put("code", "SUCCESS");
        responseJson.put("message", "微信支付成功");
        return responseJson;
    }
}

  • 若在开发环境中,则需交给spring管理
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource(value = "classpath:/properties/httpClient.properties")
public class HttpClientConfig {
    @Value("${http.maxTotal}")
    private Integer maxTotal;                        //最大连接数

    @Value("${http.defaultMaxPerRoute}")
    private Integer defaultMaxPerRoute;                //最大并发链接数

    @Value("${http.connectTimeout}")
    private Integer connectTimeout;                    //创建链接的最大时间

    @Value("${http.connectionRequestTimeout}")
    private Integer connectionRequestTimeout;        //链接获取超时时间

    @Value("${http.socketTimeout}")
    private Integer socketTimeout;                    //数据传输最长时间

    @Value("${http.staleConnectionCheckEnabled}")
    private boolean staleConnectionCheckEnabled;    //提交时检查链接是否可用

    //定义httpClient链接池
    @Bean(name = "httpClientConnectionManager")
    public PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager() {
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
        manager.setMaxTotal(maxTotal);  //设定最大链接数
        manager.setDefaultMaxPerRoute(defaultMaxPerRoute);  //设定并发链接数
        return manager;
    }

    //定义HttpClient

    /**
     * 实例化连接池,设置连接池管理器。
     * 这里需要以参数形式注入上面实例化的连接池管理器
     *
     * @Qualifier 指定bean标签进行注入
     */
    @Bean(name = "httpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {

        //HttpClientBuilder中的构造方法被protected修饰,所以这里不能直接使用new来实例化一个HttpClientBuilder,可以使用HttpClientBuilder提供的静态方法create()来获取HttpClientBuilder对象
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(httpClientConnectionManager);
        return httpClientBuilder;
    }

    /**
     * 注入连接池,用于获取httpClient
     *
     * @param httpClientBuilder
     * @return
     */
    @Bean
    public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder") HttpClientBuilder httpClientBuilder) {

        return httpClientBuilder.build();
    }

    /**
     * Builder是RequestConfig的一个内部类
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * 设置builder的连接信息
     *
     * @return
     */
    @Bean(name = "builder")
    public RequestConfig.Builder getBuilder() {
        RequestConfig.Builder builder = RequestConfig.custom();
        return builder.setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout)
                .setStaleConnectionCheckEnabled(staleConnectionCheckEnabled);
    }

    /**
     * 使用builder构建一个RequestConfig对象
     *
     * @param builder
     * @return
     */
    @Bean
    public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder) {
        return builder.build();
    }
}

import javax.annotation.PreDestroy;

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component    //交给spring容器管理
public class HttpClientClose extends Thread {
    @Autowired
    private PoolingHttpClientConnectionManager manage;
    private volatile boolean shutdown;    //开关 volatitle表示多线程可变数据,一个线程修改,其他线程立即修改

    public HttpClientClose() {
        ///System.out.println("执行构造方法,实例化对象");
        //线程开启启动
        this.start();
    }


    @Override
    public void run() {
        try {
            //如果服务没有关闭,执行线程
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);            //等待5秒
                    //System.out.println("线程开始执行,关闭超时链接");
                    //关闭超时的链接
                    PoolStats stats = manage.getTotalStats();
                    int av = stats.getAvailable();    //获取可用的线程数量
                    int pend = stats.getPending();    //获取阻塞的线程数量
                    int lea = stats.getLeased();    //获取当前正在使用的链接数量
                    int max = stats.getMax();
                    //System.out.println("max/"+max+":	av/"+av+":  pend/"+pend+":   lea/"+lea);
                    manage.closeExpiredConnections();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

        super.run();
    }

    //关闭清理无效连接的线程
    @PreDestroy    //容器关闭时执行该方法.
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            //System.out.println("关闭全部链接!!");
            notifyAll(); //全部从等待中唤醒.执行关闭操作;
        }
    }
}

httpClient.properties

#最大连接数
http.maxTotal = 1000
#并发数
http.defaultMaxPerRoute = 20
#创建连接的最长时间
http.connectTimeout=5000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=5000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
  • 调用API
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class HttpClientService {
	@Autowired
	private CloseableHttpClient httpClient;
	@Autowired
	private RequestConfig requestConfig;

	/**
	 * 	编辑工具API的目的简化代码,实现松耦合 
	 * 	作用:帮助用户发起http请求,获取正确的结果返回给用户 参数设计:
	 * 1.用户url地址
	 * 2.Map<参数名,参数值 > 3.字符集
	 * 
	 * get请求方式: 1.无参数时:http://www.baidu.com 
	 * 2.有参数时:http://www.baidu.com?key=--
	 * 
	 * @param url
	 * @param params
	 * @param charset
	 * @return
	 */

	// 实现httpClient GET提交
	public String doGet(String url, Map<String, String> params, String charset) {
		String result = null;
		// 1.判断字符集编码是否为空 如果为空则给定默认值utf-8
		if (StringUtils.isEmpty(charset)) {

			charset = "UTF-8";
		}
		// 2.判断用户是否需要传递参数
		if (params != null) {
			try {
				URIBuilder uriBuilder = new URIBuilder(url);
				for (Map.Entry<String, String> entry : params.entrySet()) {

					uriBuilder.addParameter(entry.getKey(), entry.getValue());
				}
				// url?id=1&name=tom
				url = uriBuilder.build().toString();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// 3.定义参数提交对象
		HttpGet get = new HttpGet(url);

		// 4.为请求设定超时时间
		get.setConfig(requestConfig);

		// 5.通过httpClient发送请求
		try {
			CloseableHttpResponse response = httpClient.execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				// 表示程序调用成功
				result = EntityUtils.toString(response.getEntity(), charset);
			} else {
				System.out.println("调用异常:状态信息:" + response.getStatusLine().getStatusCode());
				throw new RuntimeException();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	public String doGet(String url) {

		return doGet(url, null, null);
	}

	public String doGet(String url, Map<String, String> params) {

		return doGet(url, params, null);
	}

	public String doGet(String url, String charset) {

		return doGet(url, null, charset);
	}

	// 实现httpClient POST提交
	public String doPost(String url, Map<String, String> params, String charset) {
		String result = null;

		// 1.定义请求类型
		HttpPost post = new HttpPost(url);
		post.setConfig(requestConfig); // 定义超时时间

		// 2.判断字符集是否为null
		if (StringUtils.isEmpty(charset)) {

			charset = "UTF-8";
		}

		// 3.判断用户是否传递参数
		if (params != null) {
			// 3.2准备List集合信息
			List<NameValuePair> parameters = new ArrayList<>();

			// 3.3将数据封装到List集合中
			for (Map.Entry<String, String> entry : params.entrySet()) {

				parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}

			// 3.1模拟表单提交
			try {
				UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, charset); // 采用u8编码

				// 3.4将实体对象封装到请求对象中
				post.setEntity(formEntity);
			} catch (UnsupportedEncodingException e) {

				e.printStackTrace();
			}
		}

		// 4.发送请求
		try {
			CloseableHttpResponse response = httpClient.execute(post);

			// 4.1判断返回值状态
			if (response.getStatusLine().getStatusCode() == 200) {

				// 4.2表示请求成功
				result = EntityUtils.toString(response.getEntity(), charset);
			} else {
				System.out.println("获取状态码信息:" + response.getStatusLine().getStatusCode());
				throw new RuntimeException();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;
	}

	public String doPost(String url) {

		return doPost(url, null, null);
	}

	public String doPost(String url, Map<String, String> params) {

		return doPost(url, params, null);
	}

	public String doPost(String url, String charset) {

		return doPost(url, null, charset);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值