HttpClient3.1一点说明

1.HttpClient使用时,最好让httpclient可以重用,可以创建一个HttpClient对象,然后在同步代码块中使用,或者使用连接池管理(推荐)。

2.HttpClient虽然可以重用,但是PostMethod(或GetMethod)不能重用,否则会出问题(类似总是Read timeout等)。

各种版本代码:

1.完整正确的代码(使用了连接池,并且每次连接都重新创建PostMethod对象,PostMethod对象使用完后关闭。测试没发生任何问题):

package com.handmessage.ups.shortmessageapi.send;


import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


import com.handmessage.ups.shortmessageapi.ShortMessageApiService;
import com.handmessage.ups.shortmessageapi.bean.ShortMessage;


public class SendCaptchaQueen {
    private static Logger logger = LogManager.getLogger(SendCaptchaQueen.class);
    
  
    static int requestTimeout = 10000;
    static int readTimeout = 15000;
static HttpClient client;
    static {
        HttpClientParams httpParameters = new HttpClientParams();
        httpParameters.setConnectionManagerTimeout(requestTimeout);
        httpParameters.setSoTimeout(readTimeout);
        httpParameters.setContentCharset(ShortMessageApiService.getEncode());
        MultiThreadedHttpConnectionManager hm =  new MultiThreadedHttpConnectionManager();
        client = new HttpClient(httpParameters, hm);
    }
    
    public static boolean sendCaptcha(ShortMessage sm) {
        logger.info(sm.getContent());
        PostMethod method = new PostMethod(ShortMessageApiService.getUrl());
        method.setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=" + ShortMessageApiService.getEncode());
        NameValuePair[] data = {
                new NameValuePair("account", ShortMessageApiService.getAccount()), 
                new NameValuePair("password", ShortMessageApiService.getPassword()), //密码可以使用明文密码或使用32位MD5加密
                new NameValuePair("mobile", sm.getMobileNo()), 
                new NameValuePair("content", sm.getContent()),
        };
        String submitResult, code = null, message;
        try {
            method.setRequestBody(data);
            int httpCode = client.executeMethod(method);
            switch (httpCode) {
            case HttpStatus.SC_INTERNAL_SERVER_ERROR:
            case HttpStatus.SC_NOT_FOUND:
            case HttpStatus.SC_UNAUTHORIZED:
            case HttpStatus.SC_PRECONDITION_FAILED:
            default:
                logger.error("短信请求失败,httpCode:{}。手机号:{},用户名:{},短信内容:{}", 
                        httpCode, sm.getMobileNo(), ShortMessageApiService.getAccount(), sm.getContent());
                break;
            case HttpStatus.SC_OK:
                submitResult = method.getResponseBodyAsString();
                
                Document doc = DocumentHelper.parseText(submitResult); 
                Element root = doc.getRootElement();
                code = root.elementText("code");
                message = root.elementText("msg");   
                String smsid = root.elementText("smsid"); 
                if ("2".equals(code)) 
                    logger.info("短信发送成功,手机号:{},smsid:{}", sm.getMobileNo(), smsid);
                else
                    logger.warn("短信发送失败,手机号:{},code:{},msg:{},用户名:{},短信内容:{}", 
                            sm.getMobileNo(), code, message, ShortMessageApiService.getAccount(), sm.getContent());
                break;
            }
        } catch (IOException | DocumentException e) {
            logger.error("短信发送失败,代码出现异常:{}", e);
        } finally {
            if(method != null)
                try {
                    method.getResponseBodyAsStream().close();
                } catch (IOException e) {
                    logger.error("PostMethod关闭出现异常:{}", e);
                }
        }
        return "2".equals(code);
    }
}


2.使用连接池,并且每次重新创建PostMethod对象,使用完PostMethod位关闭(10个线程测试没啥问题,性能也和上一种差不多)

package com.handmessage.ups.shortmessageapi.send;


import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


