基于httpclient的http以及soap请求工具类

引入maven依赖:

<dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpclient</artifactId>
     <version>4.5.13</version>
</dependency>

HttpUtils.java

import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
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.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import java.nio.charset.Charset;

/**
 * @author linxz
 * @version 1.0
 * @date 2021/1/25 17:04
 */
@Slf4j
public class HttpUtils {

    // 池化管理
    private static PoolingHttpClientConnectionManager poolConnManager = null;

    /**
     * 连接目标超时时间
     */
    private static final int defaultcCnnectionTimeOut =3000;

    /**
     * 从连接池中获取可用连接超时
     */
    private static final int defaultRequestTimeOut =1000;

    /**
     * 等待响应超时
     */
    private static final int defaultSocketTimeOut =30000;

    /**
     * 重试次数
     */
    private static final int defaultRequestRetryCount =3;

    /**
     * 最多连接数
     */
    private static final int defaultMaxTotal =800;

    /**
     * 最大路由
     */
    private static final int defaultMaxPerRoute =200;

    static {
        try {
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, TrustAllStrategy.INSTANCE);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
            // 配置同时支持 HTTP 和 HTPPS
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();
            // 初始化连接管理器
            poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            // 同时最多连接数
            poolConnManager.setMaxTotal(defaultMaxTotal);
            // 设置最大路由
            poolConnManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
            // 此处解释下MaxtTotal和DefaultMaxPerRoute的区别:
            // 1、MaxtTotal是整个池子的大小;
            // 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如:
            // MaxtTotal=400 DefaultMaxPerRoute=200
            // 而我只连接到http://www.abc.com时,到这个主机的并发最多只有200;而不是400;
            // 而我连接到http://www.bac.com 和
            // http://www.ccd.com时,到每个主机的并发最多只有200;即加起来是400(但不能超过400);所以起作用的设置是DefaultMaxPerRoute
        } catch (Exception e){
            log.error("HttpClient连接池初始化失败",e);
        }
    }

    public static CloseableHttpClient getConnection() {
        return getConnection(defaultcCnnectionTimeOut, defaultRequestTimeOut, defaultSocketTimeOut, defaultRequestRetryCount);
    }

    public static CloseableHttpClient getConnection(int connTimeOut,int requestTimeOut,int socketTimeOut,int retryCount) {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(connTimeOut)
                                                     .setConnectionRequestTimeout(requestTimeOut)
                                                     .setSocketTimeout(socketTimeOut)
                                                     .build();
        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(poolConnManager)
                .setDefaultRequestConfig(config)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false)).build();
        return httpClient;
    }

    /**
     * 发送post请求,使用默认设置
     * @param httpPost
     * @return
     */
    public static String post(HttpPost httpPost){
        return executeHttpReq(httpPost);
    }

    /**
     * 发送get请求,使用默认设置
     * @param httpGet
     * @return
     */
    public static String get(HttpGet httpGet){
        return executeHttpReq(httpGet);
    }

    /**
     * 发送post请求,自定义超时时间与重试次数
     * @param httpPost
     * @param connTimeOut
     * @param requestTimeOut
     * @param socketTimeOut
     * @param retryCount
     * @return
     */
    public static String post(HttpPost httpPost,int connTimeOut,int requestTimeOut,int socketTimeOut,int retryCount, Charset charset){
        return executeHttpReq(httpPost,connTimeOut,requestTimeOut,socketTimeOut,retryCount,charset);
    }

    /**
     * 发送get请求,自定义超时时间与重试次数
     * @param httpGet
     * @param connTimeOut
     * @param requestTimeOut
     * @param socketTimeOut
     * @param retryCount
     * @return
     */
    public static String get(HttpGet httpGet,int connTimeOut,int requestTimeOut,int socketTimeOut,int retryCount, Charset charset){
        return executeHttpReq(httpGet,connTimeOut,requestTimeOut,socketTimeOut,retryCount,charset);
    }

    /**
     * 发送http请求,使用默认设置
     * @param httpRequest
     * @return
     */
    public static String executeHttpReq(HttpUriRequest httpRequest){
        return executeHttpReq(httpRequest, defaultcCnnectionTimeOut, defaultRequestTimeOut, defaultSocketTimeOut, defaultRequestRetryCount,CommonConstant.DEFAULT_CHARSET);
    }

    /**
     * 发送http请求,自定义超时时间与重试次数
     * @param httpRequest
     * @param connTimeOut
     * @param requestTimeOut
     * @param socketTimeOut
     * @param retryCount
     * @return
     */
    public static String executeHttpReq(HttpUriRequest httpRequest, int connTimeOut, int requestTimeOut, int socketTimeOut, int retryCount, Charset charset){
        CloseableHttpClient httpClient=getConnection(connTimeOut,requestTimeOut,socketTimeOut,retryCount);
        try(CloseableHttpResponse httpResponse=httpClient.execute(httpRequest)){
            return EntityUtils.toString(httpResponse.getEntity(), charset);
        }catch (Exception e){
            log.error("http请求失败",e);
        }
        return null;
    }

    public static void main(String[] args) throws JsonProcessingException {
        //测试get接口
        HttpGet getRequest=new HttpGet("https://www.baidu.com");
        System.out.println(get(getRequest));
        //测试post接口
        HttpPost postRequest = new HttpPost("http://localhost:8888/api/user/getUserInfo");
        postRequest.addHeader("authToken","JhgziUt2Q/k8NbYzns8OlQ==");
        StringEntity params = new StringEntity("", "UTF-8");
        postRequest.addHeader("content-type", "application/json");
        postRequest.setEntity(params);
        System.out.println(post(postRequest));
        //测试webservice接口
        HttpPost soapRequest=new HttpPost("http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx");
        soapRequest.addHeader("Content-Type","text/xml;charset=UTF-8");
        soapRequest.setEntity(new StringEntity("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://WebXml.com.cn/\">\n" +
                "   <soapenv:Header/>\n" +
                "   <soapenv:Body>\n" +
                "      <web:getCountryCityByIp>\n" +
                "         <!--Optional:-->\n" +
                "         <web:theIpAddress>144.144.144.1</web:theIpAddress>\n" +
                "      </web:getCountryCityByIp>\n" +
                "   </soapenv:Body>\n" +
                "</soapenv:Envelope>",CommonConstant.DEFAULT_CHARSET));
        System.out.println(post(soapRequest));
    }
}

