HttpClient跨域访问技术(导一个依赖,两个配置类,一个工具类,最后是怎么运用)


		
			org.apache.httpcomponents
			httpclient
		

httpClient.properties配置文件

#最大连接数
http.maxTotal = 1000
#并发数
http.defaultMaxPerRoute = 20
#创建连接的最长时间
http.connectTimeout=5000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=5000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true

HttpClientConfig配置类,写在配置包中

@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
	 */
	@SuppressWarnings("deprecation")
	@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();
	}
}

(3)HttpClientClose配置类,写在配置包中


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

工具类,防止工具包中


/**工具类:通过此工具类实现服务器之间的 “跨域访问”,有doGet,doPost 注意:配置*/
@Service
public class HttpClientService {
	@Autowired//通过连接池HttpClientBuilder,用于获取httpClient
	private CloseableHttpClient httpClient;
	@Autowired//设定请求的超时时间等
	private RequestConfig requestConfig;

	public String doGet(String url,Map params,String charset){
		String result = null;
		//1.判断字符集编码是否为空 如果为空则给定默认值utf-8
		if(StringUtils.isEmpty(charset)) {
			charset="UTF-8";
		}
		/**
		 * 2.http://manage.jt.com/items/10010
		 *   http://manage.jt.com/items/10010?id=1&name=xxx
		 *   判断用户是否传递参数.
		 *   Map>
		 */
		if(params!=null) {
			url+="?";//第一步拼接?号
			for (Map.Entry enty : params.entrySet()) {
				String key = enty.getKey();
				String value = enty.getValue();
				url+=key+"="+value+"&";
			}
			//去除多余的&符
			url=url.substring(0, url.length()-1);
		}
		
		//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 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 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 parameters = 
					new ArrayList<>();

			//3.3将数据封装到List集合中
			for (Map.Entry 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 params){

		return doPost(url, params, null);
	}

	public String doPost(String url,String charset){

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

测试实践类

public class ItemServiceImpl implements ItemService{

	@Autowired
	private HttpClientService httpClient;
	
	@CacheFind
	@Override//前台服务器jt-web模拟HTTP协议,发送地址到后台服务器jt-manage取数据,然后返回给前台jt-web
	public Item findItemById(Long itemId) {
		String url="http://manage.jt.com/web/item/findItemById";
		Map params = new HashMap<>();
		params.put("itemId", itemId+"");
		String json = httpClient.doGet(url, params);
		
		return ObjectMapperUtill.toObject(json, Item.class);
	}
	
	@CacheFind
	@Override//前台服务器jt-web模拟HTTP协议,发送地址到后台服务器jt-manage取数据,然后返回给前台jt-web
	public ItemDesc findItemDescById(Long itemId) {
		String url="http://manage.jt.com/web/item/findItemDescById";
		Map params = new HashMap<>();
		params.put("itemId", itemId+"");
		String json = httpClient.doGet(url, params);
		
		return ObjectMapperUtill.toObject(json, ItemDesc.class);
	}

}

你可能感兴趣的:(跨域访问技术)