import com.handmessage.ups.shortmessageapi.ShortMessageApiService;
import com.handmessage.ups.shortmessageapi.bean.ShortMessage;

public class SendCaptchaQueen {
    private static Logger logger = LogManager.getLogger(SendCaptchaQueen.class);
    
  


    static HttpClient client;
    static {
        client = new HttpClient(); 
        client.getParams().setContentCharset(ShortMessageApiService.getEncode());
        client.getParams().setConnectionManagerTimeout(10000);
        client.getParams().setSoTimeout(15000);
    }
    
    public static boolean sendCaptcha(ShortMessage sm) {
        logger.info(sm.getContent());
        NameValuePair[] data = {
                new NameValuePair("account", ShortMessageApiService.getAccount()), 
                new NameValuePair("password", ShortMessageApiService.getPassword()), //密码可以使用明文密码或使用32位MD5加密
                new NameValuePair("mobile", sm.getMobileNo()), 
                new NameValuePair("content", sm.getContent()),
        };
        String submitResult, code = null, message;
        try {
            PostMethod method = new PostMethod(ShortMessageApiService.getUrl());
            method.setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=" + ShortMessageApiService.getEncode());
            method.setRequestBody(data);
            synchronized (SendCaptchaQueen.class) {
                client.executeMethod(method);
                submitResult = method.getResponseBodyAsString();
            }
            
            Document doc = DocumentHelper.parseText(submitResult); 
            Element root = doc.getRootElement();
            code = root.elementText("code");
            message = root.elementText("msg");   
            String smsid = root.elementText("smsid"); 
            if ("2".equals(code)) 
                logger.info("短信发送成功,手机号:{},smsid:{}", sm.getMobileNo(), smsid);
            else
                logger.warn("短信发送失败,手机号:{},code:{},msg:{},短信内容:{}", sm.getMobileNo(), code, message,sm.getContent());
        } catch (IOException | DocumentException e) {
            logger.error("电话:{},内容:{},异常:{}", sm.getMobileNo(), sm.getContent(), e);
        }
        return "2".equals(code);
    }
}


3.未使用连接池,并且每次重新创建PostMethod对象,使用完PostMethod未关闭(10个线程测试没啥问题,性能也和上一种差不多):

package com.handmessage.ups.shortmessageapi.send;


import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


import com.handmessage.ups.shortmessageapi.ShortMessageApiService;
import com.handmessage.ups.shortmessageapi.bean.ShortMessage;

public class SendCaptchaQueen {
    private static Logger logger = LogManager.getLogger(SendCaptchaQueen.class);
    
  


    static HttpClient client;
    static {
        client = new HttpClient(); 
        client.getParams().setContentCharset(ShortMessageApiService.getEncode());
        client.getParams().setConnectionManagerTimeout(10000);
        client.getParams().setSoTimeout(15000);
    }
    
    public static boolean sendCaptcha(ShortMessage sm) {
        logger.info(sm.getContent());
        NameValuePair[] data = {
                new NameValuePair("account", ShortMessageApiService.getAccount()), 
                new NameValuePair("password", ShortMessageApiService.getPassword()), //密码可以使用明文密码或使用32位MD5加密
                new NameValuePair("mobile", sm.getMobileNo()), 
                new NameValuePair("content", sm.getContent()),
        };
        String submitResult, code = null, message;
        try {
            PostMethod method = new PostMethod(ShortMessageApiService.getUrl());
            method.setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=" + ShortMessageApiService.getEncode());
            method.setRequestBody(data);
            synchronized (SendCaptchaQueen.class) {
                client.executeMethod(method);
                submitResult = method.getResponseBodyAsString();
            }
            
            Document doc = DocumentHelper.parseText(submitResult); 
            Element root = doc.getRootElement();
            code = root.elementText("code");
            message = root.elementText("msg");   
            String smsid = root.elementText("smsid"); 
            if ("2".equals(code)) 
                logger.info("短信发送成功,手机号:{},smsid:{}", sm.getMobileNo(), smsid);
            else
                logger.warn("短信发送失败,手机号:{},code:{},msg:{},短信内容:{}", sm.getMobileNo(), code, message,sm.getContent());
        } catch (IOException | DocumentException e) {
            logger.error("电话:{},内容:{},异常:{}", sm.getMobileNo(), sm.getContent(), e);
        }
        return "2".equals(code);
    }
}


