在spring MVC中,大多数时候是由客户端的页面通过ajax等方式向controller发送请求,但有时候需要在java代码中直接向controller发送请求,这时可以使用HttpCilent实现。
首先用到的包是httpclient-4.3.5.jar和httpcore-4.3.2.jar
先看下面代码:
package module.system.common; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; 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.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; /** * 在java中处理http请求. * @author nagsh * */ public class HttpDeal { /** * 处理get请求. * @param url 请求路径 * @return json */ public String get(String url){ //实例化httpclient CloseableHttpClient httpclient = HttpClients.createDefault(); //实例化get方法 HttpGet httpget = new HttpGet(url); //请求结果 CloseableHttpResponse response = null; String content =""; try { //执行get方法 response = httpclient.execute(httpget); if(response.getStatusLine().getStatusCode()==200){ content = EntityUtils.toString(response.getEntity(),"utf-8"); System.out.println(content); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; } /** * 处理post请求. * @param url 请求路径 * @param params 参数 * @return json */ public String post(String url,Map<String, String> params){ //实例化httpClient CloseableHttpClient httpclient = HttpClients.createDefault(); //实例化post方法 HttpPost httpPost = new HttpPost(url); //处理参数 List<NameValuePair> nvps = new ArrayList <NameValuePair>(); Set<String> keySet = params.keySet(); for(String key : keySet) { nvps.add(new BasicNameValuePair(key, params.get(key))); } //结果 CloseableHttpResponse response = null; String content=""; try { //提交的参数 UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, "UTF-8"); //将参数给post方法 httpPost.setEntity(uefEntity); //执行post方法 response = httpclient.execute(httpPost); if(response.getStatusLine().getStatusCode()==200){ content = EntityUtils.toString(response.getEntity(),"utf-8"); System.out.println(content); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; } public static void main(String[] args) { HttpDeal hd = new HttpDeal(); hd.get("http://localhost:8080/springMVC/userType/getAll.do"); Map<String,String> map = new HashMap(); map.put("id","1"); hd.post("http://localhost:8080/springMVC/menu/getChildren.do",map); } }这个类里的get和post方法分别可以实现get请求和post请求,如果单单在一个java测试类里边运行是没问题的,但在controller或jsp中调用,会抛异常。为什么呢?由于是在springMVC中,所以,我们应该把它交给spring来管理。
首先是:httpClient-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置占位符 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:/httpclient.properties" /> </bean> <!-- 定义httpclient连接池 --> <bean id="httpClientConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" destroy-method="close"> <!-- 设置连接总数 --> <property name="maxTotal" value="${http.pool.maxTotal}"></property> <!-- 设置每个地址的并发数 --> <property name="defaultMaxPerRoute" value="${http.pool.defaultMaxPerRoute}"></property> </bean> <!-- 定义 HttpClient工厂,这里使用HttpClientBuilder构建--> <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"> <property name="connectionManager" ref="httpClientConnectionManager"></property> </bean> <!-- 得到httpClient的实例 --> <bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build"/> <!-- 定期清理无效的连接 --> <bean class="module.system.common.IdleConnectionEvictor" destroy-method="shutdown"> <constructor-arg index="0" ref="httpClientConnectionManager" /> <!-- 间隔一分钟清理一次 --> <constructor-arg index="1" value="60000" /> </bean> <!-- 定义requestConfig的工厂 --> <bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder"> <!-- 从连接池中获取到连接的最长时间 --> <property name="connectionRequestTimeout" value="${http.request.connectionRequestTimeout}"/> <!-- 创建连接的最长时间 --> <property name="connectTimeout" value="${http.request.connectTimeout}"/> <!-- 数据传输的最长时间 --> <property name="socketTimeout" value="${http.request.socketTimeout}"/> <!-- 提交请求前测试连接是否可用 --> <property name="staleConnectionCheckEnabled" value="${http.request.staleConnectionCheckEnabled}"/> </bean> <!-- 得到requestConfig实例 --> <bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" /> </beans>
#从连接池中获取到连接的最长时间 http.request.connectionRequestTimeout=500 #5000 http.request.connectTimeout=5000 #数据传输的最长时间 http.request.socketTimeout=30000 #提交请求前测试连接是否可用 http.request.staleConnectionCheckEnabled=true #设置连接总数 http.pool.maxTotal=200 #设置每个地址的并发数 http.pool.defaultMaxPerRoute=100
package module.system.common; import org.apache.http.conn.HttpClientConnectionManager; /** * 定期清理无效的http连接 */ public class IdleConnectionEvictor extends Thread { private final HttpClientConnectionManager connMgr; private Integer waitTime; private volatile boolean shutdown; public IdleConnectionEvictor(HttpClientConnectionManager connMgr,Integer waitTime) { this.connMgr = connMgr; this.waitTime = waitTime; this.start(); } @Override public void run() { try { while (!shutdown) { synchronized (this) { wait(waitTime); // 关闭失效的连接 connMgr.closeExpiredConnections(); } } } catch (InterruptedException ex) { // 结束 } } /** * 销毁释放资源 */ public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } } }重新部署一下,就可以在controller里实例化HttpDeal类并调用它的方法了。我的spring MVC整合了json,所以返回值是json数据,比如:
[{"id":1,"type":"管理员","menu":"1,2,3"},{"id":2,"type":"操作员","menu":"1,2,"}] [{"id":4,"attributes":null,"children":[],"text":"用户管理","pid":1,"url":"../user/getPage.do","title":null,"ptext":"系统管理"},{"id":5,"attributes":null,"children":[],"text":"部门管理","pid":1,"url":"../department/getPage.do","title":null,"ptext":"系统管理"},{"id":10,"attributes":null,"children":[],"text":"权限管理","pid":1,"url":"../userType/getPage.do","title":null,"ptext":"系统管理"}]