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();
}
@PostConstruct
public 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)}
*/
@Deprecated
public 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)}
*/
@Deprecated
public 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 {
//字符串Entity
StringEntity 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 count
return false;
}
if (exception instanceof ConnectTimeoutException) {
// Connection refused
return true;
}
if (exception instanceof UnknownHostException) {
// Unknown host
return true;
}
if (exception instanceof InterruptedIOException) {
// Timeout
return true;
}
if (exception instanceof SSLException) {
// SSL handshake exception
return 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;
}
}