HttpClient配置及使用

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(); //全部从等待中唤醒.执行关闭操作;
		}
	}
}

使用

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.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.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; // 请求的API
	@Autowired
	private RequestConfig requestConfig; // 控制请求的超时时间

	/*
	 * 业务分析: 1. 参数说明: 1).url的地址 2).Map<String,String> 3).封装字符集 2.返回值:String类型的JSON数据
	 * 3. get请求分析 id = 1 name = tomcat url1:http://xxx.xx.com/xx?id=1&name=tomcat
	 * url2:http://xxx.xx.com/xx
	 */

	public String doGet(String url, Map<String, String> params, String charset) {
		// 1.判断用户是否传递了字符集
		if (StringUtils.isEmpty(charset)) {
			charset = "UTF-8";
		}
		// 2.判断用户是否传递了参数
		if (params != null) { // 如果有参数则需要字符串的拼接
			url += "?"; // http://xxx.xx.com/xx?
			for (Map.Entry<String, String> entry : params.entrySet()) {
				String key = entry.getKey();
				String value = entry.getValue();
				url += key + "=" + value + "&";
			}
			// 去除多余的&
			url = url.substring(0, url.length() - 1);
		}
		//3.定义请求对象  发起请求
		HttpGet httpGet = new HttpGet(url);
		//4.设定请求的超时时间
		httpGet.setConfig(requestConfig);
		
		//5.发起请求
		try {
			CloseableHttpResponse response = httpClient.execute(httpGet);
			int status = response.getStatusLine().getStatusCode();
			if(status == 200) {
				//表示请求正常
				String result = EntityUtils.toString(response.getEntity(),charset);
				return result;
			}else {
				throw new RuntimeException("请求状态异常:"+status+":"+url);
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	public String doGet(String url) {
		return doGet(url, null, null);
	}
	
	public String doGet(String url,Map<String,String> params) {
		return doGet(url, params, null);
	}
	

	// 实现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);
	}

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

		// 1.定义请求类型
		HttpPost post = new HttpPost(url);
		post.setConfig(requestConfig); // 定义超时时间
		post.setHeader("Content-type","application/json");
		// 2.判断字符集是否为null
		if (StringUtils.isEmpty(charset)) {
			charset = "UTF-8";
		}

		if (headers != null){
			for (Map.Entry<String, String> head : headers.entrySet()) {
				post.setHeader(head.getKey(),head.getValue());
			}
		}

		// 3.判断用户是否传递参数
		if (StringUtils.isNotBlank(jsonParam)) {
			// 3.1模拟表单提交
			try {
				StringEntity stringEntity = new StringEntity(jsonParam,charset);
				stringEntity.setContentEncoding(charset);  //设置编码格式
				// 发送Json格式的数据请求
				stringEntity.setContentType("application/json");
				post.setEntity(stringEntity);
			} catch (Exception 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;
	}

}

测试

	@Autowired
	private HttpClientService httpClientService;
	
	@Test
	public void test2() {
		Map<String,String> params = new HashMap<>();
		params.put("id", "12");
		params.put("name", "完蛋了!!");
		String result = httpClientService.doGet("http://www.baidu.com", params, null);
		System.out.println(result);
	}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值