1、HttpClient的用法简介
关于JavaScript跨域的请求,可以在后台使用HttpClient去请求,再把请求结果发回给前台。已解决JavaScript跨域访问的问题。
2、HttpClient与Spring的整合文件
2.1 httpclient.properties的配置
#设置最大连接数
http.maxTotal=200
#设置每个主机的并发数
http.defaultMaxPerRoute=20
#创建连接的最长时间
http.connectTimeout=1000
#从连接池中获取到连接的最长时间
http.connectionRequestTimeout=500
#数据传输的最长时间
http.socketTimeout=10000
#提交请求前测试连接是否可用
http.staleConnectionCheckEnabled=true
2.2 log4j.properties的配置
log4j.rootLogger=DEBUG,A1
log4j.logger.com.taotao = DEBUG
log4j.logger.org.mybatis = DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
2.3 bean-properties.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 使用spring自带的占位符替换功能 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:httpclient.properties</value>
</list>
</property>
</bean>
<!--需要扫描的package -->
<context:component-scan base-package="com.web.service" />
</beans>
2.4 bean-httpclient.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--创建httpclient的连接池 -->
<bean id="httpClientConnectionManager"
class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager"
destroy-method="shutdown">
<!-- 设置最大连接数 -->
<property name="maxTotal" value="${http.maxTotal}" />
<!-- 设置每个主机的并发数 -->
<property name="defaultMaxPerRoute" value="${http.defaultMaxPerRoute}" />
</bean>
<!-- 创建httpClient对象 -->
<!-- httpClient是由HttpClientBuilder通过build方法创建,这个可以设置连接池 -->
<!-- 1.创建HttpClientBuilder -->
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder">
<!--设置连接池 -->
<property name="connectionManager" ref="httpClientConnectionManager"></property>
</bean>
<!-- 2.创建httpClient -->
<!-- 通过httpClientBulider得到httpClient对象,并且设置httpClient为多利模式 -->
<!-- 要保证httpClient为多利,以为每次都是新的http请求 -->
<bean id="httpClient" class="org.apache.http.impl.client.CloseableHttpClient"
factory-bean="httpClientBuilder" factory-method="build" scope="prototype" />
<!-- 构造请求参数 -->
<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">
<!-- 创建连接的最长时间 -->
<property name="connectTimeout" value="${http.connectTimeout}" />
<!-- 从连接池中获取到连接的最长时间 -->
<property name="connectionRequestTimeout" value="${http.connectionRequestTimeout}" />
<!-- 数据传输的最长时间 -->
<property name="socketTimeout" value="${http.socketTimeout}" />
<!-- 提交请求前测试连接是否可用 -->
<property name="staleConnectionCheckEnabled" value="${http.staleConnectionCheckEnabled}" />
</bean>
<bean id="requestConfig" class="org.apache.http.client.config.RequestConfig"
factory-bean="requestConfigBuilder" factory-method="build" />
<!--清理无效的http连接 -->
<bean class="com.web.service.IdleConnectionEvictor"
destroy-method="shutdown">
<constructor-arg index="0" ref="httpClientConnectionManager"></constructor-arg>
</bean>
</beans>
3、 封装了HttpClient操作的HttpService.java的实现
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
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;
@Service
public class HttpService {
// 创建Httpclient对象
@Autowired(required = false)
private CloseableHttpClient httpClient;
// 请求信息的配置
@Autowired(required = false)
private RequestConfig requestConfig;
/**
* 执行Get请求
*
* @param url
* @return 请求到的内容
* @throws URISyntaxException
* @throws IOException
* @throws ClientProtocolException
*/
public String doGet(String url) throws URISyntaxException,
ClientProtocolException, IOException {
return doGet(url, null);
}
/**
* 执行Get请求
*
* @param url
* @param params
* 请求中的参数
* @return 请求到的内容
* @throws URISyntaxException
* @throws IOException
* @throws ClientProtocolException
*/
public String doGet(String url, Map<String, Object> params)
throws URISyntaxException, ClientProtocolException, IOException {
// 定义请求的参数
URI uri = null;
if (params != null) {
URIBuilder builder = new URIBuilder(url);
for (Map.Entry<String, Object> entry : params.entrySet()) {
builder.addParameter(entry.getKey(),
String.valueOf(entry.getValue()));
}
uri = builder.build();
}
// 创建http GET请求
HttpGet httpGet = null;
if (uri != null) {
httpGet = new HttpGet(uri);
} else {
httpGet = new HttpGet(url);
}
// 设置请求参数
httpGet.setConfig(this.requestConfig);
// 请求的结果
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpClient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
// 获取服务端返回的数据,并返回
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
} finally {
if (response != null) {
response.close();
}
}
return null;
}
/**
*
* @param url
* @param params
* 请求中的参数
* @return 请求到的内容
* @throws URISyntaxException
* @throws ClientProtocolException
* @throws IOException
*/
public String doPost(String url, Map<String, Object> params)
throws URISyntaxException, ClientProtocolException, IOException {
// 设置post参数
List<NameValuePair> parameters = null;
// 构造一个form表单式的实体
UrlEncodedFormEntity formEntity = null;
// 定义请求的参数
if (params != null) {
// 设置post参数
parameters = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
// 添加参数
parameters.add(new BasicNameValuePair(entry.getKey(), String
.valueOf(entry.getValue())));
}
// 构造一个form表单式的实体
formEntity = new UrlEncodedFormEntity(parameters);
}
// 创建http GET请求
HttpPost httpPost = null;
if (formEntity != null) {
httpPost = new HttpPost(url);
// 将请求实体设置到httpPost对象中
httpPost.setEntity(formEntity);
// 伪装浏览器请求
httpPost.setHeader(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36");
} else {
httpPost = new HttpPost(url);
// 伪装浏览器请求
httpPost.setHeader(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36");
}
// 设置请求参数
httpPost.setConfig(this.requestConfig);
// 请求的结果
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpClient.execute(httpPost);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
// 获取服务端返回的数据,并返回
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
} finally {
if (response != null) {
response.close();
}
}
return null;
}
/**
*
* @param url
* @param params
* 请求中的参数
* @return 请求到的内容
* @throws URISyntaxException
* @throws ClientProtocolException
* @throws IOException
*/
public String doPost(String url) throws URISyntaxException,
ClientProtocolException, IOException {
return doPost(url, null);
}
}
@Autowired(required = false)表示的含义是,spring容器里面有这个bean就注入,没有就不注入。
4、 用于清除无效请求IdleConnectionEvictor.java的实现
import org.apache.http.conn.HttpClientConnectionManager;
//关闭连接池的无效链接
public class IdleConnectionEvictor extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {
this.connMgr = connMgr;
this.start();// 启动线程
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
// 每隔5秒执行一个,关闭失效的http连接
wait(5000);
// 关闭失效的连接
connMgr.closeExpiredConnections();
}
}
} catch (InterruptedException ex) {
// 结束
}
}
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
5、 测试代码
public class TestApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:spring/bean-*.xml");
System.out.println(context);
HttpService httpService = context.getBean("httpService",
HttpService.class);
System.out.println(httpService);
try {
// Map<String, String> maps = new HashMap<String, String>();
// maps.put("wd", "java");
// String string = httpService.doGet("http://www.baidu.com/s");
// System.out.println(string);
Map<String, Object> maps = new HashMap<String, Object>();
maps.put("wd", "java");
String string = httpService.doPost(
"http://localhost:8080/ssss/HaHaServlet", maps);
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、源码下载