spring+httpclient完美集成,封装常用客户端工具类

spring+httpclient完美集成,封装常用客户端工具类

1.导入依赖

  
<spring.version>4.0.2.RELEASEspring.version>  

<httpclient.version>4.5.2httpclient.version>
  
<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-coreartifactId>  
    <version>${spring.version}version>  
dependency>
<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-beansartifactId>  
    <version>${spring.version}version>  
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-ormartifactId>  
    <version>${spring.version}version>  
dependency>


  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-oxmartifactId>  
    <version>${spring.version}version>
    
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions> 
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-txartifactId>  
    <version>${spring.version}version>  
    
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions>
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-jdbcartifactId>  
    <version>${spring.version}version>
    
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions>  
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-webmvcartifactId>  
    <version>${spring.version}version>  
    
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions> 
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-aopartifactId>  
    <version>${spring.version}version>  
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions> 
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-context-supportartifactId>  
    <version>${spring.version}version>  
    <exclusions>  
        <exclusion>  
            <groupId>org.springframeworkgroupId>  
            <artifactId>spring-beansartifactId>  
        exclusion>  
    exclusions>
dependency>  

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-jmsartifactId>  
    <version>${spring.version}version>  
dependency>

<dependency>  
    <groupId>org.springframeworkgroupId>  
    <artifactId>spring-testartifactId>  
    <version>${spring.version}version>  
dependency>

<dependency>
    <groupId>org.apache.httpcomponentsgroupId>
    <artifactId>httpclientartifactId>
    <version>${httpclient.version}version>
dependency>

2.spring-httpclient.xml


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

    
    <bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
        <property name="connectionManager" ref="httpClientConnectionManager">property>
    bean>

    
    <bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build"/>

    
    <bean class="com.ssm.common.http.ClearConnectionsHandler" destroy-method="shutdown">
        <constructor-arg index="0" ref="httpClientConnectionManager"/>
    bean>

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

    
    <bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />

beans>

3.httpclient.properties

#从连接池中获取到连接的最长时间
http.request.connectionRequestTimeout=500
#设置链接超时
http.request.connectTimeout=5000
#数据传输的最长时间
http.request.socketTimeout=30000
#提交请求前测试连接是否可用
http.request.staleConnectionCheckEnabled=true
#设置连接总数
http.pool.maxTotal=200
#设置每个地址的并发数
http.pool.defaultMaxPerRoute=100
#设置定时清除无效链接时间
http.maxIdleTime=1

封装代码
1.HttpClient响应实体,还可以拓展响应体内容,主要就是这2个了

package com.ssm.common.http;

import java.io.Serializable;

/**
 * HttpClient响应实体
 * @autho 董杨炀
 * @time 2017年5月8日 下午3:35:26
*/
public class HttpResult implements Serializable{

    private static final long serialVersionUID = 1L;

    /**
     * 状体码
     */
    private Integer statusCode;

    /**
     * 响应内容
     */
    private String content;

    public HttpResult(){

    }

    public HttpResult(Integer statusCode, String content) {
        this.statusCode = statusCode;
        this.content = content;
    }

    /** 
     * 获取状体码
     * @return 状体码 
     */
    public Integer getStatusCode() {
        return statusCode;
    }


    /** 
     * 设置状体码 
     * @param statusCode 状体码 
     */
    public void setStatusCode(Integer statusCode) {
        this.statusCode = statusCode;
    }


    /** 
     * 获取响应内容
     * @return 响应内容 
     */
    public String getContent() {
        return content;
    }


    /** 
     * 设置响应内容 
     * @param content 响应内容 
     */
    public void setContent(String content) {
        this.content = content;
    }

    /**
     * @autho 董杨炀
     * @time 2017年5月8日 下午3:37:23
     * @return
     */
    @Override
    public String toString() {
        return "HttpResult [statusCode=" + statusCode + ", content=" + content + "]";
    }

}

2.定义暴露出来的httpClient操作对象.此对象实现spring的BeanFactoryAware接口.

实现BeanFactoryAware接口,重写setBeanFactory方法可以拥有BeanFactory对象,也就是springIOC的核心容器工厂.通过该工厂可以获取IOC容器管理的所有bean
package com.ssm.common.http;

