httpClient工具类

1.httpClient工具类(http/https、重发、超时、连接数的设置)

package com.xxxxxxx.xxxx.xxxx.payutil;import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
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.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;/*** {@code HttpClient}为HTTP请求客户端,负责将报文发送至指定URL。** <p>{@code HttpClient}提供了丰富的http/https请求功能,根据实际应用场景可以向服务器发送多种请求实体。</p>** <p>通过注解@Autowired可以注入实例对象。</p>** <p>使用时根据实际情况在配置文件配置:*    <dl>*         <dd>连接池最大连接数:httpClient.maxConnTotal,未配置默认50</dd>*        <dd>每个路由最大连接数:httpClient.maxConnPerRoute,未配置默认为最大连接数的一半</dd>*         <dd>超时时间(单位秒):httpClient.timeout,未配置默认30秒</dd>*       <dd>重发次数:httpClient.retryCount,未配置默认3次</dd>*  </dl>* </p>** <blockquote>参数说明如下:每个路由最大连接数:httpClient.maxConnPerRoute* 如配置为2时,意味着请求到http://www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!* </blockquote>** <p><strong>设计思路:</strong>* HTTP请求客户端组件主要封装{@code Apache HttpClient},为接入着提供定制化的{@code HttpClient}实例并提供向服务器发送各种格式请求的方法。* ?HTTP客户端组件需要满足发送{@code http}和{@code https}请求的能力,在实现过程中需要向注册器注册{@code http}工厂和{@code https}工厂。* ?鉴于不同服务器对请求参数编码不同,每个方法需要提供接收编码格式的参数,如果未要求编码格式,默认采用{@code UTF-8}。*/
public class HttpClient {private static final String CHARSET_UTF_8 = "UTF-8";/** 连接池最大连接数 **/private int maxConnTotal = 50;/** 每个路由最大连接数 **/private int maxConnPerRoute = 0;/** 超时时间,秒 **/private int timeout= 50;/** 重发次数 **/private int retryCount = 5;/** 连接客户端 **/private CloseableHttpClient closeableHttpClient;/*** 构造方法* @throws KeyManagementException* @throws NoSuchAlgorithmException*/public HttpClient() throws KeyManagementException, NoSuchAlgorithmException{//超时时间,单位秒int httpReqTimeOut = timeout * 1000;/*** maxConnPerRoute为每个路由的最大连接数,如:maxConnPerRoute=2时,* 请求到www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!*/if (maxConnPerRoute == 0)maxConnPerRoute = maxConnTotal / 2;SSLContext sslContext = SSLContext.getInstance("TLS");// 初始化SSL上下文sslContext.init(null, new TrustManager[] { tm }, null);// SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);// 注册http套接字工厂和https套接字工厂Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", sslsf).build();// 连接池管理器PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);pcm.setMaxTotal(maxConnTotal);//连接池最大连接数pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数/***  请求参数配置*  connectionRequestTimeout:*                       从连接池中获取连接的超时时间,超过该时间未拿到可用连接,*                         会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool*  connectTimeout:*                 连接上服务器(握手成功)的时间,超出该时间抛出connect timeout*  socketTimeout:*                 服务器返回数据(response)的时间,超过该时间抛出read timeout*/RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(httpReqTimeOut).setConnectTimeout(httpReqTimeOut).setSocketTimeout(httpReqTimeOut).build();/*** 构造closeableHttpClient对象*/closeableHttpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(pcm).setRetryHandler(retryHandler).build();}@PostConstructpublic void init() throws Exception {//超时时间,单位秒int httpReqTimeOut = timeout * 1000;/*** maxConnPerRoute为每个路由的最大连接数,如:maxConnPerRoute=2时,* 请求到www.baidu.com的最大连接数只能为2,即使连接池还有1000个可用连接!*/if (maxConnPerRoute == 0)maxConnPerRoute = maxConnTotal / 2;SSLContext sslContext = SSLContext.getInstance("TLS");// 初始化SSL上下文sslContext.init(null, new TrustManager[] { tm }, null);// SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);// 注册http套接字工厂和https套接字工厂Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", sslsf).build();// 连接池管理器PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);pcm.setMaxTotal(maxConnTotal);//连接池最大连接数pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每个路由最大连接数/***  请求参数配置*  connectionRequestTimeout:*                          从连接池中获取连接的超时时间,超过该时间未拿到可用连接,*                         会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool*  connectTimeout:*                 连接上服务器(握手成功)的时间,超出该时间抛出connect timeout*  socketTimeout:*                 服务器返回数据(response)的时间,超过该时间抛出read timeout*/RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(httpReqTimeOut).setConnectTimeout(httpReqTimeOut).setSocketTimeout(httpReqTimeOut).build();/*** 构造closeableHttpClient对象*/closeableHttpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(pcm).setRetryHandler(retryHandler).build();}/*** post 数据,数据以key、value存放在Map中* @param url http请求地址* @param paramMap 请求参数* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException* @throws Exception*/public String postMap(String url, Map<String, String> paramMap) throws ClientProtocolException, ParseException, IOException {return postMap(url, paramMap, CHARSET_UTF_8);}/*** post 数据,数据以key、value存放在Map中* @param url http请求地址* @param paramMap 请求参数* @param charsetName 编码格式* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException* @throws Exception*/public String postMap(String url, Map<String, String> paramMap, String charsetName) throws ClientProtocolException, ParseException, IOException {// post请求HttpPost post = new HttpPost(url);// 设置参数List<NameValuePair> formParams = new ArrayList<NameValuePair>();for (Map.Entry<String, String> entry : paramMap.entrySet()) {formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));}// 对参数进行编码post.setEntity(new UrlEncodedFormEntity(formParams, Charset.forName(charsetName)));return httpRequest(post, charsetName);}/*** 根据约定往商户发送报文,报文属性为xmldata* @param url 发送报文地址* @param xmldata 发送报文的xml String* @return 请求响应消息字符串* @throws IOException* @deprecated 使用{@link #postMap(String, Map)}*/@Deprecatedpublic String sendMerchantMsg(String url, String xmldata) throws IOException {return sendMerchantMsg(url, xmldata, CHARSET_UTF_8);}/*** 根据约定往商户发送报文,报文属性为xmldata* @param url 发送报文地址* @param xmldata 发送报文的xml String* @param charsetName 编码格式* @param charsetName 编码格式* @return 请求响应消息字符串* @throws IOException* @deprecated 使用{@link #postMap(String, Map, String)}*/@Deprecatedpublic String sendMerchantMsg(String url, String xmldata, String charsetName) throws IOException {// post请求HttpPost httpost = new HttpPost(url);// 设置参数List<NameValuePair> params = new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("xmldata", xmldata));// 对参数进行编码httpost.setEntity(new UrlEncodedFormEntity(params, Charset.forName(charsetName)));//发起请求String responseText = httpRequest(httpost, charsetName);return responseText;}/*** 根据与省端约定发送报文,报文格式为xmlhead和xmlbody* @param url 报文地址* @param xmlHead 报文头* @param xmlBody 报文体* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException*/public String sendCrmMsg(String url, String xmlHead, String xmlBody) throws ClientProtocolException, ParseException, IOException {return sendCrmMsg(url, xmlHead, xmlBody, CHARSET_UTF_8);}/*** 根据与省端约定发送报文,报文格式为xmlhead和xmlbody* @param url 报文地址* @param xmlHead 报文头* @param xmlBody 报文体* @param charsetName 编码格式* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException*/public String sendCrmMsg(String url, String xmlHead, String xmlBody, String charsetName) throws ClientProtocolException, ParseException, IOException {StringBody head = null;StringBody body = null;/*  head = new StringBody(xmlHead, ContentType.create("text/plain", Charset.forName(charsetName)));body = new StringBody(xmlBody, ContentType.create("text/plain", Charset.forName(charsetName)));*/head = new StringBody(xmlHead);body = new StringBody(xmlBody);HttpEntity entity = MultipartEntityBuilder.create().addPart("xmlhead", head).addPart("xmlbody", body).setCharset(Charset.forName(charsetName)).build();HttpPost httpost = new HttpPost(url);httpost.setEntity(entity);return httpRequest(httpost, charsetName);}/*** 发送字符串消息到指定url* @param url 消息接收的url* @param msg 请求消息* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException*/public String sendStringMsg(String url, String msg) throws ClientProtocolException, ParseException, IOException {return sendStringMsg(url, msg, CHARSET_UTF_8);}/*** 发送字符串消息到指定url* @param url 消息接收的url* @param msg 请求消息* @return 请求响应消息字符串* @throws IOException* @throws ParseException* @throws ClientProtocolException*/public String sendStringMsg(String url, String msg, String charsetName) throws ClientProtocolException, ParseException, IOException {//字符串EntityStringEntity entity = null;entity = new StringEntity(msg, Charset.forName(charsetName));//http post请求HttpPost httpost = new HttpPost(url);httpost.setEntity(entity);return httpRequest(httpost, charsetName);}/*** http 请求* @param request* @return 请求响应消息字符串* @throws* @throws IOException* @throws ParseException*/private String httpRequest(HttpUriRequest request, String charsetName)throws ClientProtocolException, ParseException, IOException {String responseText = null;CloseableHttpResponse response = null;HttpEntity entitys = null;try {response = closeableHttpClient.execute(request);if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {entitys = response.getEntity();if (entitys != null) {// 将返回实体转换为字符串responseText = EntityUtils.toString(entitys, Charset.forName(charsetName));}} else {// 放弃连接request.abort();}} catch (ClientProtocolException e) {throw e;} catch (ParseException e) {throw e;} catch (IOException e) {throw e;} finally {if (entitys != null) {try {//释放资源可用触发连接放回连接池EntityUtils.consume(entitys);} catch (IOException e) {throw e;}}}return responseText;}/*** 重发处理器*/private HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {// 打印警告信息
//          logger.warn(String.format("HttpClient向%s发起请求失败,出现异常%s,第%d次进入重发处理器判断是否需要重发。", context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST), exception,executionCount));if (executionCount >= retryCount) {// Do not retry if over max retry countreturn false;}if (exception instanceof ConnectTimeoutException) {// Connection refusedreturn true;}if (exception instanceof UnknownHostException) {// Unknown hostreturn true;}if (exception instanceof InterruptedIOException) {// Timeoutreturn true;}if (exception instanceof SSLException) {// SSL handshake exceptionreturn false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);if (idempotent) {// 必须是幂等性的才能进行重发return true;}return false;}};/*** 信任管理器*/private static X509TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public X509Certificate[] getAcceptedIssuers() {return null;}};public int getMaxConnTotal() {return maxConnTotal;}public void setMaxConnTotal(int maxConnTotal) {this.maxConnTotal = maxConnTotal;}public int getMaxConnPerRoute() {return maxConnPerRoute;}public void setMaxConnPerRoute(int maxConnPerRoute) {this.maxConnPerRoute = maxConnPerRoute;}public int getTimeout() {return timeout;}public void setTimeout(int timeout) {this.timeout = timeout;}public int getRetryCount() {return retryCount;}public void setRetryCount(int retryCount) {this.retryCount = retryCount;}}

2.证书加解密(获取证书信息、加解密、随机生成秘钥等)

package com.xxxxx.util;import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;public class SecurityUtil {/*** 按指定的字符集进行 Base64编码* @param text     原码* @param charset 字符集* @return String    编码* @throws Exception*/public static String encodeBase64(String text, String charset) throws Exception {String retData = null;if (StringUtils.isNotBlank(text)) {byte[] b = null;if (StringUtils.isBlank(charset)) {b = encodeBase64(text.getBytes());} else {b = encodeBase64(text.getBytes(charset));}retData = new String(b);}return retData;}/*** 对Base64编码进行解码* @param data     原码* @return byte[] 编码* @throws Exception*/public static byte[] encodeBase64(byte[] data) throws Exception {if (data != null && data.length > 0) {return Base64.encodeBase64(data);} else {return null;}}/*** 按指定的字符集对 Base64编码进行解码* @param text      编码* @param charset 字符集* @return String    原码* @throws Exception*/public static String decodeBase64(String text, String charset) throws Exception {String retData = null;if (StringUtils.isNotBlank(text)) {byte[] b = decodeBase64(text.getBytes());if (StringUtils.isBlank(charset)) {retData = new String(b);} else {retData = new String(b, charset);}}return retData;}/*** 对Base64编码进行解码* @param data       编码* @return byte[] 原码* @throws Exception*/public static byte[] decodeBase64(byte[] data) throws Exception {if (data != null && data.length > 0) {return Base64.decodeBase64(data);} else {return null;}}/*** 将字节数组转换成16进制的字符串* @param bytes      字节数组* @return String   16进制字符串* @throws Exception*/public static String encodeByte2HexString(byte[] bytes) throws Exception {if (bytes != null && bytes.length > 0) {return new String(Hex.encodeHex(bytes));} else {return null;}}/*** 将16进制的字符串转换成字节数组* @param text        16进制字符串* @return byte[]    字节数组* @throws Exception*/public static byte[] decodeHexString2Byte(String text) throws Exception {if (StringUtils.isNotBlank(text)) {return Hex.decodeHex(text.toCharArray());} else {return null;}}/*** 根据指定的密钥和算法转换格式对数据进行加密,算法转换格式为:算法或算法/模式/填充,其中:* 算法可:AES、DES、DESede、RC2、RSA;* 模式可:NONE、CBC、CFB|CFBx、 CTR、CTS、ECB、OFB、OFBx、PCBC;* 填充可:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding* @param data      原文数据* @param key       加密密钥* @param transformation    转换格式* @return byte[]   密文数据* @throws Exception*/public static byte[] encrypt(byte[] data, byte[] key, String transformation) throws Exception {if (data == null || data.length == 0 || key == null || key.length == 0 || StringUtils.isBlank(transformation)) {throw new Exception("加密数据或加密密钥或加密算法为空");}String algorithm = null;if (transformation.indexOf('/') > 0) {algorithm = transformation.substring(0, transformation.indexOf('/'));} else {algorithm = transformation;}Cipher cipher = Cipher.getInstance(transformation);if (algorithm.startsWith("RSA")) {KeyFactory factory = KeyFactory.getInstance("RSA");RSAPublicKey rpk = (RSAPublicKey)factory.generatePublic(new X509EncodedKeySpec(key));cipher.init(Cipher.ENCRYPT_MODE, rpk);}else if (algorithm.startsWith("DES")) {// 生成一个可信任的随机数源  SecureRandom sr = new SecureRandom();  // 从原始密钥数据创建DESKeySpec对象  DESKeySpec dks = new DESKeySpec(key);  // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);  SecretKey securekey = keyFactory.generateSecret(dks);  // 用密钥初始化Cipher对象  cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);  } else {SecretKeySpec sks = new SecretKeySpec(key, algorithm);cipher.init(Cipher.ENCRYPT_MODE, sks);}return cipher.doFinal(data);}/*** 根据指定的密钥和算法转换格式对数据进行加密,算法转换格式为:算法或算法/模式/填充,其中:* 算法可:AES、DES、DESede、RC2、RSA;* 模式可:NONE、CBC、CFB|CFBx、 CTR、CTS、ECB、OFB、OFBx、PCBC;* 填充可:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding* @param text        原文数据* @param charset   报文字符集* @param key      加密密钥* @param transformation    转换格式* @return String   经Base64转码的密文数据* @throws Exception*/public static String encrypt(String text, String charset, byte[] key, String transformation) throws Exception {String ciphertxt = null;if (StringUtils.isNotBlank(text)) {byte[] data = null;if (StringUtils.isBlank(charset)) {data = text.getBytes();} else {data = text.getBytes(charset);}byte[] cipher = encrypt(data, key, transformation);/*if (transformation.startsWith("DES")) {String strs = new BASE64Encoder().encode(cipher);return strs;  }else {*/ciphertxt = new String(encodeBase64(cipher));cipher = decodeBase64(ciphertxt.getBytes());/*}*/}return ciphertxt;}/*** 根据指定的密钥和算法转换格式对加密数据进行解密,其中算法转换格式为:算法或算法/模式/填充,其中* 算法:AES、DES、DESede、RC2、RSA;* 模式:NONE、CBC、CFB|CFBx、CTR、CTS、ECB、OFB、OFBx、PCBC;* 填充:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding* @param data      密文数据* @param key       加密密钥* @param transformation    转换格式* @return byte[]   原文数据* @throws Exception*/public static byte[] decrypt(byte[] data, byte[] key, String transformation) throws Exception {if (data == null || data.length == 0 || key == null || key.length == 0 || StringUtils.isBlank(transformation)) {throw new Exception("解密数据或解密密钥或解密算法为空");}String algorithm = null;if (transformation.indexOf('/') > 0) {algorithm = transformation.substring(0, transformation.indexOf('/'));} else {algorithm = transformation;}Cipher cipher = Cipher.getInstance(transformation);if (algorithm.startsWith("RSA")) {KeyFactory factory = KeyFactory.getInstance("RSA");RSAPrivateKey rpk = (RSAPrivateKey)factory.generatePrivate(new PKCS8EncodedKeySpec(key));cipher.init(Cipher.DECRYPT_MODE, rpk);}else if (algorithm.startsWith("DES")) {// 生成一个可信任的随机数源  SecureRandom sr = new SecureRandom();  // 从原始密钥数据创建DESKeySpec对象  DESKeySpec dks = new DESKeySpec(key);  // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);  SecretKey securekey = keyFactory.generateSecret(dks);  // Cipher对象实际完成解密操作  cipher = Cipher.getInstance(algorithm);  // 用密钥初始化Cipher对象  cipher.init(Cipher.DECRYPT_MODE, securekey, sr);  } else {SecretKeySpec sks = new SecretKeySpec(key, algorithm);cipher.init(Cipher.DECRYPT_MODE, sks);}return cipher.doFinal(data);}/*** 根据指定的密钥和算法转换格式对加密数据进行解密,其中算法转换格式为:算法或算法/模式/填充,其中* 算法:AES、DES、DESede、RC2、RSA;* 模式:NONE、CBC、CFB|CFBx、CTR、CTS、ECB、OFB、OFBx、PCBC;* 填充:NoPadding、ISO10126Padding、OAEPPadding、OAEPWith<digest>And<mgf>Padding、PKCS1Padding、 PKCS5Padding、SSL3Padding* @param ciphertxt    经Base64转码的密文数据* @param charset 报文字符集* @param key      加密密钥* @param transformation    转换格式* @return String   原文数据* @throws Exception*/public static String decrypt(String ciphertxt, String charset, byte[] key, String transformation) throws Exception {String text = null;if (StringUtils.isNotBlank(ciphertxt)) {byte[] cipher = decodeBase64(ciphertxt.getBytes());byte[] data = decrypt(cipher, key, transformation);if (StringUtils.isBlank(charset)) {text = new String(data);} else {text = new String(data, charset);}}return text;}/*** 根据指定的算法(MD2、MD5、SHA1、SHA256、SHA384、SHA512)进行报文摘要* @param data        原始报文* @param algorithm 摘要算法* @return byte[]   报文摘要* @throws Exception*/public static byte[] messageDigest(byte[] data, String algorithm) throws Exception {byte[] digest = null;if (data != null && data.length > 0) {MessageDigest md = MessageDigest.getInstance(algorithm);digest = md.digest(data);}return digest;}/*** 根据指定的算法(MD2、MD5、SHA1、SHA256、SHA384、SHA512)和指定的报文字符集进行报文摘要* @param text     原始报文* @param charset   报文字符集* @param algorithm    摘要算法* @return byte[]   报文摘要* @throws Exception*/public static String messageDigestHex(String text, String charset, String algorithm) throws Exception {byte[] digest = null;if (StringUtils.isNotBlank(text)) {byte[] data = null;if (StringUtils.isBlank(charset)) {data = text.getBytes();} else {data = text.getBytes(charset);}digest = messageDigest(data, algorithm);}return encodeByte2HexString(digest);}/*** 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和密钥对报文数据进行数字签名* @param data     报文数据* @param algorithm 签名算法* @param Key       签名私钥* @return byte[]   数字签名* @throws Exception*/public static byte[] sign(byte[] data, String algorithm, PrivateKey key) throws Exception {if (data == null || data.length == 0 || StringUtils.isBlank(algorithm) || key == null) {throw new Exception("待签名数据或签名算法或签名私钥为空");}Signature sign = Signature.getInstance(algorithm);sign.initSign(key);sign.update(data);return sign.sign();}/*** 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和经过16进制转码、Base64编码的密钥对报文数据进行数字签名* @param text        报文数据* @param charset   字符集* @param algorithm  签名算法* @param Key       签名私钥* @return String   经16进制转码后的数字签名* @throws Exception*/public static String sign(String text, String charset, String algorithm, byte[] key) throws Exception {//public static String sign(String text, String charset, String algorithm, PrivateKey privateKey) throws Exception {byte[] data = null;if (StringUtils.isBlank(charset)) {data = text.getBytes();} else {data = text.getBytes(charset);}String keyAlgorithm = null;KeySpec keySpec = null;if (algorithm.endsWith("RSA")) {keyAlgorithm = "RSA";keySpec = new PKCS8EncodedKeySpec(key);} else {keyAlgorithm = algorithm;keySpec = new X509EncodedKeySpec(key);}KeyFactory factory = KeyFactory.getInstance(keyAlgorithm);PrivateKey privateKey = factory.generatePrivate(keySpec);byte[] signData = sign(data, algorithm, privateKey);return encodeByte2HexString(signData);}/*** 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和密钥对数字签名进行验证* @param data     报文数据* @param signature 数字签名* @param algorithm 签名算法* @param Key       验签公钥* @return boolean  验签结果:true 验签通过; false 验签失败* @throws Exception*/public static boolean verify(byte[] data, byte[] signature, String algorithm, PublicKey key) throws Exception {if (signature == null || signature.length == 0 || StringUtils.isBlank(algorithm) || key == null) {throw new Exception("签名数据或签名算法或签名钥为空");}Signature sign = Signature.getInstance(algorithm);sign.initVerify(key);sign.update(data);return sign.verify(signature);}/*** 根据指定的算法(NONEwithRSA、MD2withRSA、MD5withRSA、SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)和经16进制转码、Base64编码的密钥对数字签名进行验证* @param text      报文数据* @param charset   字符集* @param signature  经16进制转码的数字签名* @param algorithm 签名算法* @param Key       验签公钥* @return boolean  验签结果:true 验签通过; false 验签失败* @throws Exception*/public static boolean verify(String text, String charset, String signature, String algorithm, byte[] key) throws Exception {//public static boolean verify(String text, String charset, String signature, String algorithm, PublicKey publicKey) throws Exception {byte[] data = null;if (StringUtils.isBlank(charset)) {data = text.getBytes();} else {data = text.getBytes(charset);}String keyAlgorithm = null;if (algorithm.endsWith("RSA")) {keyAlgorithm = "RSA";} else {keyAlgorithm = algorithm;}KeySpec keySpec = new X509EncodedKeySpec(key);KeyFactory factory = KeyFactory.getInstance(keyAlgorithm);PublicKey publicKey = factory.generatePublic(keySpec);return verify(data, decodeHexString2Byte(signature), algorithm, publicKey);}/*** 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建加密密钥* @param algorithm 算法* @param keysize 密钥大小* @return SecretKey    密钥* @throws Exception*/public static SecretKey generateKey(String algorithm, int keysize) throws Exception {if (StringUtils.isBlank(algorithm) || keysize < 0) {throw new Exception("产生密钥的算法为空或密钥长度为空");}KeyGenerator generator = KeyGenerator.getInstance(algorithm);SecureRandom random = SecureRandom.getInstance("SHA1PRNG");if (keysize > 0) {generator.init(keysize, random);} else {generator.init(random);}return generator.generateKey();}/*** 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建加密密钥* @param algorithm   算法* @param keysize 密钥大小* @return String   经16进制转码的密钥* @throws Exception*/public static String generateSecretKey(String algorithm, int keysize) throws Exception {String key = null;SecretKey secretKey = generateKey(algorithm, keysize);if (secretKey != null) {key = encodeByte2HexString(secretKey.getEncoded());}return  key;}/*** 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建一组随机密钥对(公钥、私钥)* @param algorithm  算法* @param keysize 密钥大小* @return KeyPair  密钥对* @throws Exception*/public static KeyPair generateKeyPair(String algorithm, int keysize) throws Exception {if (StringUtils.isBlank(algorithm) || keysize <= 0) {throw new Exception("产生密钥的算法为空或密钥长度为空");}KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm);SecureRandom random = SecureRandom.getInstance("SHA1PRNG");generator.initialize(keysize, random);return generator.genKeyPair();}/*** 根据指定的算法(DSA、RSA、EC、DiffieHellman)创建一组随机密钥对(公钥、私钥),并将密钥转换16进制字符串再进行Base64编码* @param algorithm  摘要算法* @param keysize   密钥大小* @return String[] 密钥数组,密钥存放次序:公钥、私钥* @throws Exception*/public static String[] generateSecretKeys(String algorithm, int keysize) throws Exception {String[] keys = null;KeyPair keyPair = generateKeyPair(algorithm, keysize);if (keyPair != null) {keys = new String[2];byte[] key = keyPair.getPublic().getEncoded();keys[0] = encodeByte2HexString(key);key = keyPair.getPrivate().getEncoded();keys[1] = encodeByte2HexString(key);}return keys;}

读取私钥代码

KeyStore ks = KeyStore.getInstance("JKS");//File file = FileUtil.getFile("cmsz_keystore");File file = FileUtil.getFile(ConfigUtil.getProperty("keyStoreFile"));FileInputStream fis = new FileInputStream(file);ks.load(fis, ConfigUtil.getProperty("keyStorePwd").toCharArray());privateKey = (PrivateKey) ks.getKey(ConfigUtil.getProperty("alias"), ConfigUtil.getProperty("keyPwd").toCharArray());

读取公钥代码

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");File file = FileUtil.getFile(ConfigUtil.getProperty("caCertificateFile"));FileInputStream fis = new FileInputStream(file);X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(fis);publicKey = certificate.getPublicKey();

具体代码:

package com.xxxx.util;import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import com.xxxx.util.XmlUtil;public class SignUtil {private static Log log = LogFactory.getLog(SignUtil.class);/*** 数字签名:将Map对象转换成Xml报文,并添加采用SHA1WithRSA算法进行的数字签名,* @param map          Map对象* @param transactionId    交易流水号* @param channelId        渠道id* @param isExtSystem   是否外部系统签名* @return String       16进制转码后的数字签名* @throws Exception*/public static String sign(Map map, String transactionId, String channelId, boolean isExtSystem) throws Exception {//String ADVPAY = "AdvPay";//业务平台根节点String xml = XmlUtil.format(map, "AdvPay", "GBK");//String BUSI_DATA = "BusiData";String message = transactionId + XmlUtil.getElementXml(xml, "BusiData").trim();String signature = sign(message, channelId, isExtSystem);//String VERIFY_CODE = "VerifyCode";//验证码xml = XmlUtil.setElementValue(xml, "VerifyCode", signature);return xml;}/*** 数字签名:将Map对象转换成Xml报文,并添加采用SHA1WithRSA算法进行的数字签名,* @param map          Map对象* @param transactionId    交易流水号* @param channelId        渠道id* @return String       16进制转码后的数字签名* @throws Exception*/public static String sign(Map map, String transactionId, String channelId) throws Exception {return sign(map,transactionId,channelId,false);}/*** 数字签名:根据指定的渠道编号、密钥类型从密钥配置表中获取相关密钥,再使用该密钥对报文数据进行SHA1WithRSA算法的签名* @param message       报文* @param channelId       渠道id* @param isExtSystem   是否外部系统签名* @return String       16进制转码后的数字签名* @throws Exception*/public static String sign(String message, String channelId, boolean isExtSystem) throws Exception {String signature = null;if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {log.error("待签名数据:" + message);/*IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/String value="true";if (value == null) {throw new Exception("渠道编号["+channelId+"]密钥不存在!");}String key = null;PrivateKey privateKey =null;if (isExtSystem) {KeyStore ks = KeyStore.getInstance("JKS");//File file = FileUtil.getFile("cmsz_keystore");File file = FileUtil.getFile(ConfigUtil.getProperty("keyStoreFile"));FileInputStream fis = new FileInputStream(file);ks.load(fis, ConfigUtil.getProperty("keyStorePwd").toCharArray());privateKey = (PrivateKey) ks.getKey(ConfigUtil.getProperty("alias"), ConfigUtil.getProperty("keyPwd").toCharArray());//是外部系统私钥byte[] encoded = privateKey.getEncoded();char[] encodeHex = Hex.encodeHex(encoded);StringBuffer sb=new StringBuffer();for (char c : encodeHex) {sb.append(c+"");}key=sb.toString();System.out.println("-----key----"+key);//key ="30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100a9d1c7d8add8fe191f4f6008cd28b745238e71d6f06734e8bd785add6e98a629a4410176b370f12f3777eef656088f6ec37206a38f38f722439fa70f20f7162a9812e04645e272b6a8c7c6fdff47e7ecc85a69203bee8fc63198838a4f4cd0e9314d75d1ef92daa7a2630c9ed21dc9da82abfde2aca0ef38f1589fab811e91eb0203010001028180680f5b75c439e6a2c053e456205965cc6118655bbf5e8ec65b6c07ca0e7e4dbbd0a1e0e2badc677e766ff0a7545ad4819c14204b537525c3024b2f948eafba0d866e6cf06c29475da9742ede90697b3691dcd1c7b879ecc6dbad5e37c619fd6c54f595555ddd60c4f4dc9b4082c08ba1b725d268474e7b80c5b9fa57a1a93fc9024100f77369ae906c3c45186cdf97de13de37ab6b746899777a879c458fd740daea4e5362bcc9c0716eb721ba627f5450e5889d8e684c97f954e908b19abc20460245024100afafc12871e2c9f5c3439d7e24292be83e6299d63311fab06320e616b0b9e63529c0199538e2aa5a04afee5181c8bef331c6184ded7f268086e1249b5c399e6f02410080b616ad874fd555b76bc22df384f01c92dcb4d347a85f22b4c576196811b6b8812525bfe78ad92506b53550b7e1d052ec694b9533a3ac67fe6eab66d97eb0e50241009e2d122e94e2c84ca2227560c5b3dfd93899d3c1bbb75b4a85e56fe34bf803a127d6d1f1bd06aeb35f76fa8d9dd91cba9ebca8d33899fb134adcd7f59cc22fb7024100c71a9943caa962b6f5c147289ab0e41796ad07fa425d7cd1ad9998984cc69045de99382c007c566a5104c0d98018136e23e18f567dada06f2826db524cebbe11";} else {//key = value.getPayPrivateKey();}byte[] k = SecurityUtil.decodeHexString2Byte(key);signature = SecurityUtil.sign(message, null, "SHA1WithRSA", k);log.error("签名结果:" + signature);}return signature;}/*** 签名验证:根据指定的渠道编号、密钥类型从密钥配置表中获取相关密钥,再使用该密钥和报文数据对数字签名进行SHA1WithRSA算法的签名验证* @param message       报文* @param signature       16进制转码后的数字签名* @param channelId     渠道id* @param isExtSystem   是否外部系统签名验证* @return boolean        数字签名验证结果:true 验证通过;false 验证失败* @throws Exception*/public static boolean verify(String message, String signature, String channelId, boolean isExtSystem) throws Exception {boolean verifyResult = false;if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {log.error("待验签数据:" + message);/*    IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/String value="key";if (value == null) {throw new Exception("渠道编号["+channelId+"]密钥不存在!");}String key = null;PublicKey publicKey=null;if (isExtSystem) {CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");File file = FileUtil.getFile(ConfigUtil.getProperty("caCertificateFile"));FileInputStream fis = new FileInputStream(file);X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(fis);publicKey = certificate.getPublicKey();byte[] encoded = publicKey.getEncoded();char[] encodeHex = Hex.encodeHex(encoded);StringBuffer bf=new StringBuffer();for (char c : encodeHex) {bf.append(c+"");}System.out.println("---pubkey----"+bf.toString());//获取外部系统公钥key=bf.toString();//key = "30819f300d06092a864886f70d010101050003818d0030818902818100a9d1c7d8add8fe191f4f6008cd28b745238e71d6f06734e8bd785add6e98a629a4410176b370f12f3777eef656088f6ec37206a38f38f722439fa70f20f7162a9812e04645e272b6a8c7c6fdff47e7ecc85a69203bee8fc63198838a4f4cd0e9314d75d1ef92daa7a2630c9ed21dc9da82abfde2aca0ef38f1589fab811e91eb0203010001".trim();} else {//key = value.getPayPublicKey();}byte[] k = SecurityUtil.decodeHexString2Byte(key);verifyResult = SecurityUtil.verify(message, null, signature, "SHA1WithRSA", k);log.error("签名结果:" + verifyResult);}return verifyResult;}/*** 报文加密:根据渠道编号、密钥类型从密钥配置表中查询相关加密密钥,再使用该密钥对报文数据进行RSA算法加密* @param message        原文* @param channelId       渠道id* @param isExtSystem   是否外部系统签名* @return String       16进制转码后的加密密文* @throws Exception*/public static String encrypt(String message, String channelId, boolean isExtSystem) throws Exception {String ciphertxt = null;if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(channelId)) {/*IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/String key = null;if (isExtSystem) {//key = value.getExtPublicKey();} else {//key = value.getPayPublicKey();}byte[] k = SecurityUtil.decodeHexString2Byte(key);ciphertxt = SecurityUtil.encrypt(message, "GBK", k, "RSA/ECB/PKCS1Padding");}return ciphertxt;}/*** 密文解密:根据渠道编号、密钥类型从密钥配置表中查询相关加密密钥,再使用该密钥对加密报文数据进行RSA算法解密* @param ciphertxt     16进制转码后的加密密文* @param channelId     渠道id* @param isExtSystem   是否外部系统签名* @return String       原文* @throws Exception*/public static String decrypt(String ciphertxt, String channelId, boolean isExtSystem) throws Exception {String message = null;if (StringUtils.isNotBlank(ciphertxt) && StringUtils.isNotBlank(channelId)) {/*  IBsKeyManageSV sv = (IBsKeyManageSV)ServiceFactory.getSeviceOfLocal(IBsKeyManageSV.class);IBOBsKeyManageValue value = sv.getBsKeyManageByChannelId(channelId);*/String key = null;if (isExtSystem) {//   key = value.getExtPrivateKey();} else {//  key = value.getPayPrivateKey();}byte[] k = SecurityUtil.decodeHexString2Byte(key);message = SecurityUtil.decrypt(ciphertxt, "GBK", k, "RSA/ECB/PKCS1Padding");}return message;}/*** 生成一个随机数并通过MD5算法进行报文摘要* @param ciphertxt     16进制转码后的加密密文* @param channelId     渠道id* @param isExtSystem   是否外部系统签名* @return String       原文* @throws Exception*/public static String getNonceStr() throws Exception {Random random = new Random();return SecurityUtil.messageDigestHex(String.valueOf(random.nextInt(10000)), null, "MD5");}/*** 按Map对象中Key的子字符串次序从小到大排序生成URL参数串,其格式为:key1=value1&key2=value2…* @param map          Map对象* @param encode       编码格式* @return String       URL参数串* @throws Exception*/public static String createUrlQueryString(Map<String, String> map, String encode) throws Exception {Object[] keys = map.keySet().toArray();Arrays.sort(keys);StringBuffer sb = new StringBuffer();for (Object key : keys) {String value = map.get(key);if (value != null) {if (sb.length() > 0) {sb.append("&");}sb.append(key.toString()).append('=');if (StringUtils.isBlank(encode)) {sb.append(value);} else {sb.append(URLEncoder.encode(value, encode));}}}return sb.toString();}
package com.xxxx.xxxx.common.util;import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;/*** <p>Title: XML报文处理工具</p>* <p>Description: 提供各种XML报文数据与Map对象间的转换方法</p>* <p>Copyright: Copyright (c) 2015</p>* <p>Company: AI(NanJing)</p>* @author ZhouZH* @date 2015-09-21* @version 1.0*/public class XmlUtil {/*** 将指定的Map对象转换成XML报文* @param map            Map对象* @param root         指定XML报文的根节点名称* @param encoding     字符集* @return String        转换后的XML报文* @throws Exception*/public static String format(Map map, String root, String encoding) throws Exception {String xml = null;if (map != null && map.size() > 0) {Document document = DocumentHelper.createDocument();document.setXMLEncoding(encoding);Element rootElement = document.addElement(root);format(rootElement, map);xml = document.asXML();}return xml;}/*** 将指定的XML报文转换成Map对象,忽略根节点* @param xml           XML字符串* @return String     转换后的XML报文* @throws Exception*/public static Map parse(String xml) throws Exception {Map map = null;if (StringUtils.isNotBlank(xml)) {SAXReader reader = null;StringReader sr = null;try {reader = new SAXReader();sr = new StringReader(xml);Document document = reader.read(sr);Element root = document.getRootElement();map = (Map) parse(root);System.out.println(map);} finally {if (sr != null) {sr.close();}}}return map;}/*** 从现有的XML报文中截取指定XML元素相关的内容* @param xmlElmentName  XML元素名称* @return Object        数据对象* @throws Exception*/public static String getElementXml(String xml, String xmlElmentName) {String elementXml = null;if (StringUtils.isNotBlank(xml)) {String perfix = String.format("<%s>", xmlElmentName);String suffix = String.format("</%s>", xmlElmentName);int beginIndex = xml.indexOf(perfix);int endIndex = xml.indexOf(suffix);if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {elementXml = xml.substring(beginIndex, endIndex + suffix.length());}}return elementXml;}/*** 从现有的XML报文中截取指定XML元素的值* @param xml         XML报文* @param xmlElmentName    XML元素名称* @return String        数据对象* @throws Exception*/public static String getElementValue(String xml, String xmlElmentName) {String value = null;String elementXml = getElementXml(xml, xmlElmentName);if (StringUtils.isNotBlank(elementXml)) {int beginIndex = elementXml.indexOf(">");int endIndex = elementXml.lastIndexOf("<");if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {value = elementXml.substring(beginIndex + 1, endIndex);}}return value;}/*** 从现有的XML报文中截取指定XML元素的值* @param xml          XML报文* @param xmlElmentName    XML元素名称* @param xmlElmentValueXML元素内容* @return Object     数据对象* @throws Exception*/public static String setElementValue(String xml, String xmlElmentName, String xmlElmentValue) {String value = null;if (StringUtils.isNotBlank(xml)) {String perfix = String.format("<%s>", xmlElmentName);String suffix = String.format("</%s>", xmlElmentName);int beginIndex = xml.indexOf(perfix);int endIndex = xml.indexOf(suffix);if (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex) {value = xml.substring(0, beginIndex) + perfix + xmlElmentValue + xml.substring(endIndex);}}return value;}/*** 将指定的数据对象转换成XML元素对象* @param parent      XML元素对象的父节点* @param object     数据对象* @return void         无* @throws Exception*/private static void format(Element parent, Object object) {if (object != null) {if (object instanceof Map) {Set set = ((Map)object).keySet();Iterator iterator = set.iterator();while (iterator.hasNext()) {Object key = iterator.next();Element child = parent.addElement(key.toString());Object value = ((Map) object).get(key);format(child, value);}} else if (object instanceof List) {Element p = parent.getParent();Iterator iterator = ((List)object).iterator();while (iterator.hasNext()) {Object value = iterator.next();Element child = parent.createCopy();p.add(child);format(child, value);}} else if (object instanceof Object[]) {Element p = parent.getParent();for(Object value : (Object[])object) {Element child = parent.createCopy();p.add(child);format(child, value);}p.remove(parent);} else {parent.setText(object.toString());}}}/*** 将XML元素对象转换成数据对象* @param element       XML元素对象* @return Object        数据对象* @throws Exception*/private static Object parse(Element element) {Object object = null;if (element != null && element.isTextOnly()) {object = element.getText();} else {Map map = new HashMap();Iterator iterator = element.elementIterator();while (iterator.hasNext()) {Element e = (Element) iterator.next();String key = e.getName();Object value = parse(e);Object v = map.get(key);if (v != null) {List list = null;if (v instanceof List) {list = (List)v;} else {list = new ArrayList();list.add(v);map.put(key, list);}list.add(value);} else {map.put(key, value);}}object = map;}return object;}}

工具类-httpClient工具类相关推荐

  1. Java开发小技巧(五):HttpClient工具类

    前言 大多数Java应用程序都会通过HTTP协议来调用接口访问各种网络资源,JDK也提供了相应的HTTP工具包,但是使用起来不够方便灵活,所以我们可以利用Apache的HttpClient来封装一个具 ...

  2. HttpClient工具类

    HttpClient工具类 package cn.sh.steven.httpclient;import com.alibaba.fastjson.JSON; import com.alibaba.f ...

  3. apache httpclient 工具类_HttpClient

    HttpClient 简介 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 ...

  4. apache httpclient 工具类_HttpClient 和Mycat 主从节点和读写分离

    第175次(HttpClient) 学习主题:HttpClient 学习目标: 1 掌握HttpClient自定义工具以及HttpClient具体的使用 对应视频: http://www.itbaiz ...

  5. apache httpclient 工具类_使用HttpClient进行服务的远程调用

    目标:使用apache公司的产品http httpcomponents 完成服务调用. HTTPClient调用服务 4:导入httpclient的依赖配置 org.apache.httpcompon ...

  6. 使用单例模式实现自己的HttpClient工具类

    本文转载自:http://www.cnblogs.com/codingmyworld/archive/2011/08/17/2141706.html 使用单例模式实现自己的HttpClient工具类 ...

  7. 14、阿里云短信Demo演示、Http的Get请求和Post请求演示、httpClient工具类演示、发送短信模块搭建、搭建用户中心模块、完成user注册基本功能、验证码存入redis、短信验证码注册

    阿里云短信Demo演示 一.前端部分 无前端. 二.后端部分 1.创建发送短信测试模块SmsSendDemo,不用使用骨架. 2.在pom文件中引入依赖坐标 <dependency>< ...

  8. HttpClient工具类封装

    HttpClient是Apache Jakarta Common下的子项目,用来提供高效的.最新的.功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议.HttpCli ...

  9. HttpClient工具类及应用

    Content-Type类型: 常见的媒体格式类型如下: text/html : HTML格式 text/plain :纯文本格式 text/xml : XML格式 image/gif :gif图片格 ...

最新文章

  1. TF (transform) in ROS
  2. ViewGroup1——自定义布局
  3. IT Monitor
  4. jdk动态代理与cglib动态代理例子
  5. [51nod1264]线段相交
  6. Codeforces Round #662 (Div. 2)
  7. matlab meshgrid
  8. netty 关闭chnnal_Netty 源码学习——服务端流程分析
  9. cas4.0 mysql_【SSO单点系列】:CAS4.0 CAS整合SpringMVC+MyBatis实现数据库校验(04)
  10. 介绍PS大局观很不错的转文
  11. app = Flask(__name__) 是个什么东西
  12. 2020牛客多校训练3 G Operating on a Graph(并查集+链式结构)
  13. 在Ubuntu 将PHP5升级到PHP7.0 PHP7.1
  14. 联想服务器ThinkServer网卡驱动程序缺失的解决办法
  15. html的android开发工具,只会html也可以做安卓app(附实例)
  16. Laravel学习笔记汇总——Eloquent Model模型和数据库操作
  17. 2021-2027全球与中国轧辊弯曲机市场现状及未来发展趋势
  18. 盘点2019年十大泡沫经济事件:今年哪个行业有点衰?
  19. 微信小程序开发之城市选择器 城市切换
  20. 网盘搜索神器php源码,127网盘搜索源码|网盘资源搜索神器|thinkphp3.1.3框架开发的...

热门文章

  1. Oracle 中的 (+) 到底是啥意思?
  2. Windows 修改本地的IP ,改成自己喜欢的IP
  3. 计算机图像隐藏信息,信息隐藏原理及应用
  4. 【游戏开发】天龙八部demo
  5. ICCV2021 | MicroNet:以极低的 FLOPs 改进图像识别
  6. linux运行rcp,Linux rcp 命令
  7. 无法加载控制器:Datas
  8. 2014/12/14实验室会议
  9. cad2020安装1603错误_AutoCAD2020安装不了什么原因 安装失败解决办法
  10. Void 指 针 和 NULL 指 针