spring MVC 管理HttpClient---实现在java中直接向Controller发送请求

在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>

httpclient.properties:

#从连接池中获取到连接的最长时间
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

一个必须的类,几记得修改xml里的该类的路径:

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":"系统管理"}]

可以通过我另一篇文章http://blog.csdn.net/u012116457/article/details/24371877里的方法将json转为map等。

时间: 2024-10-11 11:47:37

spring MVC 管理HttpClient---实现在java中直接向Controller发送请求的相关文章

Spring MVC普通类或工具类中调用service报空空指针的解决办法(调用service报java.lang.NullPointerException)

当我们在非Controller类中应用service的方法是会报空指针,如图: 这是因为Spring MVC普通类或工具类中调用service报空null的解决办法(调用service报java.lang.NullPointerException) 按上述步骤解决完自己的工具类后,你会发现项目运行后仍然报空指针此时你需要在applicationContext.xml 配置文件中添加一行配置文件 如图: 对自己工具类所在的包进行注解扫描,使Spring能够识别自己上面所配置的注解 原文地址:htt

maven新建Spring MVC + MyBatis + Oracle的Web项目中pom.xml文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion&

java中使HttpDelete可以发送body信息

java中使HttpDelete可以发送body信息RESTful api中用到了DELETE方法,android开发的同事遇到了问题,使用HttpDelete执行DELETE操作的时候,不能携带body信息,研究了很久之后找到了解决方法. 我们查看httpclient-4.2.3的源码可以发现,methods包下面包含HttpGet, HttpPost, HttpPut, HttpDelete等类来实现http的常用操作. 其中,HttpPost继承自HttpEntityEnclosingRe

Spring Mvc Session超时easyui tab页中ajax请求跳出问题

<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射,添加拦截器,类级别的处理器映射 --> 拦截器配置 public class HandlerInterceptor1 extends HandlerInterceptorAdapter {//此处一般继承HandlerInterceptorAdapter适配器即可 @Override public boolean preHandle(HttpServletRequest request, HttpServletResp

Play framework框架中通过post方式发送请求

搞了好久这个最终还是在play官方文档中看见的发送请求的方式,国内好像很少有使用这个框架的,加之自己不是太愿意宣传,好东西总归是好东西,不说废话了. 在play中发送请求有两种常用的方式,一种get,一种post,当然,这里说的发送请求都是向第三方站点发送请求,而不是内部发送,内部当然不需要通过这种方式了. get方式: WS.url("url").setQueryParameter(arg0, arg1)..setQueryParameter(arg0, arg1).get(); 而

转:PHP中的使用curl发送请求(GET请求和POST请求)

原文地址:http://www.jb51.net/article/104974.htm 使用CURL发送请求的基本流程 使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤: 1.初始化连接句柄: 2.设置CURL选项: 3.执行并获取结果: 4.释放VURL连接句柄. 下面的程序片段是使用CURL发送HTTP的典型过程: // 1. 初始化 $ch = curl_init(); // 2. 设置选项,包括URL curl_setopt($ch,CURLOPT_URL,"http

Redis(2)用jedis实现在java中使用redis

昨天已经在windows环境下安装使用了redis. 下面准备在java项目中测试使用redis. redis官网推荐使用jedis来访问redis.所以首先准备了jedis的jar包,以及需要依赖的jar包. commons-pool2-2.3 hamcrest-core-1.3 jedis-2.7.2.jar 因为redis也是属于一种数据库,也是对数据的访问,所以把他放置在dao层,与service分开 import redis.clients.jedis.Jedis; import re

spring mvc将model存入到session中去

今天需要针对预览功能将参数通过window.open(url+参数)的方式请求后台方法,进行页面跳转,然而当参数太大时,通过url的方式会导致请求参数过长而失败.所以只能改用post方式,将参数以bean或者requestbosy的方式传递给controller,但是这种方会使原来能自动跳转的url不跳转,目前还没找到原因.通过redirect的方式会导致塞到model的参数无法获取,因此需要将model参数存入到session中去.参考了以下两篇原文,供大家参考. 原文参考:http://bl

Java中实现短信发送

最近跟着做公司的项目偶然接触到的,顺势把这个给记录下来,给自己梳理一下. 采用引入第三方工具的方式,网上查了半天,发现简单的实现方式便是注册一个中国网建的账号,新建账号的时候会附带赠几条免费短信,彩信 ,之后想要在使用就得花钱了.简单的操作流程如下. 网建的链接如下: http://www.smschinese.cn/api.shtml 手机号注册登陆成功之后页面如下: 如上页面可以看到我们之前发送的短息信息以及相关的剩余短信条数. 我们可以参考它那边提供的API接口文档,接入jar包,利用自己