SoapUtils.java

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;

import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * @author linxz
 * @version 1.0
 * @date 2021/1/25 17:04
 */
@Slf4j
public class SoapUtils {

    /**
     * 使用SOAP1.1发送消息
     *
     * @param url 为访问的wsdl地址(登陆后wsdl文件中的soap:address)
     * @param soapXml
     * @param soapAction
     * @param userpass 认证用户密码格式:username:password(如:admin:123456)
     * @return
     */
    public static String doPostSoap1_1(String url, String soapXml, String soapAction, String userpass) {
        return doPostSoapByDefaultHttpSetting(url,soapXml,soapAction,userpass,"text/xml;charset=UTF-8");
    }

    /**
     * 使用SOAP1.2发送消息
     *
     * @param url 为访问的wsdl地址(登陆后wsdl文件中的soap:address)
     * @param soapXml
     * @param soapAction
     * @param userpass 认证用户密码格式:username:password(如:admin:123456)
     * @return
     */
    public static String doPostSoap1_2(String url, String soapXml, String soapAction, String userpass) {
        return doPostSoapByDefaultHttpSetting(url,soapXml,soapAction,userpass,"application/soap+xml;charset=UTF-8");
    }

    /**
     * 发送SOAP消息,使用默认的http请求设置
     * @param url
     * @param soapXml
     * @param soapAction
     * @param userpass
     * @param contentType
     * @return
     */
    public static String doPostSoapByDefaultHttpSetting(String url, String soapXml, String soapAction, String userpass, String contentType){
        String result = null;
        result=HttpUtils.post(createPostRequest(url, soapXml, soapAction, userpass, contentType));
        // 打印响应内容
        log.debug("soap响应:{}", result);
        return result;
    }