4.使用了连接池,并且公用了PostMethod对象。(测试10个线程并发,除了第一个执行成功,其他均报read timeout错误):

package com.handmessage.ups.shortmessageapi.send;


import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


import com.handmessage.ups.shortmessageapi.ShortMessageApiService;
import com.handmessage.ups.shortmessageapi.bean.ShortMessage;

public class SendCaptchaQueen {
    private static Logger logger = LogManager.getLogger(SendCaptchaQueen.class);
    
  


    static HttpClient client;
    static PostMethod method;
    static {
        HttpClientParams httpParameters = new HttpClientParams();
        httpParameters.setConnectionManagerTimeout(10000);
        httpParameters.setSoTimeout(15000);
        httpParameters.setContentCharset(ShortMessageApiService.getEncode());
        MultiThreadedHttpConnectionManager hm =  new MultiThreadedHttpConnectionManager();
        client = new HttpClient(httpParameters, hm);
        method = new PostMethod(ShortMessageApiService.getUrl());
        method.setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=" + ShortMessageApiService.getEncode());
    }
    
    public static boolean sendCaptcha(ShortMessage sm) {
        logger.info(sm.getContent());
        NameValuePair[] data = {
                new NameValuePair("account", ShortMessageApiService.getAccount()), 
                new NameValuePair("password", ShortMessageApiService.getPassword()), //密码可以使用明文密码或使用32位MD5加密
                new NameValuePair("mobile", sm.getMobileNo()), 
                new NameValuePair("content", sm.getContent()),
        };
        String submitResult, code = null, message;
        try {
            synchronized (SendCaptchaQueen.class) {
                method.setRequestBody(data);
                client.executeMethod(method);
                submitResult = method.getResponseBodyAsString();
            }
            
            Document doc = DocumentHelper.parseText(submitResult); 
            Element root = doc.getRootElement();
            code = root.elementText("code");
            message = root.elementText("msg");   
            String smsid = root.elementText("smsid"); 
            if ("2".equals(code)) 
                logger.info("短信发送成功,手机号:{},smsid:{}", sm.getMobileNo(), smsid);
            else
                logger.warn("短信发送失败,手机号:{},code:{},msg:{},短信内容:{}", sm.getMobileNo(), code, message,sm.getContent());
        } catch (IOException | DocumentException e) {
            logger.error("电话:{},内容:{},异常:{}", sm.getMobileNo(), sm.getContent(), e);
        }
        return "2".equals(code);
    }
}


5.未使用连接池并公用PostMethod对象(现象和上一种差不多):

package com.handmessage.ups.shortmessageapi.send;


import java.io.IOException;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;


import com.handmessage.ups.shortmessageapi.ShortMessageApiService;
import com.handmessage.ups.shortmessageapi.bean.ShortMessage;

public class SendCaptchaQueen {
    private static Logger logger = LogManager.getLogger(SendCaptchaQueen.class);
    
  


static HttpClient client;
    static PostMethod method;
    static {
        client = new HttpClient(); 
        client.getParams().setContentCharset(ShortMessageApiService.getEncode());
        client.getParams().setConnectionManagerTimeout(10000);
        client.getParams().setSoTimeout(15000);
        method = new PostMethod(ShortMessageApiService.getUrl());
        method.setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=" + ShortMessageApiService.getEncode());
    }
    