import java.io.IOException;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ssm.utils.StringUtils;

/**
 * @autho 董杨炀
 * @time 2017年5月8日 下午3:22:09
 */
@Component("httpClientOperate")
public class HttpClientOperate implements BeanFactoryAware{

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    /**
     * 将required设置为false:
     * 为了避免RequestConfig没被注进来的时候其他方法都不能用,报createbeanfailedexception
     * 
     */
    @Autowired(required=false)
    private RequestConfig requestConfig;

    private CloseableHttpClient getHttpClient(){
        return this.beanFactory.getBean(CloseableHttpClient.class);
    }

    /**
     * 无参get请求
     * @autho 董杨炀
     * @time 2017年5月8日 下午3:30:08
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String doGet(String url) throws ClientProtocolException, IOException{
        // 创建http GET请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);//设置请求参数
        CloseableHttpResponse response = null;
        try {
            // 执行请求
            response = this.getHttpClient().execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                return content;
            }
        } finally {
            if (response != null) {
                response.close();
            }
            //httpclient.close();
        }
        return null;
    }

    /**
     * 有参get请求
     * @param url
     * @return
     * @throws URISyntaxException 
     * @throws IOException 
     * @throws ClientProtocolException 
     */
    public String doGet(String url , Map params) throws URISyntaxException, ClientProtocolException, IOException{
        URIBuilder uriBuilder = new URIBuilder(url);
        if(params != null){
            for(String key : params.keySet()){
                uriBuilder.setParameter(key, params.get(key));
            }
        }
        return this.doGet(uriBuilder.build().toString());
    }

    /**
     * 有参post请求
     * @autho 董杨炀
     * @time 2017年5月8日 下午3:32:48
     * @param url
     * @param params
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public HttpResult doPost(String url , Map params) throws ClientProtocolException, IOException{
        // 创建http POST请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        if(params != null){
            // 设置2个post参数,一个是scope、一个是q
            List parameters = new ArrayList(0);
            for(String key : params.keySet()){
                parameters.add(new BasicNameValuePair(key, params.get(key)));
            }
            // 构造一个form表单式的实体
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
            // 将请求实体设置到httpPost对象中
            httpPost.setEntity(formEntity);
        }
        CloseableHttpResponse response = null;
        try {
            // 执行请求
            response = this.getHttpClient().execute(httpPost);
            // 判断返回状态是否为200
            /*if (response.getStatusLine().getStatusCode() == 200) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                System.out.println(content);
            }*/
            return new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(), "UTF-8"));
        } finally {
            if (response != null) {
                response.close();
            }
            //httpclient.close();
        }
    }

    /**
     * 有参post请求,json交互
     * @autho 董杨炀
     * @time 2017年5月8日 下午3:33:01
     * @param url
     * @param json
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public HttpResult doPostJson(String url , String json) throws ClientProtocolException, IOException{
         // 创建http POST请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        if(StringUtils.isNotBlank(json)){
            //标识出传递的参数是 application/json
            StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
        }
        CloseableHttpResponse response = null;
        try {
            // 执行请求
            response = this.getHttpClient().execute(httpPost);
            // 判断返回状态是否为200
            /*if (response.getStatusLine().getStatusCode() == 200) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                System.out.println(content);
            }*/
            return new HttpResult(response.getStatusLine().getStatusCode(),EntityUtils.toString(response.getEntity(), "UTF-8"));
        } finally {
            if (response != null) {
                response.close();
            }
            //httpclient.close();
        }
    }

    /**
     * 无参post请求
     * @autho 董杨炀
     * @time 2017年5月8日 下午3:33:27
     * @param url
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public HttpResult doPost(String url) throws ClientProtocolException, IOException{
        return this.doPost(url, null);
    }
}

3.自定义类,利用线程定时扫描清理无效连接

package com.ssm.common.http;

import org.apache.http.conn.HttpClientConnectionManager;

/**
 * 自定义定时清理无效链接(httpclient)
 * @autho 董杨炀
 * @time 2017年5月8日 下午3:16:59
*/
public class ClearConnectionsHandler extends Thread{

    private final HttpClientConnectionManager connMgr;