    /**
     * 使用SOAP1.1发送消息
     *
     * @param url 为访问的wsdl地址(登陆后wsdl文件中的soap:address)
     * @param soapXml
     * @param soapAction
     * @param userpass 认证用户密码格式:username:password(如:admin:123456)
     * @return
     */
    public static String doPostSoap1_1(String url, String soapXml, String soapAction, String userpass
            , int connTimeOut, int requestTimeOut, int socketTimeOut, int retryCount, Charset charset) {
        return doPostSoapByCustomerHttpSetting(url,soapXml,soapAction,userpass,"text/xml;charset=UTF-8",
                connTimeOut,requestTimeOut,socketTimeOut,retryCount,charset);
    }

    /**
     * 使用SOAP1.2发送消息
     *
     * @param url 为访问的wsdl地址(登陆后wsdl文件中的soap:address)
     * @param soapXml
     * @param soapAction
     * @param userpass 认证用户密码格式:username:password(如:admin:123456)
     * @return
     */
    public static String doPostSoap1_2(String url, String soapXml, String soapAction, String userpass
            , int connTimeOut, int requestTimeOut, int socketTimeOut, int retryCount, Charset charset) {
        return doPostSoapByCustomerHttpSetting(url,soapXml,soapAction,userpass,"application/soap+xml;charset=UTF-8",
                connTimeOut,requestTimeOut,socketTimeOut,retryCount,charset);
    }

    /**
     * 发送SOAP消息,使用自定义的http请求设置
     * @param url
     * @param soapXml
     * @param soapAction
     * @param userpass
     * @param contentType
     * @param connTimeOut
     * @param requestTimeOut
     * @param socketTimeOut
     * @param retryCount
     * @param charset
     * @return
     */
    public static String doPostSoapByCustomerHttpSetting(String url, String soapXml, String soapAction, String userpass, String contentType
            , int connTimeOut, int requestTimeOut, int socketTimeOut, int retryCount, Charset charset){
        String result = null;
        result=HttpUtils.post(createPostRequest(url, soapXml, soapAction, userpass, contentType),connTimeOut,requestTimeOut,socketTimeOut,retryCount,charset);
        // 打印响应内容
        log.debug("soap响应:{}", result);
        return result;
    }

    /**
     * 构建post请求体
     * @param url
     * @param soapXml
     * @param soapAction
     * @param userpass
     * @param contentType
     * @return
     */
    private static HttpPost createPostRequest(String url, String soapXml, String soapAction, String userpass,String contentType){
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", contentType);
        if(StringUtils.isNotBlank(soapAction)){
            httpPost.setHeader("SOAPAction", soapAction);
        }
        if (CommonUtils.isNotBlank(userpass)) {
            String base64Auth=Base64Utils.encryptForBase64(userpass.getBytes(CommonConstant.DEFAULT_CHARSET));
            BasicHeader basicHeader=new BasicHeader("Authorization", "Basic " +(base64Auth));
            httpPost.addHeader(basicHeader);
            log.debug("加密后内容:{}", new BasicHeader("Authorization", "Basic " + base64Auth));
        }
        StringEntity data = new StringEntity(soapXml, CommonConstant.DEFAULT_CHARSET);
        httpPost.setEntity(data);
        return httpPost;
    }

    /**
     * 创建SoapMessage对象,通过传入的参数自动填充
     * @param nameSpaceMap
     * @param methodInfo
     * @return
     * @throws Exception
     */
    public static SOAPMessage buildSOAPMessage(Map<String, String> nameSpaceMap, SoapMethodInfo methodInfo) throws Exception{
        SOAPMessage soapMessage=buildSOAPMessage(nameSpaceMap);
        String prefix=methodInfo.getUseNameSpaceName();
        String methodName=methodInfo.getMethodName();
        if(nameSpaceMap.containsKey(prefix)==false){
            throw ExceptionUtils.exception("不存在的命名空间名称:"+prefix);
        }
        SOAPBody soapBody=soapMessage.getSOAPBody();
        SOAPElement methodElement=soapBody.addChildElement(methodName,prefix,nameSpaceMap.get(prefix));
        for(SoapMethodParam methodParam:methodInfo.getParams()){
            buildParams(methodParam,methodElement,prefix);
        }
        return soapMessage;
    }