    public static boolean sendCaptcha(ShortMessage sm) {
        logger.info(sm.getContent());
        NameValuePair[] data = {
                new NameValuePair("account", ShortMessageApiService.getAccount()), 
                new NameValuePair("password", ShortMessageApiService.getPassword()), //密码可以使用明文密码或使用32位MD5加密
                new NameValuePair("mobile", sm.getMobileNo()), 
                new NameValuePair("content", sm.getContent()),
        };
        String submitResult, code = null, message;
        try {
            synchronized (SendCaptchaQueen.class) {
                method.setRequestBody(data);
                client.executeMethod(method);
                submitResult = method.getResponseBodyAsString();
            }
            
            Document doc = DocumentHelper.parseText(submitResult); 
            Element root = doc.getRootElement();
            code = root.elementText("code");
            message = root.elementText("msg");   
            String smsid = root.elementText("smsid"); 
            if ("2".equals(code)) 
                logger.info("短信发送成功,手机号:{},smsid:{}", sm.getMobileNo(), smsid);
            else
                logger.warn("短信发送失败,手机号:{},code:{},msg:{}", sm.getMobileNo(), code, message);
        } catch (IOException | DocumentException e) {
            logger.error(e);
        }
        return "2".equals(code);
    }
}


Junit测试代码如下:

package com.handmessage.ups.shortmessageapi.client;


import java.util.Random;
import java.util.concurrent.CountDownLatch;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.handmessage.jeelib.apisocket.client.ApiClient;
import com.handmessage.ups.shortmessageapi.client.SendCaptchaClient.RegisterSendRequest;
import com.handmessage.ups.shortmessageapi.client.SendCaptchaClient.SendResponse;
import com.handmessage.ups.shortmessageapi.client.SendSmsClient.SendSmsRequest;
import com.handmessage.ups.shortmessageapi.client.SendSmsClient.SendSmsResponse;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-test-config.xml"})
public class SendMessageConcurrentTest {
    private static ObjectMapper mapper = new ObjectMapper();
    
    @Autowired
    private ApiClient shortMessageApi;
    
    Random random = new Random();
    CountDownLatch begin = new CountDownLatch(1);
    CountDownLatch end  = new CountDownLatch(10);


    @Test
    public void test() {
        for (int i = 0; i < 10; i++) {
            new Thread(new MyThread("thread" + (i + 1))).start();
        }
        begin.countDown();
        try {
            end.await();
            System.out.println("完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    class MyThread implements Runnable {


        public MyThread() {}
        public MyThread(String name) {
            this.name = name;
        }
        private String name;
        public String getName() {
            return name;
        }


        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public void run() {
            try {
                String phone = getPhone();
                boolean go = random.nextBoolean();
                begin.await();
                try {
                    go(go, phone);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                end.countDown();
            }
        }
        
        public void go(boolean go, String phone) throws JsonProcessingException {
            if (go) {
                postReg(phone);
                System.out.println("postReg" + phone);
            } else { 
                postQuik();
                System.out.println("postQuik" + phone);
            }
        }
        
        public void postReg(String phone) throws JsonProcessingException {
            RegisterSendRequest request = new RegisterSendRequest(phone, null, 3, "127.0.0.1");
            SendResponse response = (SendResponse) shortMessageApi.getResponse(request);
            System.out.println(this.getName() + ":" + mapper.writeValueAsString(response));
        }
        
        public void postQuik() throws JsonProcessingException {
            SendSmsRequest request = new SendSmsRequest();
            request.setMobilePhone(getPhone());
            request.setName("test" + this.getName());
            request.setPw("pass" + this.getName());
            SendSmsResponse response = (SendSmsResponse) shortMessageApi.getResponse(request);
            System.out.println(this.getName() + ":" + mapper.writeValueAsString(response));
        }
        
        public String getPhone() {
            String[] phones = {"测试电话号码1", "测试电话号码2", "测试电话号码3"};
            return phones[random.nextInt(3)];
        }
        
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值