    private volatile boolean shutdown;

    public ClearConnectionsHandler(HttpClientConnectionManager connMgr) {
        this.connMgr = connMgr;
        this.start();
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);
                    // 关闭失效的连接
                    connMgr.closeExpiredConnections();
                }
            }
        } catch (InterruptedException ex) {
            // 结束
        }
    }

    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }

}

客户端访问测试
1.直接启动ssm工程war测试,写一个bean实现InitializingBean接口,重写afterPropertiesSet()方法.

InitializingBean接口作用:在bean初始化完成之后自动执行afterPropertiesSet()方法

@Component:IOC容器扫描到此注解标记的class就会装载该bean
package com.ssm.common.http;

import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @autho 董杨炀
 * @time 2017年5月8日 下午4:25:54
*/
@Component
public class MyHttpTest implements InitializingBean{

    @Resource
    private HttpClientOperate httpClientOperate;

    /**
     * @autho 董杨炀
     * @time 2017年5月8日 下午4:26:20
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        //无参get请求
        String result = httpClientOperate.doGet("http://www.baidu.com");
        System.out.println(result);
        //有参get请求
        Map map = new HashMap<>();
        map.put("waybillNo", "12341223");
        String result2 = httpClientOperate.doGet("http://www.baidu.com", map);
        System.out.println(result2);
        //post请求
        HttpResult entity = httpClientOperate.doPost("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY");
        System.out.println(entity);
        //有参post请求
        HttpResult entity2 = httpClientOperate.doPost("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY", map);
        System.out.println(entity2);
        //有参post请求rest服务 JSON
        String json = "{\"waybillNo\":\"12341223\"}";
        HttpResult entity3 = httpClientOperate.doPostJson("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY",json);
        System.out.println(entity3);
    }
}

2.如果你没有去git检出改ssm项目.利用junit测试也可以.或者手动main启动spring容器加载配置来测试

package com.ssm.httptest;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ssm.common.http.HttpClientOperate;
import com.ssm.common.http.HttpResult;

/**
 * 手动启动spring容器测试
 * @autho 董杨炀
 * @time 2017年5月8日 下午3:55:10
*/
public class HttpClientTest {

    public static void main(String[] args) throws IOException, URISyntaxException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "spring-test.xml" });
        HttpClientOperate httpClientOperate = (HttpClientOperate)context.getBean("httpClientOperate");
        //无参get请求
        String result = httpClientOperate.doGet("http://www.baidu.com");
        System.out.println(result);
        //有参get请求
        Map map = new HashMap<>();
        map.put("waybillNo", "12341223");
        String result2 = httpClientOperate.doGet("http://www.baidu.com", map);
        System.out.println(result2);
        //post请求
        HttpResult entity = httpClientOperate.doPost("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY");
        System.out.println(entity);
        //有参post请求
        HttpResult entity2 = httpClientOperate.doPost("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY", map);
        System.out.println(entity2);
        //有参post请求rest服务 JSON
        String json = "{\"waybillNo\":\"12341223\"}";
        HttpResult entity3 = httpClientOperate.doPostJson("http://10.230.21.133:8180/esb2/rs/ESB_FOSS2ESB_FOSS_THE_RECEIVING_VERIFY",json);
        System.out.println(entity3);
    }
}

spring-test.xml


<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-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    
    <import resource="spring-httpclient.xml"/>

    
    <context:component-scan base-package="com.ssm.common.http"/>

    
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        
        <property name="locations">
            <list>
                <value>classpath:jdbc.propertiesvalue>
                <value>classpath:httpclient.propertiesvalue>
            list>
        property>
    bean>

    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${driver}">property>
        <property name="jdbcUrl" value="${url}">property>
        <property name="user" value="${username}">property>
        <property name="password" value="${password}">property>
    bean>
beans>

jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username=root
password=root
#定义初始连接数  
initialSize=10
#定义最大连接数  
maxActive=20
#定义最大空闲  
maxIdle=20
#定义最小空闲  
minIdle=1
#定义最长等待时间  
maxWait=60000

测试结果如下图:完美
spring+httpclient完美集成,封装常用客户端工具类_第1张图片

你可能感兴趣的:(javaEE)