    /**
     * 创建SoapMessage对象,通过传入的Consumer填充调用函数以及参数信息(自定义程度高)
     * @param nameSpaceMap
     * @param methodBuilder
     * @return
     * @throws Exception
     */
    public static SOAPMessage buildSOAPMessage(Map<String, String> nameSpaceMap, Consumer<SOAPBody> methodBuilder) throws Exception{
        SOAPMessage soapMessage=buildSOAPMessage(nameSpaceMap);
        SOAPBody soapBody=soapMessage.getSOAPBody();
        methodBuilder.accept(soapBody);
        return soapMessage;
    }

    private static SOAPMessage buildSOAPMessage(Map<String, String> nameSpaceMap) throws Exception{
        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart=soapMessage.getSOAPPart();
        SOAPEnvelope envelope=soapPart.getEnvelope();
        for (Map.Entry<String,String> entry:nameSpaceMap.entrySet()){
            envelope.addNamespaceDeclaration(entry.getKey(),entry.getValue());
        }
        return soapMessage;
    }

    /**
     * 填充参数
     * @param methodParam 参数信息
     * @param rootElement body结点
     */
    private static void buildParams(SoapMethodParam methodParam, SOAPElement rootElement, String nameSpace) throws Exception {
        SOAPElement valueElement=rootElement.addChildElement(methodParam.getName(),nameSpace);
        if(methodParam.getSimpleValue()!=null){
            //简单值模式
            valueElement.setValue(methodParam.getSimpleValue());
        }else {
            //对象模式
            buildParams(methodParam.getObjectValue(),valueElement,nameSpace);
        }
    }

    /**
     * 将SOAPMessage转换成string
     * @param soapMessage
     * @return
     * @throws Exception
     */
    public static String convertSOAPMessageToString(SOAPMessage soapMessage)throws Exception{
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source source = soapMessage.getSOAPPart().getContent();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1000);
        StreamResult result = new StreamResult(byteArrayOutputStream);
        transformer.transform(source, result);
        String xml = new String(byteArrayOutputStream.toByteArray());
        return xml;
    }

    /**
     * 把soap字符串格式化为SOAPMessage
     *
     * @param soapString
     * @return
     */
    public static SOAPMessage convertStringToSOAPMessage(String soapString) {
        MessageFactory msgFactory;
        try {
            msgFactory = MessageFactory.newInstance();
            SOAPMessage reqMsg = msgFactory.createMessage(new MimeHeaders(),
                    new ByteArrayInputStream(soapString.getBytes(CommonConstant.DEFAULT_CHARSET)));
            reqMsg.saveChanges();
            return reqMsg;
        } catch (Exception e) {
            throw ExceptionUtils.exception("soap字符串转换为SOAPMessage失败",e);
        }
    }

    public static void main(String[] args) throws Exception {
        /**
         * 命名空间,查看wsdl:types结点中的s:schema的targetNamespace
         * 键以xmlns:开头,后面带上自定义的名称 eg: xmlns:web="http://WebXml.com.cn/"表示把这个命名空间用定义名字叫web,后续使用的时候,用web:表示引用"http://WebXml.com.cn/"这个命名空间
         */
        Map<String,String> nameSpace=new HashMap<>();

        /**
         * 对应格式:
         * <?xml version="1.0" encoding="UTF-8" standalone="no"?>
         * <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://WebXml.com.cn/">
         *    <soapenv:Header/>
         *    <soapenv:Body>
         *       <web:getCountryCityByIp>
         *          <!--Optional:-->
         *          <web:theIpAddress>144.144.144.1</web:theIpAddress>
         *       </web:getCountryCityByIp>
         *    </soapenv:Body>
         * </soapenv:Envelope>
         */
//        nameSpace.put("a","http://WebXml.com.cn/");
//        MethodInfo methodInfo=new MethodInfo();
//        methodInfo.setMethodName("getCountryCityByIp");
//        methodInfo.setUseNameSpaceName("a");
//        MethodParam methodParam=new MethodParam();
//        methodParam.setName("theIpAddress");
//        methodParam.setSimpleValue("144.144.144.1");
//        methodInfo.setParams(Collections.singletonList(methodParam));
//        String xml=convertSOAPMessageToString(buildSOAPMessage(nameSpace,methodInfo));
//        System.out.println(xml);
//        String result=doPostSoap1_1("http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx",xml,"","");
//        System.out.println(result);
        /**
         * 对应格式:
         * <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://WebXml.com.cn/">
         *    <soapenv:Header/>
         *    <soapenv:Body>
         *       <web:getDomesticAirlinesTime>
         *          <!--Optional:-->
         *          <web:startCity>深圳</web:startCity>
         *          <!--Optional:-->
         *          <web:lastCity>上海</web:lastCity>
         *          <!--Optional:-->
         *          <web:theDate>2021-01-26</web:theDate>
         *          <!--Optional:-->
         *          <web:userID></web:userID>
         *       </web:getDomesticAirlinesTime>
         *    </soapenv:Body>
         * </soapenv:Envelope>
         */
//        nameSpace.put("web","http://WebXml.com.cn/");
//        MethodInfo methodInfo=new MethodInfo();
//        methodInfo.setMethodName("getDomesticAirlinesTime");
//        methodInfo.setUseNameSpaceName("web");
//        List<MethodParam> methodParams=new ArrayList<>();
//        MethodParam startCity=new MethodParam();
//        startCity.setName("startCity");
//        startCity.setSimpleValue("深圳");
//        MethodParam lastCity=new MethodParam();
//        lastCity.setName("lastCity");
//        lastCity.setSimpleValue("上海");
//        MethodParam theDate=new MethodParam();
//        theDate.setName("theDate");
//        theDate.setSimpleValue("2021-01-26");
//        methodParams.add(startCity);
//        methodParams.add(lastCity);
//        methodParams.add(theDate);
//        methodInfo.setParams(methodParams);
//        String xml=convertSOAPMessageToString(buildSOAPMessage(nameSpace,methodInfo));
//        System.out.println(xml);
//        String result=doPostSoap1_1("http://www.webxml.com.cn/webservices/DomesticAirline.asmx?wsdl",xml,"","");
//        System.out.println(result);


        //测试自定义控制参数设置
//        nameSpace.put("web","http://WebXml.com.cn/");
//        MethodInfo methodInfo=new MethodInfo();
//        String xml=convertSOAPMessageToString(buildSOAPMessage(nameSpace, new Consumer<SOAPBody>() {
//            @Override
//            public void accept(SOAPBody soapBody) {
//                try {
//                    SOAPElement methodElement=soapBody.addChildElement("getDomesticAirlinesTime","web","http://WebXml.com.cn/");
//                    SOAPElement startCity=methodElement.addChildElement("startCity","web");
//                    startCity.setValue("深圳");
//                    SOAPElement lastCity=methodElement.addChildElement("lastCity","web");
//                    lastCity.setValue("上海");
//                    SOAPElement theDate=methodElement.addChildElement("theDate","web");
//                    theDate.setValue("2021-01-26");
//                } catch (SOAPException e) {
//                    e.printStackTrace();
//                }
//            }
//        }));
//        System.out.println(xml);
//        String result=doPostSoap1_1("http://www.webxml.com.cn/webservices/DomesticAirline.asmx?wsdl",xml,"","");
//        System.out.println(result);
    }
}
SoapMethodInfo.java
/**
 * @author linxz
 * @version 1.0
 * @date 2021/1/26 17:11
 */
@Getter
@Setter
public class SoapMethodInfo {
    //调用的方法名
    private String methodName;

    //调用方法所引用的命名空间,为nameSpace中的key
    private String useNameSpaceName;

    //调用方法所使用的参数,可以有层级嵌套
    private List<SoapMethodParam> params;
}
SoapMethodParam.java
import lombok.Getter;
import lombok.Setter;

/**
 * @author linxz
 * @version 1.0
 * @date 2021/1/26 17:11
 */
@Getter
@Setter
public class SoapMethodParam {
    //参数名称
    private String name;
    //参数值,对象类型,与simpleValue仅需设置一个,优先使用simpleValue
    private SoapMethodParam objectValue;
    //参数值,简单类型,与objectValue仅需设置一个,优先使用simpleValue
    private String simpleValue;
}

文中的

CommonUtils.isNotBlank()方法是判断字符串是否为空
CommonConstant.DEFAULT_CHARSET等价于Charset.forName(DEFAULT_CHARSET_VALUE);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值