Commit b02e361c authored by zhangc's avatar zhangc

commit apigateway

parent eac58a08
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jz.dm.gateway.common.util;
import org.apache.commons.codec.BinaryDecoder;
import org.apache.commons.codec.BinaryEncoder;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
/**
* Provides Base64 encoding and decoding as defined by RFC 2045.
*
* <p>This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite>
* from RFC 2045 <cite>Multipurpose Internet Mail Extensions (MIME) Part One:
* Format of Internet Message Bodies</cite> by Freed and Borenstein.</p>
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
* @author Apache Software Foundation
* @since 1.0-dev
* @version $Id: Base64.java,v 1.20 2004/05/24 00:21:24 ggregory Exp $
*/
public class Base64 implements BinaryEncoder, BinaryDecoder {
/**
* Chunk size per RFC 2045 section 6.8.
*
* <p>The {@value} character limit does not count the trailing CRLF, but counts
* all other characters, including any equal signs.</p>
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
*/
static final int CHUNK_SIZE = 76;
/**
* Chunk separator per RFC 2045 section 2.1.
*
* @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
*/
static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes();
/**
* The base length.
*/
static final int BASELENGTH = 255;
/**
* Lookup length.
*/
static final int LOOKUPLENGTH = 64;
/**
* Used to calculate the number of bits in a byte.
*/
static final int EIGHTBIT = 8;
/**
* Used when encoding something which has fewer than 24 bits.
*/
static final int SIXTEENBIT = 16;
/**
* Used to determine how many bits data contains.
*/
static final int TWENTYFOURBITGROUP = 24;
/**
* Used to get the number of Quadruples.
*/
static final int FOURBYTE = 4;
/**
* Used to test the sign of a byte.
*/
static final int SIGN = -128;
/**
* Byte used to pad output.
*/
static final byte PAD = (byte) '=';
// Create arrays to hold the base64 characters and a
// lookup for base64 chars
private static byte[] base64Alphabet = new byte[BASELENGTH];
private static byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
// Populating the lookup and character arrays
static {
for (int i = 0; i < BASELENGTH; i++) {
base64Alphabet[i] = (byte) -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
}
for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
}
base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (byte) ('A' + i);
}
for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('a' + j);
}
for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (byte) ('0' + j);
}
lookUpBase64Alphabet[62] = (byte) '+';
lookUpBase64Alphabet[63] = (byte) '/';
}
private static boolean isBase64(byte octect) {
if (octect == PAD) {
return true;
} else if (base64Alphabet[octect] == -1) {
return false;
} else {
return true;
}
}
/**
* Tests a given byte array to see if it contains
* only valid characters within the Base64 alphabet.
*
* @param arrayOctect byte array to test
* @return true if all bytes are valid characters in the Base64
* alphabet or if the byte array is empty; false, otherwise
*/
public static boolean isArrayByteBase64(byte[] arrayOctect) {
arrayOctect = discardWhitespace(arrayOctect);
int length = arrayOctect.length;
if (length == 0) {
// shouldn't a 0 length array be valid base64 data?
// return false;
return true;
}
for (int i = 0; i < length; i++) {
if (!isBase64(arrayOctect[i])) {
return false;
}
}
return true;
}
/**
* Encodes binary data using the base64 algorithm but
* does not chunk the output.
*
* @param binaryData binary data to encode
* @return Base64 characters
*/
public static byte[] encodeBase64(byte[] binaryData) {
return encodeBase64(binaryData, false);
}
/**
* Encodes binary data using the base64 algorithm and chunks
* the encoded output into 76 character blocks
*
* @param binaryData binary data to encode
* @return Base64 characters chunked in 76 character blocks
*/
public static byte[] encodeBase64Chunked(byte[] binaryData) {
return encodeBase64(binaryData, true);
}
/**
* Decodes an Object using the base64 algorithm. This method
* is provided in order to satisfy the requirements of the
* Decoder interface, and will throw a DecoderException if the
* supplied object is not of type byte[].
*
* @param pObject Object to decode
* @return An object (of type byte[]) containing the
* binary data which corresponds to the byte[] supplied.
* @throws DecoderException if the parameter supplied is not
* of type byte[]
*/
@Override
public Object decode(Object pObject) throws DecoderException {
if (!(pObject instanceof byte[])) {
throw new DecoderException("Parameter supplied to Base64 decode is not a byte[]");
}
return decode((byte[]) pObject);
}
/**
* Decodes a byte[] containing containing
* characters in the Base64 alphabet.
*
* @param pArray A byte array containing Base64 character data
* @return a byte array containing binary data
*/
@Override
public byte[] decode(byte[] pArray) {
return decodeBase64(pArray);
}
/**
* Encodes binary data using the base64 algorithm, optionally
* chunking the output into 76 character blocks.
*
* @param binaryData Array containing binary data to encode.
* @param isChunked if isChunked is true this encoder will chunk
* the base64 output into 76 character blocks
* @return Base64-encoded data.
*/
public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
int lengthDataBits = binaryData.length * EIGHTBIT;
int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
byte encodedData[] = null;
int encodedDataLength = 0;
int nbrChunks = 0;
if (fewerThan24bits != 0) {
//data not divisible by 24 bit
encodedDataLength = (numberTriplets + 1) * 4;
} else {
// 16 or 8 bit
encodedDataLength = numberTriplets * 4;
}
// If the output is to be "chunked" into 76 character sections,
// for compliance with RFC 2045 MIME, then it is important to
// allow for extra length to account for the separator(s)
if (isChunked) {
nbrChunks =
(CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
}
encodedData = new byte[encodedDataLength];
byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
int i = 0;
int nextSeparatorIndex = CHUNK_SIZE;
int chunksSoFar = 0;
//log.debug("number of triplets = " + numberTriplets);
for (i = 0; i < numberTriplets; i++) {
dataIndex = i * 3;
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
b3 = binaryData[dataIndex + 2];
//log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
byte val3 =
((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
//log.debug( "val2 = " + val2 );
//log.debug( "k4 = " + (k<<4) );
//log.debug( "vak = " + (val2 | (k<<4)) );
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] =
lookUpBase64Alphabet[(l << 2) | val3];
encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 0x3f];
encodedIndex += 4;
// If we are chunking, let's put a chunk separator down.
if (isChunked) {
// this assumes that CHUNK_SIZE % 4 == 0
if (encodedIndex == nextSeparatorIndex) {
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedIndex,
CHUNK_SEPARATOR.length);
chunksSoFar++;
nextSeparatorIndex =
(CHUNK_SIZE * (chunksSoFar + 1)) +
(chunksSoFar * CHUNK_SEPARATOR.length);
encodedIndex += CHUNK_SEPARATOR.length;
}
}
}
// form integral number of 6-bit groups
dataIndex = i * 3;
if (fewerThan24bits == EIGHTBIT) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
//log.debug("b1=" + b1);
//log.debug("b1<<2 = " + (b1>>2) );
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4];
encodedData[encodedIndex + 2] = PAD;
encodedData[encodedIndex + 3] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03);
byte val1 =
((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 =
((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
encodedData[encodedIndex] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex + 1] =
lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2];
encodedData[encodedIndex + 3] = PAD;
}
if (isChunked) {
// we also add a separator to the end of the final chunk.
if (chunksSoFar < nbrChunks) {
System.arraycopy(
CHUNK_SEPARATOR,
0,
encodedData,
encodedDataLength - CHUNK_SEPARATOR.length,
CHUNK_SEPARATOR.length);
}
}
return encodedData;
}
/**
* Decodes Base64 data into octects
*
* @param base64Data Byte array containing Base64 data
* @return Array containing decoded data.
*/
public static byte[] decodeBase64(byte[] base64Data) {
// RFC 2045 requires that we discard ALL non-Base64 characters
base64Data = discardNonBase64(base64Data);
// handle the edge case, so we don't have to worry about it later
if (base64Data.length == 0) {
return new byte[0];
}
int numberQuadruple = base64Data.length / FOURBYTE;
byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
// Throw away anything not in base64Data
int encodedIndex = 0;
int dataIndex = 0;
{
// this sizes the output array properly - rlw
int lastData = base64Data.length;
// ignore the '=' padding
while (base64Data[lastData - 1] == PAD) {
if (--lastData == 0) {
return new byte[0];
}
}
decodedData = new byte[lastData - numberQuadruple];
}
for (int i = 0; i < numberQuadruple; i++) {
dataIndex = i * 4;
marker0 = base64Data[dataIndex + 2];
marker1 = base64Data[dataIndex + 3];
b1 = base64Alphabet[base64Data[dataIndex]];
b2 = base64Alphabet[base64Data[dataIndex + 1]];
if (marker0 != PAD && marker1 != PAD) {
//No PAD e.g 3cQl
b3 = base64Alphabet[marker0];
b4 = base64Alphabet[marker1];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
} else if (marker0 == PAD) {
//Two PAD e.g. 3c[Pad][Pad]
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
} else if (marker1 == PAD) {
//One PAD e.g. 3cQ[Pad]
b3 = base64Alphabet[marker0];
decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex + 1] =
(byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
}
encodedIndex += 3;
}
return decodedData;
}
/**
* Discards any whitespace from a base-64 encoded block.
*
* @param data The base-64 encoded data to discard the whitespace
* from.
* @return The data, less whitespace (see RFC 2045).
*/
static byte[] discardWhitespace(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++) {
switch (data[i]) {
case (byte) ' ' :
case (byte) '\n' :
case (byte) '\r' :
case (byte) '\t' :
break;
default:
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
/**
* Discards any characters outside of the base64 alphabet, per
* the requirements on page 25 of RFC 2045 - "Any characters
* outside of the base64 alphabet are to be ignored in base64
* encoded data."
*
* @param data The base-64 encoded data to groom
* @return The data, less non-base64 characters (see RFC 2045).
*/
static byte[] discardNonBase64(byte[] data) {
byte groomedData[] = new byte[data.length];
int bytesCopied = 0;
for (int i = 0; i < data.length; i++) {
if (isBase64(data[i])) {
groomedData[bytesCopied++] = data[i];
}
}
byte packedData[] = new byte[bytesCopied];
System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
return packedData;
}
// Implementation of the Encoder Interface
/**
* Encodes an Object using the base64 algorithm. This method
* is provided in order to satisfy the requirements of the
* Encoder interface, and will throw an EncoderException if the
* supplied object is not of type byte[].
*
* @param pObject Object to encode
* @return An object (of type byte[]) containing the
* base64 encoded data which corresponds to the byte[] supplied.
* @throws EncoderException if the parameter supplied is not
* of type byte[]
*/
@Override
public Object encode(Object pObject) throws EncoderException {
if (!(pObject instanceof byte[])) {
throw new EncoderException(
"Parameter supplied to Base64 encode is not a byte[]");
}
return encode((byte[]) pObject);
}
/**
* Encodes a byte[] containing binary data, into a byte[] containing
* characters in the Base64 alphabet.
*
* @param pArray a byte array containing binary data
* @return A byte array containing only Base64 character data
*/
@Override
public byte[] encode(byte[] pArray) {
return encodeBase64(pArray, false);
}
public static void main(String[] args) throws EncoderException, DecoderException {
// aGVsbG8gd29ybGQ=
// aGVsbG8gd29ybGQ=
System.out.println(new Base64().encode("hello world".getBytes()).getClass());
System.out.println(new String(new Base64().encode("hello world".getBytes())));
System.out.println(new String(new Base64().decode("aGVsbG8gd29ybGQ=".getBytes())));
}
}
package com.jz.dm.gateway.common.util;
import com.jz.dm.gateway.common.StringUtil;
import java.lang.reflect.Array;
import java.util.*;
/**
* <code>Class</code> 处理工具类
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ClassUtil {
/** 资源文件的分隔符: <code>'/'</code>。 */
public static final char RESOURCE_SEPARATOR_CHAR = '/';
/** Java类名的分隔符: <code>'.'</code>。 */
public static final char PACKAGE_SEPARATOR_CHAR = '.';
/** Java类名的分隔符: <code>"."</code>。 */
public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
/** 内联类的分隔符: <code>'$'</code>。 */
public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
/** 内联类的分隔符: <code>"$"</code>。 */
public static final String INNER_CLASS_SEPARATOR = String
.valueOf(INNER_CLASS_SEPARATOR_CHAR);
/** 所有类的信息表,包括父类, 接口, 数组的维数等信息。 */
private static Map TYPE_MAP = Collections
.synchronizedMap(new WeakHashMap());
/* ============================================================================ */
/* 取得类名和package名的方法。 */
/* ============================================================================ */
/**
* 取得对象所属的类的直观类名。
*
* <p>
* 相当于 <code>object.getClass().getName()</code> ,但不同的是,该方法用更直观的方式显示数组类型。 例如:
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param object 要显示类名的对象
*
* @return 用于显示的直观类名,如果原类名为空或非法,则返回 <code>null</code>
*/
public static String getClassNameForObject(Object object) {
if (object == null) {
return null;
}
return getClassName(object.getClass().getName(), true);
}
/**
* 取得直观的类名。
*
* <p>
* 相当于 <code>clazz.getName()</code> ,但不同的是,该方法用更直观的方式显示数组类型。 例如:
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param clazz 要显示类名的类
*
* @return 用于显示的直观类名,如果原始类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getClassName(Class clazz) {
if (clazz == null) {
return null;
}
return getClassName(clazz.getName(), true);
}
/**
* 取得直观的类名。
*
* <p>
* <code>className</code> 必须是从 <code>clazz.getName()</code> 所返回的合法类名。该方法用更直观的方式显示数组类型。 例如:
* <pre>
* int[].class.getName() = "[I" ClassUtil.getClassName(int[].class) = "int[]"
*
* Integer[][].class.getName() = "[[Ljava.lang.Integer;" ClassUtil.getClassName(Integer[][].class) = "java.lang.Integer[][]"
* </pre>
* </p>
*
* <p>
* 对于非数组的类型,该方法等效于 <code>Class.getName()</code> 方法。
* </p>
*
* <p>
* 注意,该方法所返回的数组类名只能用于显示给人看,不能用于 <code>Class.forName</code> 操作。
* </p>
*
* @param className 要显示的类名
*
* @return 用于显示的直观类名,如果原类名为 <code>null</code> ,则返回 <code>null</code> ,如果原类名是非法的,则返回原类名
*/
public static String getClassName(String className) {
return getClassName(className, true);
}
/**
* 取得直观的类名。
*
* @param className 类名
* @param processInnerClass 是否将内联类分隔符 <code>'$'</code> 转换成 <code>'.'</code>
*
* @return 直观的类名,或 <code>null</code>
*/
private static String getClassName(String className, boolean processInnerClass) {
if (StringUtil.isEmpty(className)) {
return className;
}
if (processInnerClass) {
className = className.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
}
int length = className.length();
int dimension = 0;
// 取得数组的维数,如果不是数组,维数为0
for (int i = 0; i < length; i++, dimension++) {
if (className.charAt(i) != '[') {
break;
}
}
// 如果不是数组,则直接返回
if (dimension == 0) {
return className;
}
// 确保类名合法
if (length <= dimension) {
return className; // 非法类名
}
// 处理数组
StringBuffer componentTypeName = new StringBuffer();
switch (className.charAt(dimension)) {
case 'Z':
componentTypeName.append("boolean");
break;
case 'B':
componentTypeName.append("byte");
break;
case 'C':
componentTypeName.append("char");
break;
case 'D':
componentTypeName.append("double");
break;
case 'F':
componentTypeName.append("float");
break;
case 'I':
componentTypeName.append("int");
break;
case 'J':
componentTypeName.append("long");
break;
case 'S':
componentTypeName.append("short");
break;
case 'L':
if ((className.charAt(length - 1) != ';') || (length <= (dimension + 2))) {
return className; // 非法类名
}
componentTypeName.append(className.substring(dimension + 1, length - 1));
break;
default:
return className; // 非法类名
}
for (int i = 0; i < dimension; i++) {
componentTypeName.append("[]");
}
return componentTypeName.toString();
}
/**
* 取得指定对象所属的类的短类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
* <pre>
* ClassUtil.getShortClassNameForObject(Boolean.TRUE) = "Boolean" ClassUtil.getShortClassNameForObject(new Boolean[10]) = "Boolean[]" ClassUtil.getShortClassNameForObject(new int[1][2]) = "int[][]"
* </pre>
* </p>
*
* @param object 要查看的对象
*
* @return 短类名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getShortClassNameForObject(Object object) {
if (object == null) {
return null;
}
return getShortClassName(object.getClass().getName());
}
/**
* 取得短类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
* <pre>
* ClassUtil.getShortClassName(Boolean.class) = "Boolean" ClassUtil.getShortClassName(Boolean[].class) = "Boolean[]" ClassUtil.getShortClassName(int[][].class) = "int[][]" ClassUtil.getShortClassName(Map.Entry.class) = "Map.Entry"
* </pre>
* </p>
*
* @param clazz 要查看的类
*
* @return 短类名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getShortClassName(Class clazz) {
if (clazz == null) {
return null;
}
return getShortClassName(clazz.getName());
}
/**
* 取得类名,不包括package名。
*
* <p>
* 此方法可以正确显示数组和内联类的名称。
* </p>
*
* <p>
* 例如:
* <pre>
* ClassUtil.getShortClassName(Boolean.class.getName()) = "Boolean" ClassUtil.getShortClassName(Boolean[].class.getName()) = "Boolean[]" ClassUtil.getShortClassName(int[][].class.getName()) = "int[][]" ClassUtil.getShortClassName(Map.Entry.class.getName()) = "Map.Entry"
* </pre>
* </p>
*
* @param className 要查看的类名
*
* @return 短类名,如果类名为空,则返回 <code>null</code>
*/
public static String getShortClassName(String className) {
if (StringUtil.isEmpty(className)) {
return className;
}
// 转换成直观的类名
className = getClassName(className, false);
char[] chars = className.toCharArray();
int lastDot = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
lastDot = i + 1;
} else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) {
chars[i] = PACKAGE_SEPARATOR_CHAR;
}
}
return new String(chars, lastDot, chars.length - lastDot);
}
/**
* 取得指定对象所属的类的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param object 要查看的对象
*
* @return package名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameForObject(Object object) {
if (object == null) {
return null;
}
return getPackageName(object.getClass().getName());
}
/**
* 取得指定类的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param clazz 要查看的类
*
* @return package名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageName(Class clazz) {
if (clazz == null) {
return null;
}
return getPackageName(clazz.getName());
}
/**
* 取得指定类名的package名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param className 要查看的类名
*
* @return package名,如果类名为空,则返回 <code>null</code>
*/
public static String getPackageName(String className) {
if (StringUtil.isEmpty(className)) {
return null;
}
// 转换成直观的类名
className = getClassName(className, false);
int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
if (i == -1) {
return "";
}
return className.substring(0, i);
}
/* ============================================================================ */
/* 取得类名和package名的resource名的方法。 */
/* */
/* 和类名、package名不同的是,resource名符合文件名命名规范,例如: */
/* java/lang/String.class */
/* com/alibaba/commons/lang */
/* etc. */
/* ============================================================================ */
/**
* 取得对象所属的类的资源名。
*
* <p>
* 例如:
* <pre>
* ClassUtil.getClassNameForObjectAsResource("This is a string") = "java/lang/String.class"
* </pre>
* </p>
*
* @param object 要显示类名的对象
*
* @return 指定对象所属类的资源名,如果对象为空,则返回<code>null</code>
*/
public static String getClassNameForObjectAsResource(Object object) {
if (object == null) {
return null;
}
return object.getClass().getName().replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR)
+ ".class";
}
/**
* 取得指定类的资源名。
*
* <p>
* 例如:
* <pre>
* ClassUtil.getClassNameAsResource(String.class) = "java/lang/String.class"
* </pre>
* </p>
*
* @param clazz 要显示类名的类
*
* @return 指定类的资源名,如果指定类为空,则返回<code>null</code>
*/
public static String getClassNameAsResource(Class clazz) {
if (clazz == null) {
return null;
}
return clazz.getName().replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR) + ".class";
}
/**
* 取得指定类的资源名。
*
* <p>
* 例如:
* <pre>
* ClassUtil.getClassNameAsResource("java.lang.String") = "java/lang/String.class"
* </pre>
* </p>
*
* @param className 要显示的类名
*
* @return 指定类名对应的资源名,如果指定类名为空,则返回<code>null</code>
*/
public static String getClassNameAsResource(String className) {
if (className == null) {
return null;
}
return className.replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR) + ".class";
}
/**
* 取得指定对象所属的类的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param object 要查看的对象
*
* @return package名,如果对象为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameForObjectAsResource(Object object) {
if (object == null) {
return null;
}
return getPackageNameForObject(object).replace(PACKAGE_SEPARATOR_CHAR,
RESOURCE_SEPARATOR_CHAR);
}
/**
* 取得指定类的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param clazz 要查看的类
*
* @return package名,如果类为 <code>null</code> ,则返回 <code>null</code>
*/
public static String getPackageNameAsResource(Class clazz) {
if (clazz == null) {
return null;
}
return getPackageName(clazz).replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR);
}
/**
* 取得指定类名的package名的资源名。
*
* <p>
* 对于数组,此方法返回的是数组元素类型的package名。
* </p>
*
* @param className 要查看的类名
*
* @return package名,如果类名为空,则返回 <code>null</code>
*/
public static String getPackageNameAsResource(String className) {
if (className == null) {
return null;
}
return getPackageName(className).replace(PACKAGE_SEPARATOR_CHAR, RESOURCE_SEPARATOR_CHAR);
}
/* ============================================================================ */
/* 取得类的信息,如父类, 接口, 数组的维数等。 */
/* ============================================================================ */
/**
* 取得指定维数的 <code>Array</code>类.
*
* @param componentType 数组的基类
* @param dimension 维数,如果小于 <code>0</code> 则看作 <code>0</code>
*
* @return 如果维数为0, 则返回基类本身, 否则返回数组类,如果数组的基类为 <code>null</code> ,则返回 <code>null</code>
*/
public static Class getArrayClass(Class componentType, int dimension) {
if (dimension <= 0) {
return componentType;
}
if (componentType == null) {
return null;
}
return Array.newInstance(componentType, new int[dimension]).getClass();
}
/**
* 取得数组元素的类型。
*
* @param type 要查找的类
*
* @return 如果是数组, 则返回数组元素的类型, 否则返回 <code>null</code>
*/
public static Class getArrayComponentType(Class type) {
if (type == null) {
return null;
}
return getTypeInfo(type).getArrayComponentType();
}
/**
* 取得数组的维数。
*
* @param clazz 要查找的类
*
* @return 数组的维数. 如果不是数组, 则返回 <code>0</code> ,如果数组为 <code>null</code> ,是返回 <code>-1</code>
*/
public static int getArrayDimension(Class clazz) {
if (clazz == null) {
return -1;
}
return getTypeInfo(clazz).getArrayDimension();
}
/**
* 取得指定类的所有父类。
*
* <p>
* 对于一个 <code>Class</code> 实例,如果它不是接口,也不是数组,此方法依次列出从该类的父类开始直到 <code>Object</code> 的所有类。
* </p>
*
* <p>
* 例如 <code>ClassUtil.getSuperclasses(java.util.ArrayList.class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.AbstractList</code>
* </li>
* <li>
* <code>java.util.AbstractCollection</code>
* </li>
* <li>
* <code>java.lang.Object</code>
* </li>
* </ol>
* </p>
*
* <p>
* 对于一个接口,此方法返回一个空列表。
* </p>
*
* <p>
* 例如<code>ClassUtil.getSuperclasses(java.util.List.class)</code>将返回一个空列表。
* </p>
*
* <p>
* 对于一个数组,此方法返回一个列表,列出所有component类型的父类的相同维数的数组类型。 例如:
* <code>ClassUtil.getSuperclasses(java.util.ArrayList[][].class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.AbstractList[][]</code>
* </li>
* <li>
* <code>java.util.AbstractCollection[][]</code>
* </li>
* <li>
* <code>java.lang.Object[][]</code>
* </li>
* <li>
* <code>java.lang.Object[]</code>
* </li>
* <li>
* <code>java.lang.Object</code>
* </li>
* </ol>
*
* 注意,原子类型及其数组,将被转换成相应的包装类来处理。 例如: <code>ClassUtil.getSuperclasses(int[][].class)</code>
* 返回以下列表:
*
* <ol>
* <li>
* <code>java.lang.Number[][]</code>
* </li>
* <li>
* <code>java.lang.Object[][]</code>
* </li>
* <li>
* <code>java.lang.Object[]</code>
* </li>
* <li>
* <code>java.lang.Object</code>
* </li>
* </ol>
* </p>
*
* @param clazz 要查找的类
*
* @return 所有父类的列表,如果指定类为 <code>null</code> ,则返回 <code>null</code>
*/
public static List getSuperclasses(Class clazz) {
if (clazz == null) {
return null;
}
return getTypeInfo(clazz).getSuperclasses();
}
/**
* 取得指定类的所有接口。
*
* <p>
* 对于一个 <code>Class</code> 实例,如果它不是接口,也不是数组,此方法依次列出从该类的父类开始直到 <code>Object</code> 的所有类。
* </p>
*
* <p>
* 例如 <code>ClassUtil.getInterfaces(java.util.ArrayList.class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.List</code>
* </li>
* <li>
* <code>java.util.Collection</code>
* </li>
* <li>
* <code>java.util.RandomAccess</code>
* </li>
* <li>
* <code>java.lang.Cloneable</code>
* </li>
* <li>
* <code>java.io.Serializable</code>
* </li>
* </ol>
* </p>
*
* <p>
* 对于一个数组,此方法返回一个列表,列出所有component类型的接口的相同维数的数组类型。 例如:
* <code>ClassUtil.getInterfaces(java.util.ArrayList[][].class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.util.List[][]</code>
* </li>
* <li>
* <code>java.util.Collection[][]</code>
* </li>
* <li>
* <code>java.util.RandomAccess[][]</code>
* </li>
* <li>
* <code>java.lang.Cloneable[][]</code>
* </li>
* <li>
* <code>java.io.Serializable[][]</code>
* </li>
* </ol>
* </p>
*
* <p>
* 注意,原子类型及其数组,将被转换成相应的包装类来处理。 例如: <code>ClassUtil.getInterfaces(int[][].class)</code> 返回以下列表:
*
* <ol>
* <li>
* <code>java.lang.Comparable[][]</code>
* </li>
* <li>
* <code>java.io.Serializable[][]</code>
* </li>
* </ol>
* </p>
*
* @param clazz 要查找的类
*
* @return 所有接口的列表,如果指定类为 <code>null</code> ,则返回 <code>null</code>
*/
public static List getInterfaces(Class clazz) {
if (clazz == null) {
return null;
}
return getTypeInfo(clazz).getInterfaces();
}
/**
* 判断指定类是否为内联类。
*
* @param clazz 要查找的类
*
* @return 如果是,则返回 <code>true</code>
*/
public static boolean isInnerClass(Class clazz) {
if (clazz == null) {
return false;
}
return StringUtil.contains(clazz.getName(), INNER_CLASS_SEPARATOR_CHAR);
}
/**
* 检查一组指定类型 <code>fromClasses</code> 的对象是否可以赋值给另一组类型 <code>classes</code>。
*
* <p>
* 此方法可以用来确定指定类型的参数 <code>object1, object2, ...</code> 是否可以用来调用确定参数类型为 <code>class1, class2,
* ...</code> 的方法。
* </p>
*
* <p>
* 对于 <code>fromClasses</code> 的每个元素 <code>fromClass</code> 和 <code>classes</code> 的每个元素
* <code>clazz</code>, 按照如下规则:
*
* <ol>
* <li>
* 如果目标类 <code>clazz</code> 为 <code>null</code> ,总是返回 <code>false</code>。
* </li>
* <li>
* 如果参数类型 <code>fromClass</code> 为 <code>null</code> ,并且目标类型 <code>clazz</code> 为非原子类型,则返回
* <code>true</code>。 因为 <code>null</code> 可以被赋给任何引用类型。
* </li>
* <li>
* 调用 <code>Class.isAssignableFrom</code> 方法来确定目标类 <code>clazz</code> 是否和参数类
* <code>fromClass</code> 相同或是其父类、接口,如果是,则返回 <code>true</code>。
* </li>
* <li>
* 如果目标类型 <code>clazz</code> 为原子类型,那么根据 <a href="http://java.sun.com/docs/books/jls/">The Java
* Language Specification</a> ,sections 5.1.1, 5.1.2, 5.1.4定义的Widening Primitive
* Conversion规则,参数类型 <code>fromClass</code> 可以是任何能扩展成该目标类型的原子类型及其包装类。 例如, <code>clazz</code> 为
* <code>long</code> ,那么参数类型可以是 <code>byte</code>、
* <code>short</code>、<code>int</code>、<code>long</code>、<code>char</code> 及其包装类
* <code>java.lang.Byte</code>、<code>java.lang.Short</code>、<code>java.lang.Integer</code>、
* <code>java.lang.Long</code> 和 <code>java.lang.Character</code> 。如果满足这个条件,则返回
* <code>true</code>。
* </li>
* <li>
* 不满足上述所有条件,则返回 <code>false</code>。
* </li>
* </ol>
* </p>
*
* @param classes 目标类型列表,如果是 <code>null</code> 总是返回 <code>false</code>
* @param fromClasses 参数类型列表, <code>null</code> 表示可赋值给任意非原子类型
*
* @return 如果可以被赋值,则返回 <code>true</code>
*/
public static boolean isAssignable(Class[] classes, Class[] fromClasses) {
if (!ArrayUtil.isSameLength(fromClasses, classes)) {
return false;
}
if (fromClasses == null) {
fromClasses = ArrayUtil.EMPTY_CLASS_ARRAY;
}
if (classes == null) {
classes = ArrayUtil.EMPTY_CLASS_ARRAY;
}
for (int i = 0; i < fromClasses.length; i++) {
if (isAssignable(classes[i], fromClasses[i]) == false) {
return false;
}
}
return true;
}
/**
* 检查指定类型 <code>fromClass</code> 的对象是否可以赋值给另一种类型 <code>clazz</code>。
*
* <p>
* 此方法可以用来确定指定类型的参数 <code>object1, object2, ...</code> 是否可以用来调用确定参数类型 <code>class1, class2,
* ...</code> 的方法。
* </p>
*
* <p>
* 按照如下规则:
*
* <ol>
* <li>
* 如果目标类 <code>clazz</code> 为 <code>null</code> ,总是返回 <code>false</code>。
* </li>
* <li>
* 如果参数类型 <code>fromClass</code> 为 <code>null</code> ,并且目标类型 <code>clazz</code> 为非原子类型,则返回
* <code>true</code>。 因为 <code>null</code> 可以被赋给任何引用类型。
* </li>
* <li>
* 调用 <code>Class.isAssignableFrom</code> 方法来确定目标类 <code>clazz</code> 是否和参数类
* <code>fromClass</code> 相同或是其父类、接口,如果是,则返回 <code>true</code>。
* </li>
* <li>
* 如果目标类型 <code>clazz</code> 为原子类型,那么根据 <a href="http://java.sun.com/docs/books/jls/">The Java
* Language Specification</a> ,sections 5.1.1, 5.1.2, 5.1.4定义的Widening Primitive
* Conversion规则,参数类型 <code>fromClass</code> 可以是任何能扩展成该目标类型的原子类型及其包装类。 例如, <code>clazz</code> 为
* <code>long</code> ,那么参数类型可以是 <code>byte</code>、
* <code>short</code>、<code>int</code>、<code>long</code>、<code>char</code> 及其包装类
* <code>java.lang.Byte</code>、<code>java.lang.Short</code>、<code>java.lang.Integer</code>、
* <code>java.lang.Long</code> 和 <code>java.lang.Character</code> 。如果满足这个条件,则返回
* <code>true</code>。
* </li>
* <li>
* 不满足上述所有条件,则返回 <code>false</code>。
* </li>
* </ol>
* </p>
*
* @param clazz 目标类型,如果是 <code>null</code> 总是返回 <code>false</code>
* @param fromClass 参数类型, <code>null</code> 表示可赋值给任意非原子类型
*
* @return 如果可以被赋值,则返回 <code>null</code>
*/
public static boolean isAssignable(Class clazz, Class fromClass) {
if (clazz == null) {
return false;
}
// 如果fromClass是null,只要clazz不是原子类型如int,就一定可以赋值
if (fromClass == null) {
return !clazz.isPrimitive();
}
// 如果类相同或有父子关系,当然可以赋值
if (clazz.isAssignableFrom(fromClass)) {
return true;
}
// 对于原子类型,根据JLS的规则进行扩展
// 目标class为原子类型时,fromClass可以为原子类型和原子类型的包装类型。
if (clazz.isPrimitive()) {
// boolean可以接受:boolean
if (Boolean.TYPE.equals(clazz)) {
return Boolean.class.equals(fromClass);
}
// byte可以接受:byte
if (Byte.TYPE.equals(clazz)) {
return Byte.class.equals(fromClass);
}
// char可以接受:char
if (Character.TYPE.equals(clazz)) {
return Character.class.equals(fromClass);
}
// short可以接受:short, byte
if (Short.TYPE.equals(clazz)) {
return Short.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass);
}
// int可以接受:int、byte、short、char
if (Integer.TYPE.equals(clazz)) {
return Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// long可以接受:long、int、byte、short、char
if (Long.TYPE.equals(clazz)) {
return Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// float可以接受:float, long, int, byte, short, char
if (Float.TYPE.equals(clazz)) {
return Float.class.equals(fromClass) || Long.TYPE.equals(fromClass)
|| Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
// double可以接受:double, float, long, int, byte, short, char
if (Double.TYPE.equals(clazz)) {
return Double.class.equals(fromClass) || Float.TYPE.equals(fromClass)
|| Float.class.equals(fromClass) || Long.TYPE.equals(fromClass)
|| Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
|| Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
|| Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
|| Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
|| Character.class.equals((fromClass));
}
}
return false;
}
/**
* 取得指定类的 <code>TypeInfo</code>。
*
* @param type 指定类或接口
*
* @return <code>TypeInfo</code> 对象.
*/
protected static TypeInfo getTypeInfo(Class type) {
if (type == null) {
throw new IllegalArgumentException("Parameter clazz should not be null");
}
TypeInfo classInfo;
synchronized (TYPE_MAP) {
classInfo = (TypeInfo) TYPE_MAP.get(type);
if (classInfo == null) {
classInfo = new TypeInfo(type);
TYPE_MAP.put(type, classInfo);
}
}
return classInfo;
}
/**
* 代表一个类的信息, 包括父类, 接口, 数组的维数等.
*/
protected static class TypeInfo {
private Class type;
private Class componentType;
private int dimension;
private List superclasses = new ArrayList(2);
private List interfaces = new ArrayList(2);
/**
* 创建 <code>TypeInfo</code>。
*
* @param type 创建指定类的 <code>TypeInfo</code>
*/
private TypeInfo(Class type) {
this.type = type;
// 如果是array, 设置componentType和dimension
Class componentType = null;
if (type.isArray()) {
componentType = type;
do {
componentType = componentType.getComponentType();
dimension++;
} while (componentType.isArray());
}
this.componentType = componentType;
// 取得所有superclass
if (dimension > 0) {
// 将primitive类型转换成对应的包装类
componentType = getNonPrimitiveType(componentType);
Class superComponentType = componentType.getSuperclass();
// 如果是primitive, interface, 则设置其基类为Object.
if ((superComponentType == null) && !Object.class.equals(componentType)) {
superComponentType = Object.class;
}
if (superComponentType != null) {
Class superclass = getArrayClass(superComponentType, dimension);
superclasses.add(superclass);
superclasses.addAll(getTypeInfo(superclass).superclasses);
} else {
for (int i = dimension - 1; i >= 0; i--) {
superclasses.add(getArrayClass(Object.class, i));
}
}
} else {
// 将primitive类型转换成对应的包装类
type = getNonPrimitiveType(type);
Class superclass = type.getSuperclass();
if (superclass != null) {
superclasses.add(superclass);
superclasses.addAll(getTypeInfo(superclass).superclasses);
}
}
// 取得所有interface
if (dimension == 0) {
Class[] typeInterfaces = type.getInterfaces();
List set = new ArrayList();
for (int i = 0; i < typeInterfaces.length; i++) {
Class typeInterface = typeInterfaces[i];
set.add(typeInterface);
set.addAll(getTypeInfo(typeInterface).interfaces);
}
for (Iterator i = superclasses.iterator(); i.hasNext();) {
Class typeInterface = (Class) i.next();
set.addAll(getTypeInfo(typeInterface).interfaces);
}
for (Iterator i = set.iterator(); i.hasNext();) {
Class interfaceClass = (Class) i.next();
if (!interfaces.contains(interfaceClass)) {
interfaces.add(interfaceClass);
}
}
} else {
for (Iterator i = getTypeInfo(componentType).interfaces.iterator(); i.hasNext();) {
Class componentInterface = (Class) i.next();
interfaces.add(getArrayClass(componentInterface, dimension));
}
}
}
/**
* 将所有的原子类型转换成对应的包装类,其它类型不变。
*
* @param type 要转换的类型
*
* @return 非原子类型
*/
private Class getNonPrimitiveType(Class type) {
if (type.isPrimitive()) {
if (Integer.TYPE.equals(type)) {
type = Integer.class;
} else if (Long.TYPE.equals(type)) {
type = Long.class;
} else if (Short.TYPE.equals(type)) {
type = Short.class;
} else if (Byte.TYPE.equals(type)) {
type = Byte.class;
} else if (Float.TYPE.equals(type)) {
type = Float.class;
} else if (Double.TYPE.equals(type)) {
type = Double.class;
} else if (Boolean.TYPE.equals(type)) {
type = Boolean.class;
} else if (Character.TYPE.equals(type)) {
type = Character.class;
}
}
return type;
}
/**
* 取得 <code>TypeInfo</code> 所代表的java类。
*
* @return <code>TypeInfo</code> 所代表的java类
*/
public Class getType() {
return type;
}
/**
* 取得数组元素的类型。
*
* @return 如果是数组, 则返回数组元素的类型, 否则返回 <code>null</code>
*/
public Class getArrayComponentType() {
return componentType;
}
/**
* 取得数组的维数。
*
* @return 数组的维数. 如果不是数组, 则返回 <code>0</code>
*/
public int getArrayDimension() {
return dimension;
}
/**
* 取得所有的父类。
*
* @return 所有的父类
*/
public List getSuperclasses() {
return Collections.unmodifiableList(superclasses);
}
/**
* 取得所有的接口。
*
* @return 所有的接口
*/
public List getInterfaces() {
return Collections.unmodifiableList(interfaces);
}
}
/* ============================================================================ */
/* 有关primitive类型的方法。 */
/* ============================================================================ */
/**
* 返回指定类型所对应的primitive类型。
*
* @param clazz 要检查的类型
*
* @return 如果指定类型为<code>null</code>或不是primitive类型的包装类,则返回<code>null</code>,否则返回相应的primitive类型。
*/
public static Class<?> getPrimitiveType(Class<?> clazz) {
if (clazz == null) {
return null;
}
if (clazz.isPrimitive()) {
return clazz;
}
if (clazz.equals(Long.class)) {
return long.class;
}
if (clazz.equals(Integer.class)) {
return int.class;
}
if (clazz.equals(Short.class)) {
return short.class;
}
if (clazz.equals(Byte.class)) {
return byte.class;
}
if (clazz.equals(Double.class)) {
return double.class;
}
if (clazz.equals(Float.class)) {
return float.class;
}
if (clazz.equals(Boolean.class)) {
return boolean.class;
}
if (clazz.equals(Character.class)) {
return char.class;
}
return null;
}
/**
* 返回指定类型所对应的非primitive类型。
*
* @param clazz 要检查的类型
*
* @return 如果指定类型为<code>null</code>,则返回<code>null</code>,如果是primitive类型,则返回相应的包装类,否则返回原始的类型。
*/
public static Class<?> getNonPrimitiveType(Class<?> clazz) {
if (clazz == null) {
return null;
}
if (!clazz.isPrimitive()) {
return clazz;
}
if (clazz.equals(long.class)) {
return Long.class;
}
if (clazz.equals(int.class)) {
return Integer.class;
}
if (clazz.equals(short.class)) {
return Short.class;
}
if (clazz.equals(byte.class)) {
return Byte.class;
}
if (clazz.equals(double.class)) {
return Double.class;
}
if (clazz.equals(float.class)) {
return Float.class;
}
if (clazz.equals(boolean.class)) {
return Boolean.class;
}
if (clazz.equals(char.class)) {
return Character.class;
}
return null;
}
}
/**
* Copyright (c) 2011-2014 All Rights Reserved.
*/
package com.jz.dm.gateway.common.util;
/**
* @author Admin
* @version $Id: Constants.java 2014年9月3日 下午9:03:44 $
*/
public class Constants {
/**
* 默认时间格式
**/
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT = "yyyyMMdd";
/**
* 密码的正则表达式
*/
public static final String PASSWORD_EXG = "^(?![^a-zA-Z]+$)(?!\\D+$).{8,30}$";
/**
* UTF-8字符集
**/
public static final String CHARSET_UTF8 = "UTF-8";
/**
* Date默认时区
**/
public static final String DATE_TIMEZONE = "GMT+8";
public static final String PRINCIPAL_NAME_ATTRIBUTE_OMSNAME = ".OMS_PRINCIPAL_NAME_ATTRIBUTE_NAME";
public static final String PRINCIPAL_NAME_ATTRIBUTE_MCHNAME = ".MCH_PRINCIPAL_NAME_ATTRIBUTE_NAME";
public static final String PRINCIPAL_NAME_ATTRIBUTE_PROXYNAME = ".PROXY_PRINCIPAL_NAME_ATTRIBUTE_NAME";
public static final String PRINCIPAL_NAME_ATTRIBUTE_SUPNAME = ".SUPPLIER_PRINCIPAL_NAME_ATTRIBUTE_NAME";
public static final String PERMISSIONS = "permissions";
/**
* 登录成功后,继续跳转URL
*/
public static final String GOTO_KEY = "to";
/**
* 记录密码控件的密钥key
*/
public final static String TOKEN = "token_%s";
// http请求头UA参数
public static final String UA = "user-agent";
//缓存名称
public static final String MEMBER_CACHE_NAME = "data:members";
public static final String MERCHANT_CACHE_NAME = "data:merchants";
public static final String SECRET_CACHE_NAME = "data:secret_keys";
public static final String ADDR_CACHE_NAME = "data:addrs";
public static final String PRODUCT_CACHE_NAME = "data:products";
public static final String API_WHITE_CACHE_NAME = "data:apiwhite";
//数据库序列名称
public static final String SEQ_ACCOUNT = "ids:accounts";
public static final String SEQ_ACCOUNT_WATER = "ids:accounts:water";
//public static final String SEQ_MEMBER = "ids:members";
public static final String SEQ_RECHARGE = "ids:recharges:loop:7";
public static final String SEQ_TRADE_ORDER = "ids:tradeorders:loop:7";
public static final String SEQ_PAYMENT = "ids:payment:loop:7";
public static final String SEQ_WITHDRAW = "ids:withdraws:loop:7";
public static final String SEQ_TRANSFER = "ids:transfer:loop:7";
/**
* key = 产线名:服务名:用途:数据类型:key
*/
public static final String VALID_CODE_KEY_PREFIX = "data:merchants:valid:string:";
public static final String VALID_CODE_KEY_COUNT_PREFIX = "data:merchants:valid:long:";
/** 短信签约缓存名称 **/
public static final String SMS_SIGN_KEY_PREFIX = "data:smssign:shortcode:string:";
public static final String SMS_SIGN_VALID_CODE_PREFIX = "data:smssign:validcode:string:";
public static final String SMS_SIGN_VALID_CODE_LIMIT_PREFIX = "data:smssign:validlimit:string:";
public static final String SMS_BROKER_VALID_CODE_PREFIX = "data:smsbroker:valid:string:";
/**
* 发送短信验证
*/
public static final String SEND_PAY_VALID_CODE = "sendPayValidCode";
public static final String SEND_EDIT_PASSWORD_VALID_CODE = "sendPasswordValidCode";
public static final String SEND_SIGN_VALID_CODE = "sendSignValidCode";
public static final String SMS_BROKER_VALID_CODE_TEMPLATE = "sendBrokerValidCode";
/**
* 代理商分润汇总key
*/
public static final String PROXY_ALL_FEE_SUMMARY = "PROXY_ALL_FEE_SUMMARY";
public static final String PROXYER_Fee = "PROXYER_Fee";
public static final String MERCHANT_Fee = "MERCHANT_Fee";
}
package com.jz.dm.gateway.common.util;
import com.jz.dm.gateway.common.StringUtil;
import java.util.HashMap;
import java.util.Map;
/**
* HDD HashMap
*
*/
public class HddHashMap extends HashMap<String, String> {
private static final long serialVersionUID = -3440305725602261736L;
public HddHashMap() {
super();
}
public HddHashMap(Map<? extends String, ? extends String> map) {
super(map);
}
/**
* if key or value is null, not put into hash map
*
* @see HashMap#put(Object, Object)
*/
@Override
public String put(String key, String value) {
if (StringUtil.isNotEmpty(key, value)) {
return super.put(key, value);
} else {
return null;
}
}
}
package com.jz.dm.gateway.common.util;
import com.jz.dm.gateway.common.util.Constants;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.CharacterIterator;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.util.*;
public class JSONWriter {
private StringBuffer buf = new StringBuffer();
private Stack<Object> calls = new Stack<Object>();
private boolean emitClassName = true;
private DateFormat format;
public JSONWriter(boolean emitClassName) {
this.emitClassName = emitClassName;
}
public JSONWriter() {
this(false);
}
public JSONWriter(DateFormat format) {
this(false);
this.format = format;
}
public String write(Object object) {
buf.setLength(0);
value(object);
return buf.toString();
}
public String write(long n) {
return String.valueOf(n);
}
public String write(double d) {
return String.valueOf(d);
}
public String write(char c) {
return "\"" + c + "\"";
}
public String write(boolean b) {
return String.valueOf(b);
}
private void value(Object object) {
if (object == null || cyclic(object)) {
add(null);
} else {
calls.push(object);
if (object instanceof Class<?>) string(object);
else if (object instanceof Boolean) bool(((Boolean) object).booleanValue());
else if (object instanceof Number) add(object);
else if (object instanceof String) string(object);
else if (object instanceof Character) string(object);
else if (object instanceof Map<?, ?>) map((Map<?, ?>)object);
else if (object.getClass().isArray()) array(object);
else if (object instanceof Iterator<?>) array((Iterator<?>)object);
else if (object instanceof Collection<?>) array(((Collection<?>)object).iterator());
else if (object instanceof Date) date((Date)object);
else bean(object);
calls.pop();
}
}
private boolean cyclic(Object object) {
Iterator<Object> it = calls.iterator();
while (it.hasNext()) {
Object called = it.next();
if (object == called) return true;
}
return false;
}
private void bean(Object object) {
add("{");
BeanInfo info;
boolean addedSomething = false;
try {
info = Introspector.getBeanInfo(object.getClass());
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (int i = 0; i < props.length; ++i) {
PropertyDescriptor prop = props[i];
String name = prop.getName();
Method accessor = prop.getReadMethod();
if ((emitClassName || !"class".equals(name)) && accessor != null) {
if (!accessor.isAccessible()) accessor.setAccessible(true);
Object value = accessor.invoke(object, (Object[])null);
if (value == null) continue;
if (addedSomething) add(',');
add(name, value);
addedSomething = true;
}
}
} catch (IllegalAccessException iae) {
} catch (InvocationTargetException ite) {
} catch (IntrospectionException ie) {
}
add("}");
}
private void add(String name, Object value) {
add('"');
add(name);
add("\":");
value(value);
}
private void map(Map<?, ?> map) {
add("{");
Iterator<?> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<?, ?> e = (Map.Entry<?, ?>) it.next();
value(e.getKey());
add(":");
value(e.getValue());
if (it.hasNext()) add(',');
}
add("}");
}
private void array(Iterator<?> it) {
add("[");
while (it.hasNext()) {
value(it.next());
if (it.hasNext()) add(",");
}
add("]");
}
private void array(Object object) {
add("[");
int length = Array.getLength(object);
for (int i = 0; i < length; ++i) {
value(Array.get(object, i));
if (i < length - 1) add(',');
}
add("]");
}
private void bool(boolean b) {
add(b ? "true" : "false");
}
private void date(Date date) {
if (this.format == null) {
this.format = new SimpleDateFormat(Constants.DATE_TIME_FORMAT);
this.format.setTimeZone(TimeZone.getTimeZone(Constants.DATE_TIMEZONE));
}
add("\"");
add(format.format(date));
add("\"");
}
private void string(Object obj) {
add('"');
CharacterIterator it = new StringCharacterIterator(obj.toString());
for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if (c == '"') add("\\\"");
else if (c == '\\') add("\\\\");
else if (c == '/') add("\\/");
else if (c == '\b') add("\\b");
else if (c == '\f') add("\\f");
else if (c == '\n') add("\\n");
else if (c == '\r') add("\\r");
else if (c == '\t') add("\\t");
else if (Character.isISOControl(c)) {
unicode(c);
} else {
add(c);
}
}
add('"');
}
private void add(Object obj) {
buf.append(obj);
}
private void add(char c) {
buf.append(c);
}
static char[] hex = "0123456789ABCDEF".toCharArray();
private void unicode(char c) {
add("\\u");
int n = c;
for (int i = 0; i < 4; ++i) {
int digit = (n & 0xf000) >> 12;
add(hex[digit]);
n <<= 4;
}
}
}
package com.jz.dm.gateway.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.NameFilter;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* Json工具类
*/
public class JsonUtil {
private static final ParserConfig PARSER_CONFIG = new ParserConfig();
static {
PARSER_CONFIG.propertyNamingStrategy = PropertyNamingStrategy.CamelCase;
}
private static final Map<PropertyNamingStrategy, NameFilter> NAME_FILTERS = new HashMap<PropertyNamingStrategy, NameFilter>();
static {
NAME_FILTERS.put(PropertyNamingStrategy.SnakeCase, new SnakeNameFilter());
NAME_FILTERS.put(PropertyNamingStrategy.CamelCase, new CamelNameFilter());
NAME_FILTERS.put(PropertyNamingStrategy.PascalCase, new PascalNameFilter());
NAME_FILTERS.put(PropertyNamingStrategy.KebabCase, new KebabNameFilter());
}
public static class SnakeNameFilter implements NameFilter {
/**
* @see NameFilter#process(Object, String, Object)
*/
@Override
public String process(Object object, String name, Object value) {
return PropertyNamingStrategy.SnakeCase.translate(name);
}
}
public static class CamelNameFilter implements NameFilter {
/**
* @see NameFilter#process(Object, String, Object)
*/
@Override
public String process(Object object, String name, Object value) {
return PropertyNamingStrategy.CamelCase.translate(name);
}
}
public static class PascalNameFilter implements NameFilter {
/**
* @see NameFilter#process(Object, String, Object)
*/
@Override
public String process(Object object, String name, Object value) {
return PropertyNamingStrategy.PascalCase.translate(name);
}
}
public static class KebabNameFilter implements NameFilter {
/**
* @see NameFilter#process(Object, String, Object)
*/
@Override
public String process(Object object, String name, Object value) {
return PropertyNamingStrategy.KebabCase.translate(name);
}
}
/**
* object serialize to string
*
* @param object
* @param strategy
* @return
*/
public static String toJSONString(Object object, PropertyNamingStrategy strategy) {
if (object == null) {
return null;
}
if (strategy == null) {
return JSON.toJSONString(object);
}
NameFilter nameFilter = NAME_FILTERS.get(strategy);
if (nameFilter == null) {
return JSON.toJSONString(object);
} else {
return JSON.toJSONString(object, nameFilter);
}
}
/**
* String转换为JSONObject对象
*
* @param data
* @return
*/
public static JSONObject stringToJsonObject(String data) {
if (StringUtils.isNotEmpty(data)) {
return JSONObject.parseObject(data);
}
return null;
}
}
package com.jz.dm.gateway.common.util;
import org.slf4j.Logger;
/**
* 日志打印工具
*
*/
public class LogUtil {
/** 摘要日志的内容分隔符 */
public static final String SEP = ",";
/** 修饰符 */
private static final char RIGHT_TAG = ']';
/** 修饰符 */
private static final char LEFT_TAG = '[';
/**
* 日志信息
*
*/
public interface LogInfo {
/**
* 获取日志信息
*
* @return 日志信息
*/
String getLogInfo();
}
/**
* 打印info日志。
*
* @param logger 日志对象
* @param objs 任意个要输出到日志的参数
*/
public static void info(Logger logger, Object... objs) {
if (logger.isInfoEnabled()) {
logger.info(getLogString(objs));
}
}
/**
* 打印info级别日志
*
* @param logger 日志对象
* @param logInfo 日志信息
*/
public static void info(Logger logger, LogInfo logInfo) {
if (logger.isInfoEnabled()) {
logger.info(logInfo.getLogInfo());
}
}
/**
* 打印info级别日志
*
* @param logger 日志对象
* @param e 异常信息
* @param objs 任意个要输出到日志的参数
*/
public static void info(Logger logger, Throwable e, Object... objs) {
if (logger.isInfoEnabled()) {
logger.info(getLogString(objs), e);
}
}
/**
* 打印warn级别日志
*
* @param logger 日志对象
* @param objs 任意个要输出到日志的参数
*/
public static void warn(Logger logger, Object... objs) {
logger.warn(getLogString(objs));
}
/**
* 打印warn级别日志
*
* @param logger 日志对象
* @param e 异常信息
* @param objs 任意个要输出到日志的参数
*/
public static void warn(Logger logger, Throwable e, Object... objs) {
logger.warn(getLogString(objs), e);
}
/**
* 打印error级别日志
*
* @param logger 日志对象
* @param e 异常信息
* @param objs 任意个要输出到日志的参数
*/
public static void error(Logger logger, Throwable e, Object... objs) {
logger.error(getLogString(objs), e);
}
/**
* 打印error级别日志
*
* @param logger 日志对象
* @param objs 任意个要输出到日志的参数
*/
public static void error(Logger logger, Object... objs) {
logger.error(getLogString(objs));
}
/**
* 打印debug日志。
*
* @param logger 日志对象
* @param objs 任意个要输出到日志的参数
*/
public static void debug(Logger logger, Object... objs) {
if (logger.isDebugEnabled()) {
logger.debug(getLogString(objs));
}
}
/**
* 打印debug日志。
*
* @param logger 日志对象
* @param e 异常信息
* @param objs 任意个要输出到日志的参数
*/
public static void debug(Logger logger, Throwable e, Object... objs) {
if (logger.isDebugEnabled()) {
logger.debug(getLogString(objs), e);
}
}
/**
* 生成输出到日志的字符串
*
* @param objs 任意个要输出到日志的参数
* @return 日志字符串
*/
public static String getLogString(Object... objs) {
StringBuilder log = new StringBuilder();
log.append(LEFT_TAG).append(getThreadId()).append(RIGHT_TAG);
for (Object o : objs) {
log.append(o).append(SEP);
}
return log.toString();
}
/**
* 获取线程id。
*
* @return 线程id
*/
public static String getThreadId() {
return String.valueOf(Thread.currentThread().getId());
}
}
package com.jz.dm.gateway.common.util;
import java.util.HashMap;
import java.util.Map;
/**
* 结果码
*
*/
public enum NotifyResultCode implements ResultCode {
/** 处理成功 */
SUCCESS("SUCCESS", "处理成功"),
/** 处理失败 */
FAILED("FAILED", "处理失败"),
/** 未知异常 */
UNKNOWN_EXCEPTION("UNKNOWN_EXCEPTION", "未知异常"),
/** 数据库异常 */
DATABASE_EXCEPTION("DATABASE_EXCEPTION", "数据库异常"),
/** IO异常 */
IO_EXCEPTION("IO_EXCEPTION", "IO异常"),
/** 参数不能为空 */
PARAM_CAN_NOT_NULL("PARAM_CAN_NOT_NULL", "参数不能为空"),
/** 参数不能为空 */
PARAM_CAN_NOT_EMPTY("PARAM_CAN_NOT_EMPTY", "参数不能为空"),
/** 重复发送 */
RETRANSMISSION("RETRANSMISSION", "重复发送"),
/** 无效参数 */
ILLEGAL_ARGUMENT("ILLEGAL_ARGUMENT", "无效参数"),
/** 时间格式不合法*/
ILLEGAL_DATE_FORMAT("ILLEGAL_DATE_FORMAT", "时间格式不合法"),
;
/**
* 初始化保存到map里方便根据code获取
*/
private static Map<String, NotifyResultCode> RESULT_CODES = new HashMap<String, NotifyResultCode>();
static {
for (NotifyResultCode resultCode : NotifyResultCode.values()) {
RESULT_CODES.put(resultCode.code, resultCode);
}
}
/** 结果码 */
private String code;
/** 结果码信息 */
private String msg;
/** 结果分类 */
private NotifyResultCode classification;
/**
* 构造函数
*
* @param code 结果码
* @param msg 结果码信息
*/
private NotifyResultCode(String code, String message) {
this(code, message, null);
}
/**
* 构造函数
*
* @param code 结果码
* @param msg 结果码信息
* @param classification 结果分组
*/
private NotifyResultCode(String code, String msg, NotifyResultCode classification) {
this.code = code;
this.msg = msg;
this.classification = classification;
}
/**
* 通过枚举<code>code</code>获得枚举
*
* @param code 结果码
* @return 枚举
*/
public static NotifyResultCode getResultCode(String code) {
return RESULT_CODES.get(code);
}
/**
* Getter method for property <tt>code</tt>.
*
* @return property value of code
*/
@Override
public String getCode() {
return code;
}
/**
* Setter method for property <tt>code</tt>.
*
* @param code value to be assigned to property code
*/
public void setCode(String code) {
this.code = code;
}
/**
* Getter method for property <tt>msg</tt>.
*
* @return property value of msg
*/
@Override
public String getMsg() {
return msg;
}
/**
* Setter method for property <tt>msg</tt>.
*
* @param msg value to be assigned to property msg
*/
public void setMsg(String msg) {
this.msg = msg;
}
/**
* Getter method for property <tt>classification</tt>.
*
* @return property value of classification
*/
public NotifyResultCode getClassification() {
return classification;
}
/**
* Setter method for property <tt>classification</tt>.
*
* @param classification value to be assigned to property classification
*/
public void setClassification(NotifyResultCode classification) {
this.classification = classification;
}
}
package com.jz.dm.gateway.common.util;
import com.jz.dm.gateway.common.StringUtil;
import java.io.Serializable;
import java.lang.reflect.Method;
/**
* <code>Object</code>处理工具类。
*
*/
public class ObjectUtil {
/**
* 用于表示<code>null</code>的常量。
*
* <p>
* 例如,<code>HashMap.get(Object)</code>方法返回<code>null</code>有两种可能:
* 值不存在或值为<code>null</code>。而这个singleton可用来区别这两种情形。
* </p>
*
* <p>
* 另一个例子是,<code>Hashtable</code>的值不能为<code>null</code>。
* </p>
*/
public static final Object NULL = new Serializable() {
private static final long serialVersionUID = 7092611880189329093L;
private Object readResolve() {
return NULL;
}
};
/* ============================================================================ */
/* 默认值函数。 */
/* */
/* 当对象为null时,将对象转换成指定的默认对象。 */
/* ============================================================================ */
/**
* 如果对象为<code>null</code>,则返回指定默认对象,否则返回对象本身。
* <pre>
* ObjectUtil.defaultIfNull(null, null) = null
* ObjectUtil.defaultIfNull(null, "") = ""
* ObjectUtil.defaultIfNull(null, "zz") = "zz"
* ObjectUtil.defaultIfNull("abc", *) = "abc"
* ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
* </pre>
*
* @param object 要测试的对象
* @param defaultValue 默认值
*
* @return 对象本身或默认对象
*/
public static Object defaultIfNull(Object object, Object defaultValue) {
return (object != null) ? object : defaultValue;
}
/* ============================================================================ */
/* 比较函数。 */
/* */
/* 以下方法用来比较两个对象是否相同。 */
/* ============================================================================ */
/**
* 比较两个对象是否完全相等。
*
* <p>
* 此方法可以正确地比较多维数组。
* <pre>
* ObjectUtil.equals(null, null) = true
* ObjectUtil.equals(null, "") = false
* ObjectUtil.equals("", null) = false
* ObjectUtil.equals("", "") = true
* ObjectUtil.equals(Boolean.TRUE, null) = false
* ObjectUtil.equals(Boolean.TRUE, "true") = false
* ObjectUtil.equals(Boolean.TRUE, Boolean.TRUE) = true
* ObjectUtil.equals(Boolean.TRUE, Boolean.FALSE) = false
* </pre>
* </p>
*
* @param object1 对象1
* @param object2 对象2
*
* @return 如果相等, 则返回<code>true</code>
*/
public static boolean equals(Object object1, Object object2) {
return ArrayUtil.equals(object1, object2);
}
/* ============================================================================ */
/* Hashcode函数。 */
/* */
/* 以下方法用来取得对象的hash code。 */
/* ============================================================================ */
/**
* 取得对象的hash值, 如果对象为<code>null</code>, 则返回<code>0</code>。
*
* <p>
* 此方法可以正确地处理多维数组。
* </p>
*
* @param object 对象
*
* @return hash值
*/
public static int hashCode(Object object) {
return ArrayUtil.hashCode(object);
}
/**
* 取得对象的原始的hash值, 如果对象为<code>null</code>, 则返回<code>0</code>。
*
* <p>
* 该方法使用<code>System.identityHashCode</code>来取得hash值,该值不受对象本身的<code>hashCode</code>方法的影响。
* </p>
*
* @param object 对象
*
* @return hash值
*/
public static int identityHashCode(Object object) {
return (object == null) ? 0 : System.identityHashCode(object);
}
/* ============================================================================ */
/* 取得对象的identity。 */
/* ============================================================================ */
/**
* 取得对象自身的identity,如同对象没有覆盖<code>toString()</code>方法时,<code>Object.toString()</code>的原始输出。
* <pre>
* ObjectUtil.identityToString(null) = null
* ObjectUtil.identityToString("") = "java.lang.String@1e23"
* ObjectUtil.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
* ObjectUtil.identityToString(new int[0]) = "int[]@7fa"
* ObjectUtil.identityToString(new Object[0]) = "java.lang.Object[]@7fa"
* </pre>
*
* @param object 对象
*
* @return 对象的identity,如果对象是<code>null</code>,则返回<code>null</code>
*/
public static String identityToString(Object object) {
if (object == null) {
return null;
}
return appendIdentityToString(null, object).toString();
}
/**
* 取得对象自身的identity,如同对象没有覆盖<code>toString()</code>方法时,<code>Object.toString()</code>的原始输出。
* <pre>
* ObjectUtil.identityToString(null, "NULL") = "NULL"
* ObjectUtil.identityToString("", "NULL") = "java.lang.String@1e23"
* ObjectUtil.identityToString(Boolean.TRUE, "NULL") = "java.lang.Boolean@7fa"
* ObjectUtil.identityToString(new int[0], "NULL") = "int[]@7fa"
* ObjectUtil.identityToString(new Object[0], "NULL") = "java.lang.Object[]@7fa"
* </pre>
*
* @param object 对象
* @param nullStr 如果对象为<code>null</code>,则返回该字符串
*
* @return 对象的identity,如果对象是<code>null</code>,则返回指定字符串
*/
public static String identityToString(Object object, String nullStr) {
if (object == null) {
return nullStr;
}
return appendIdentityToString(null, object).toString();
}
/**
* 将对象自身的identity——如同对象没有覆盖<code>toString()</code>方法时,<code>Object.toString()</code>的原始输出——追加到<code>StringBuffer</code>中。
* <pre>
* ObjectUtil.appendIdentityToString(*, null) = null
* ObjectUtil.appendIdentityToString(null, "") = "java.lang.String@1e23"
* ObjectUtil.appendIdentityToString(null, Boolean.TRUE) = "java.lang.Boolean@7fa"
* ObjectUtil.appendIdentityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
* ObjectUtil.appendIdentityToString(buf, new int[0]) = buf.append("int[]@7fa")
* ObjectUtil.appendIdentityToString(buf, new Object[0]) = buf.append("java.lang.Object[]@7fa")
* </pre>
*
* @param buffer <code>StringBuffer</code>对象,如果是<code>null</code>,则创建新的
* @param object 对象
*
* @return <code>StringBuffer</code>对象,如果对象为<code>null</code>,则返回<code>null</code>
*/
public static StringBuffer appendIdentityToString(StringBuffer buffer, Object object) {
if (object == null) {
return null;
}
if (buffer == null) {
buffer = new StringBuffer();
}
buffer.append(ClassUtil.getClassNameForObject(object));
return buffer.append('@').append(Integer.toHexString(identityHashCode(object)));
}
/* ============================================================================ */
/* Clone函数。 */
/* */
/* 以下方法调用Object.clone方法,默认是“浅复制”(shallow copy)。 */
/* ============================================================================ */
/**
* 复制一个对象。如果对象为<code>null</code>,则返回<code>null</code>。
*
* <p>
* 此方法调用<code>Object.clone</code>方法,默认只进行“浅复制”。 对于数组,调用<code>ArrayUtil.clone</code>方法更高效。
* </p>
*
* @param array 要复制的数组
*
* @return 数组的复本,如果原始数组为<code>null</code>,则返回<code>null</code>
*/
public static Object clone(Object array) {
if (array == null) {
return null;
}
// 对数组特殊处理
if (array instanceof Object[]) {
return ArrayUtil.clone((Object[]) array);
}
if (array instanceof long[]) {
return ArrayUtil.clone((long[]) array);
}
if (array instanceof int[]) {
return ArrayUtil.clone((int[]) array);
}
if (array instanceof short[]) {
return ArrayUtil.clone((short[]) array);
}
if (array instanceof byte[]) {
return ArrayUtil.clone((byte[]) array);
}
if (array instanceof double[]) {
return ArrayUtil.clone((double[]) array);
}
if (array instanceof float[]) {
return ArrayUtil.clone((float[]) array);
}
if (array instanceof boolean[]) {
return ArrayUtil.clone((boolean[]) array);
}
if (array instanceof char[]) {
return ArrayUtil.clone((char[]) array);
}
// Not cloneable
if (!(array instanceof Cloneable)) {
throw new RuntimeException(
"Object of class " + array.getClass().getName() + " is not Cloneable");
}
// 用reflection调用clone方法
Class<?> clazz = array.getClass();
try {
Method cloneMethod = clazz.getMethod("clone", ArrayUtil.EMPTY_CLASS_ARRAY);
return cloneMethod.invoke(array, ArrayUtil.EMPTY_OBJECT_ARRAY);
} catch (Exception e) {
throw new RuntimeException("Object clone exception.", e);
}
}
/* ============================================================================ */
/* 比较对象的类型。 */
/* ============================================================================ */
/**
* 检查两个对象是否属于相同类型。<code>null</code>将被看作任意类型。
*
* @param object1 对象1
* @param object2 对象2
*
* @return 如果两个对象有相同的类型,则返回<code>true</code>
*/
public static boolean isSameType(Object object1, Object object2) {
if ((object1 == null) || (object2 == null)) {
return true;
}
return object1.getClass().equals(object2.getClass());
}
/* ============================================================================ */
/* toString方法。 */
/* ============================================================================ */
/**
* 取得对象的<code>toString()</code>的值,如果对象为<code>null</code>,则返回空字符串<code>""</code>。
* <pre>
* ObjectUtil.toString(null) = ""
* ObjectUtil.toString("") = ""
* ObjectUtil.toString("bat") = "bat"
* ObjectUtil.toString(Boolean.TRUE) = "true"
* ObjectUtil.toString([1, 2, 3]) = "[1, 2, 3]"
* </pre>
*
* @param object 对象
*
* @return 对象的<code>toString()</code>的返回值,或空字符串<code>""</code>
*/
public static String toString(Object object) {
return (object == null) ? StringUtil.EMPTY_STRING
: (object.getClass().isArray() ? ArrayUtil.toString(object) : object.toString());
}
/**
* 取得对象的<code>toString()</code>的值,如果对象为<code>null</code>,则返回指定字符串。
* <pre>
* ObjectUtil.toString(null, null) = null
* ObjectUtil.toString(null, "null") = "null"
* ObjectUtil.toString("", "null") = ""
* ObjectUtil.toString("bat", "null") = "bat"
* ObjectUtil.toString(Boolean.TRUE, "null") = "true"
* ObjectUtil.toString([1, 2, 3], "null") = "[1, 2, 3]"
* </pre>
*
* @param object 对象
* @param nullStr 如果对象为<code>null</code>,则返回该字符串
*
* @return 对象的<code>toString()</code>的返回值,或指定字符串
*/
public static String toString(Object object, String nullStr) {
return (object == null) ? nullStr
: (object.getClass().isArray() ? ArrayUtil.toString(object) : object.toString());
}
}
package com.jz.dm.gateway.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jz.dm.gateway.common.exception.OpenApiException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* openapi请求
*
*/
public class OpenApiRequest {
private String appId;
private String openApiParams;
private JSONObject parameters;
private Object parameterObject;
private Map<String, Object> extAttributes = new HashMap<String, Object>();
public OpenApiRequest(String openApiParams) {
setOpenApiParams(openApiParams);
}
private void setOpenApiParams(String openApiParams) {
this.openApiParams = openApiParams;
try {
parameters = JSON.parseObject(openApiParams, JSONObject.class);
} catch (Exception ex) {
throw new OpenApiException(OpenApiResultCode.ILLEGAL_ARGUMENT,
"parse openapi params error, openApiParams=" + openApiParams, ex);
}
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
@SuppressWarnings("unchecked")
public <T> T getObject(Class<?> clazz) {
if (parameterObject != null) {
return (T) parameterObject;
}
try {
this.parameterObject = JSON.parseObject(openApiParams, clazz);
} catch (Exception ex) {
throw new OpenApiException(OpenApiResultCode.ILLEGAL_ARGUMENT, ex);
}
return (T) parameterObject;
}
public String getOpenApiParams() {
return this.openApiParams;
}
@SuppressWarnings("unchecked")
@Deprecated
public <T> T getParameter(String key) {
return (T) parameters.get(key);
}
public <T> T getObject(String key, Class<T> clazz) {
return parameters.getObject(key, clazz);
}
public byte[] getBytes(String key) {
return parameters.getBytes(key);
}
public Boolean getBoolean(String key) {
return parameters.getBoolean(key);
}
public boolean getBooleanValue(String key) {
return parameters.getBooleanValue(key);
}
public Byte getByte(String key) {
return parameters.getByte(key);
}
public byte getByteValue(String key) {
return parameters.getByteValue(key);
}
public Short getShort(String key) {
return parameters.getShortValue(key);
}
public short getShortValue(String key) {
return parameters.getShortValue(key);
}
public Integer getInteger(String key) {
return parameters.getInteger(key);
}
public int getIntValue(String key) {
return parameters.getIntValue(key);
}
public Long getLong(String key) {
return parameters.getLong(key);
}
public long getLongValue(String key) {
return parameters.getLongValue(key);
}
public Float getFloat(String key) {
return parameters.getFloat(key);
}
public float getFloatValue(String key) {
return parameters.getFloatValue(key);
}
public Double getDouble(String key) {
return parameters.getDouble(key);
}
public double getDoubleValue(String key) {
return parameters.getDoubleValue(key);
}
public BigDecimal getBigDecimal(String key) {
return parameters.getBigDecimal(key);
}
public BigInteger getBigInteger(String key) {
return parameters.getBigInteger(key);
}
public String getString(String key) {
return parameters.getString(key);
}
public Date getDate(String key) {
return parameters.getDate(key);
}
/**
* Get Extend Attribute
*
* @param attributeName
* @return
*/
@SuppressWarnings("unchecked")
public <T> T getExtAttribute(String attributeName) {
return (T) extAttributes.get(attributeName);
}
/**
* Set Extend Attribute
*
* @param attributeName
* @param attributeValue
*/
public void setExtAttribute(String attributeName, String attributeValue) {
this.extAttributes.put(attributeName, attributeValue);
}
/**
* Getter method for property <tt>extAttributes</tt>.
*
* @return property value of extAttributes
*/
public Map<String, Object> getExtAttributes() {
return extAttributes;
}
/**
* Setter method for property <tt>extAttributes</tt>.
*
* @param extAttributes value to be assigned to property extAttributes
*/
public void setExtAttributes(Map<String, Object> extAttributes) {
this.extAttributes = extAttributes;
}
}
package com.jz.dm.gateway.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
/**
* openapi响应
*
*/
public class OpenApiResponse {
/**
* 结果码
*/
private static final String ATTRIBUTE_NAME_CODE = "code";
/**
* 结果消息
*/
private static final String ATTRIBUTE_NAME_MSG = "msg";
/**
* 属性
*/
private final Map<String, Object> attributes = new HashMap<String, Object>();
/**
* 获取结果码
*
* @return
*/
public String getCode() {
return (String) attributes.get(ATTRIBUTE_NAME_CODE);
}
/**
* 设置结果码
*
* @param code
*/
public void setCode(String code) {
attributes.put(ATTRIBUTE_NAME_CODE, code);
}
/**
* 获取结果信息
*
* @return
*/
public String getMsg() {
return (String) attributes.get(ATTRIBUTE_NAME_MSG);
}
/**
* 设置结果信息
*
* @param msg
*/
public void setMsg(String msg) {
attributes.put(ATTRIBUTE_NAME_MSG, msg);
}
/**
* 获取属性
*
* @param attributeName
* @return
*/
@SuppressWarnings("unchecked")
public <T> T getAttribute(String attributeName) {
return (T) attributes.get(attributeName);
}
/**
* 设置属性
*
* @param attributeName
* @param attributeValue
*/
public void setAttribute(String attributeName, Object attributeValue) {
attributes.put(attributeName, attributeValue);
}
/**
* 设置对象属性
*
* @param object
*/
public void setAttribute(Object object) {
Object jsonObject = JSON.toJSON(object);
if (!(jsonObject instanceof JSONObject)) {
throw new IllegalArgumentException("object must be a javabean.");
}
attributes.putAll((JSONObject) jsonObject);
}
/**
* 获取所有属性
*
* @return
*/
public Map<String, Object> getAttributes() {
return attributes;
}
}
package com.jz.dm.gateway.common.util;
import java.util.HashMap;
import java.util.Map;
/**
* 结果码
*
*/
public enum OpenApiResultCode implements ResultCode {
/** 处理成功 */
SUCCESS("SUCCESS", "处理成功"),
/** 未知异常 */
UNKNOWN_EXCEPTION("UNKNOWN_EXCEPTION", "未知异常"),
/** 无效接口 */
ILLEGAL_INTERFACE("ILLEGAL_INTERFACE", "无效接口"),
/** 无效参数 */
ILLEGAL_ARGUMENT("ILLEGAL_ARGUMENT", "无效参数"),
/** 名类型不支持 */
SIGN_TYPE_NOT_SUPPORT("SIGN_TYPE_NOT_SUPPORT", "签名类型不支持"),
/** 数据签名错误 */
DATA_SIGN_ERROR("DATA_SIGN_ERROR", "数据签名错误"),
/** 公钥格式错误 */
PUBLIC_KEY_FORMAT_ERROR("PUBLIC_KEY_FORMAT_ERROR", "公钥格式错误"),
/** 私钥格式错误 */
PRIVATE_KEY_FORMAT_ERROR("PRIVATE_KEY_FORMAT_ERROR", "私钥格式错误"),
/** 响应数据格式错误 */
RESPONSE_DATA_FORMAT_ERROR("RESPONSE_DATA_FORMAT_ERROR", "响应数据格式错误"),
/** 签名校验错误 */
SIGN_VERIFY_ERROR("SIGN_VERIFY_ERROR", "签名校验错误"),
/** 不支持该信息摘要算法 */
NO_SUCH_MD_ALGORITHM("NO_SUCH_MD_ALGORITHM", "不支持该信息摘要算法"),
/** 信息摘要错误 */
MESSAGE_DIGEST_ERROR("MESSAGE_DIGEST_ERROR", "信息摘要错误"),
/** 数据加密错误 */
DATA_ENCRYPTION_ERROR("DATA_ENCRYPTION_ERROR", "数据加密错误"),;
/**
* 初始化保存到map里方便根据code获取
*/
private static Map<String, OpenApiResultCode> RESULT_CODES = new HashMap<String, OpenApiResultCode>();
static {
for (OpenApiResultCode openApiCode : OpenApiResultCode.values()) {
RESULT_CODES.put(openApiCode.code, openApiCode);
}
}
/** 结果码 */
private String code;
/** 结果码信息 */
private String msg;
/**
* 构造函数
*
* @param code 结果码
* @param msg 结果码信息
*/
private OpenApiResultCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* 通过枚举<code>code</code>获得枚举
*
* @param code 结果码
* @return 枚举
*/
public static OpenApiResultCode getOpenApiResultCode(String code) {
return RESULT_CODES.get(code);
}
/**
* Getter method for property <tt>code</tt>.
*
* @return property value of code
*/
@Override
public String getCode() {
return code;
}
/**
* Setter method for property <tt>code</tt>.
*
* @param code value to be assigned to property code
*/
public void setCode(String code) {
this.code = code;
}
/**
* Getter method for property <tt>msg</tt>.
*
* @return property value of msg
*/
@Override
public String getMsg() {
return msg;
}
/**
* Setter method for property <tt>msg</tt>.
*
* @param msg value to be assigned to property msg
*/
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.jz.dm.gateway.common.util;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
*
* <p>RSA签名,加解密处理核心文件,注意:密钥长度1024</p>
* @author leelun
* @version $Id: RSA.java, v 0.1 2013-11-15 下午2:33:53 lilun Exp $
*/
public class RSA {
/**
* 签名算法
*/
public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* 加密算法RSA
*/
public static final String KEY_ALGORITHM = "RSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 获取公钥的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/**
* 获取私钥的key
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
private static Logger logger = LoggerFactory.getLogger(RSA.class);
/**
* <p>
* 生成密钥对(公钥和私钥)
* </p>
*
* @return
* @throws Exception
*/
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/**
* 签名字符串
*
* @param text
* 需要签名的字符串
* @param privateKey 私钥(BASE64编码)
*
* @param input_charset
* 编码格式
* @return 签名结果(BASE64编码)
*/
public static String sign(String text, String privateKey, String charset) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(getContentBytes(text, charset));
byte[] result = signature.sign();
return Base64.encodeBase64String(result);
}
/**
* 签名字符串
*
* @param text
* 需要签名的字符串
* @param sign
* 客户签名结果
* @param publicKey
* 公钥(BASE64编码)
* @param input_charset
* 编码格式
* @return 验签结果
*/
public static boolean verify(String text, String sign, String publicKey, String charset)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(getContentBytes(text, charset));
return signature.verify(Base64.decodeBase64(sign));
}
/**
* <P>
* 私钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 公钥加密
* </p>
*
* @param data 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* <p>
* 私钥加密
* </p>
*
* @param data 源数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
/**
* <p>
* 获取私钥
* </p>
*
* @param keyMap 密钥对
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
/**
* <p>
* 获取公钥
* </p>
*
* @param keyMap 密钥对
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
}
\ No newline at end of file
package com.jz.dm.gateway.common.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSAUtils {
public static final String CHARSET = "UTF-8";
public static final String RSA_ALGORITHM = "RSA";
public static Map<String, String> createKeys(int keySize){
//为RSA算法创建一个KeyPairGenerator对象
KeyPairGenerator kpg;
try{
kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
}catch(NoSuchAlgorithmException e){
throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
}
//初始化KeyPairGenerator对象,密钥长度
kpg.initialize(keySize);
//生成密匙对
KeyPair keyPair = kpg.generateKeyPair();
//得到公钥
Key publicKey = keyPair.getPublic();
String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
//得到私钥
Key privateKey = keyPair.getPrivate();
System.out.println("私钥格式:"+privateKey.getFormat());
String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
Map<String, String> keyPairMap = new HashMap<String, String>();
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
return keyPairMap;
}
/**
* 得到公钥
* @param publicKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
/**
* 得到私钥
* @param privateKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过PKCS#8编码的Key指令获得私钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
return key;
}
/**
* 公钥加密
* @param data
* @param publicKey
* @return
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 私钥解密
* @param data
* @param privateKey
* @return
*/
public static String privateDecrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
}catch(Exception e){
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 私钥加密
* @param data
* @param privateKey
* @return
*/
public static String privateEncrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 公钥解密
* @param data
* @param publicKey
* @return
*/
public static String publicDecrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
}catch(Exception e){
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
}
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
int maxBlock = 0;
if(opmode == Cipher.DECRYPT_MODE){
maxBlock = keySize / 8;
}else{
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try{
while(datas.length > offSet){
if(datas.length-offSet > maxBlock){
buff = cipher.doFinal(datas, offSet, maxBlock);
}else{
buff = cipher.doFinal(datas, offSet, datas.length-offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
}catch(Exception e){
throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
}
package com.jz.dm.gateway.common.util;
/**
* 结果码
*
*/
public interface ResultCode {
/**
* 编码
*
* @return
*/
public String getCode();
/**
* 信息
*
* @return
*/
public String getMsg();
}
package com.jz.dm.gateway.common.util;
/**
* 签名类型
*
*/
public enum SignType {
RSA, RSA2, MD5
}
package com.jz.dm.gateway.common.util;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.jz.dm.gateway.common.StringUtil;
import com.jz.dm.gateway.common.exception.SignatureException;
import com.jz.dm.gateway.signtype.Md5;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
/**
* 签名工具
*
*/
@Slf4j
public class SignatureUtil {
public static final String SIGN_TYPE_RSA = "RSA";
/**
* sha256WithRsa 算法请求类型
*/
public static final String SIGN_TYPE_RSA2 = "RSA2";
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
public static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
public static final String SIGN_REQUEST = "SIGN_REQUEST";
public static final String SIGN_CALLBACK = "SIGN_CALLBACK";
/**
* 获取签名校验内容
*
* @param params
* @return
*/
private static String getVerifyContent(Map<String, Object> params, String... excludeParams) {
if (params == null) {
return null;
}
if (excludeParams == null || excludeParams.length == 0) {
params.remove("sign");
} else {
for (String excludeParam : excludeParams) {
params.remove(excludeParam);
}
}
StringBuffer content = new StringBuffer();
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
for (String key : keys) {
if (params.get(key) != null){
String value = params.get(key).toString();
if (!StringUtils.isEmpty(value)) {
content.append(key).append("=").append(value);
}
}
}
return content.toString();
}
/**
* 校验签名
*
* @param params
* @param publicKey
* @param charset
* @return
* @throws
*/
public static boolean verify(Map params, String publicKey, String charset,
SignType signType, String... excludeParams) {
String sign = (String) params.get("sign");
String content = getVerifyContent(params, excludeParams);
log.info("请求验签: {}", content);
if (signType == SignType.RSA) {
return rsaVerify(content, sign, publicKey, charset);
} else if (signType == SignType.RSA2) {
return rsa256Verify(content, sign, publicKey, charset);
} else if (signType == SignType.MD5) {
String calcSign = Md5.encrypt(content, publicKey, charset);
return StringUtils.equals(calcSign, sign);
} else {
throw new SignatureException(OpenApiResultCode.SIGN_TYPE_NOT_SUPPORT,
"Sign Type is Not Support : signType=" + signType);
}
}
public static void main(String[] args) {
//ed123fca54c919bce4d5e16b6ebd0304
Map<String,Object> map = new HashMap<>();
Map<String,Object> map1 = new HashMap<>();
map1.put("tradeNo", "2020041510842580008");
map1.put("outTradeNo", "XJ1586919520927");
map1.put("status", "PAYMENT");
map.put("data", map1);
String responseJson = JsonUtil.toJSONString(map,
PropertyNamingStrategy.SnakeCase);
String s = "app_id=200407008243charset=UTF-8method=trade.submitparams={\"accountType\":\"WBANK\",\"outTradeNo\":\"TS2020041411353338464\",\"remark\":\"test11\",\"items\":[{\"amount\":\"10\",\"idCard\":\"430524199707287172\",\"mobile\":\"15910401066\",\"name\":\"马斌\",\"remark\":\"test22\",\"cardNo\":\"6217995550000488697\"}]}sign_type=MD5timestamp=1586858028000version=1.0.0";
SignType signType = SignType.MD5;
String calcSign = Md5.encrypt(s, "pwxw5FaQ4UFvycYfbmRvqPQ1m96aJblURXyVsnMXPe8qJhurmebv1XPnvPkJjjC8", "UTF-8");
System.out.println(calcSign);
}
/**
* rsa校验签名
*
* @param content
* @param sign
* @param publicKey
* @param charset
* @return
* @throws
*/
public static boolean rsaVerify(String content, String sign, String publicKey, String charset) {
try {
PublicKey pubKey = getPublicKeyFromX509("RSA",
new ByteArrayInputStream(publicKey.getBytes()));
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initVerify(pubKey);
if (StringUtil.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
return signature.verify(Base64.decodeBase64(sign.getBytes()));
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.SIGN_VERIFY_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* rsa256校验签名
*
* @param content
* @param sign
* @param publicKey
* @param charset
* @return
* @throws
*/
public static boolean rsa256Verify(String content, String sign, String publicKey,
String charset) {
try {
PublicKey pubKey = getPublicKeyFromX509("RSA",
new ByteArrayInputStream(publicKey.getBytes()));
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_SHA256RSA_ALGORITHMS);
signature.initVerify(pubKey);
if (StringUtil.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
return signature.verify(Base64.decodeBase64(sign.getBytes()));
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.SIGN_VERIFY_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* 获取公钥
*
* @param algorithm
* @param ins
* @return
* @throws Exception
*/
public static PublicKey getPublicKeyFromX509(String algorithm,
InputStream ins) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
StringWriter writer = new StringWriter();
StreamUtil.io(new InputStreamReader(ins), writer);
byte[] encodedKey = writer.toString().getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
/**
* 获取签名内容
*
* @param params
* @return
*/
public static String getSignContent(Map<String, Object> params) {
StringBuffer content = new StringBuffer();
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
int index = 0;
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key) == null ? "" : params.get(key).toString();
if (StringUtil.isNotEmpty(key, value)) {
content.append(key + "=" + value);
index++;
}
}
return content.toString();
}
/**
* 内容签名
*
* @param params
* @param publicKey
* @param charset
* @param signType
* @param providePublicKey true : 惠多多提供外部公钥了, false : 没有对外提供公钥,使用外部公钥加密做签名
* @return
*/
public static String sign(Map<String, Object> params, String publicKey, String charset,
SignType signType, String businessType, boolean providePublicKey) {
String signContent = getSignContent(params);
return sign(signContent, publicKey, charset, signType, businessType, providePublicKey);
}
/**
* rsa内容签名
*
* @param content
* @param privateKey
* @param charset
* @return
*/
public static String sign(String content, String privateKey, String charset,
SignType signType, String type, boolean providePublicKey) {
log.info("参与加签字符串:{}", content);
if (signType == SignType.RSA) {
if (SIGN_CALLBACK.equals(type)) {
if (providePublicKey) {
return callBackRsaSignByPrivateKey(content, privateKey, charset);
} else {
return callBackRsaSignByPublicKey(content, privateKey, charset);
}
}
if (providePublicKey) {
return rsaSignByPrivateKey(content, privateKey, charset);
} else {
return rsaSignByPublicKey(content, privateKey, charset);
}
} else if (signType == SignType.RSA2) {
return rsa256Sign(content, privateKey, charset);
} else if (signType == SignType.MD5) {
return Md5.encrypt(content, privateKey, charset);
} else {
throw new SignatureException(OpenApiResultCode.SIGN_TYPE_NOT_SUPPORT,
"Sign Type is Not Support : signType=" + signType);
}
}
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
InputStream ins) throws Exception {
if (ins == null || StringUtil.isEmpty(algorithm)) {
return null;
}
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
byte[] privateKey = StreamUtil.readText(ins).getBytes();
privateKey = Base64.decodeBase64(privateKey);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
}
/**
* sha256WithRsa 加签
*
* @param content
* @param privateKey
* @param charset
* @return
*/
public static String rsa256Sign(String content, String privateKey, String charset) {
try {
PrivateKey priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA,
new ByteArrayInputStream(privateKey.getBytes()));
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_SHA256RSA_ALGORITHMS);
signature.initSign(priKey);
if (StringUtil.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.DATA_SIGN_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* sha1WithRsa 加签
*
* @param content
* @param publicKey
* @param charset
* @return
*/
public static String rsaSignByPublicKey(String content, String publicKey, String charset) {
try {
byte[] signed = RSA.encryptByPublicKey(content.getBytes(charset), publicKey);
return new String(Base64.encodeBase64(signed));
} catch (InvalidKeySpecException e) {
throw new SignatureException(OpenApiResultCode.PUBLIC_KEY_FORMAT_ERROR,
"RSA公钥格式不正确,请检查是否正确配置了PKCS8格式的公钥", e);
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.DATA_SIGN_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* sha1WithRsa 加签
*
* @param content
* @param privateKey
* @param charset
* @return
*/
public static String rsaSignByPrivateKey(String content, String privateKey, String charset) {
try {
PrivateKey priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA,
new ByteArrayInputStream(privateKey.getBytes()));
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
if (StringUtil.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (InvalidKeySpecException e) {
throw new SignatureException(OpenApiResultCode.PRIVATE_KEY_FORMAT_ERROR,
"RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", e);
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.DATA_SIGN_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* sha1WithRsa 回调内容加签
* @param content
* @param publicKey
* @param charset
* @return
*/
public static String callBackRsaSignByPublicKey(String content, String publicKey, String charset) {
try {
byte[] signed = RSA.encryptByPublicKey(Md5.encrypt(content,"").getBytes(charset), publicKey);
return new String(Base64.encodeBase64(signed));
} catch (InvalidKeySpecException e) {
throw new SignatureException(OpenApiResultCode.PUBLIC_KEY_FORMAT_ERROR,
"RSA公钥格式不正确,请检查是否正确配置了PKCS8格式的公钥", e);
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.DATA_SIGN_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
/**
* sha1WithRsa 回调内容加签
* @param content
* @param privateKey
* @param charset
* @return
*/
public static String callBackRsaSignByPrivateKey(String content, String privateKey, String charset) {
try {
PrivateKey priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA,
new ByteArrayInputStream(privateKey.getBytes()));
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
if (StringUtil.isEmpty(charset)) {
signature.update(Md5.encrypt(content,"").getBytes());
} else {
signature.update(Md5.encrypt(content,"").getBytes(charset));
}
byte[] signed = signature.sign();
return new String(Base64.encodeBase64(signed));
} catch (InvalidKeySpecException e) {
throw new SignatureException(OpenApiResultCode.PRIVATE_KEY_FORMAT_ERROR,
"RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", e);
} catch (Exception e) {
throw new SignatureException(OpenApiResultCode.DATA_SIGN_ERROR,
"RSAcontent = " + content + "; charset = " + charset, e);
}
}
}
package com.jz.dm.gateway.common.util;
import java.io.*;
/**
* 流处理工具
*
*/
public class StreamUtil {
private static final int DEFAULT_BUFFER_SIZE = 8192;
public static void io(InputStream in, OutputStream out) throws IOException {
io(in, out, -1);
}
public static void io(InputStream in, OutputStream out, int bufferSize) throws IOException {
if (bufferSize == -1) {
bufferSize = DEFAULT_BUFFER_SIZE;
}
byte[] buffer = new byte[bufferSize];
int amount;
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
}
public static void io(Reader in, Writer out) throws IOException {
io(in, out, -1);
}
public static void io(Reader in, Writer out, int bufferSize) throws IOException {
if (bufferSize == -1) {
bufferSize = DEFAULT_BUFFER_SIZE >> 1;
}
char[] buffer = new char[bufferSize];
int amount;
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
}
public static OutputStream synchronizedOutputStream(OutputStream out) {
return new SynchronizedOutputStream(out);
}
public static OutputStream synchronizedOutputStream(OutputStream out, Object lock) {
return new SynchronizedOutputStream(out, lock);
}
public static String readText(InputStream in) throws IOException {
return readText(in, null, -1);
}
public static String readText(InputStream in, String encoding) throws IOException {
return readText(in, encoding, -1);
}
public static String readText(InputStream in, String encoding,
int bufferSize) throws IOException {
Reader reader = (encoding == null) ? new InputStreamReader(in)
: new InputStreamReader(in, encoding);
return readText(reader, bufferSize);
}
public static String readText(Reader reader) throws IOException {
return readText(reader, -1);
}
public static String readText(Reader reader, int bufferSize) throws IOException {
StringWriter writer = new StringWriter();
io(reader, writer, bufferSize);
return writer.toString();
}
private static class SynchronizedOutputStream extends OutputStream {
private OutputStream out;
private Object lock;
SynchronizedOutputStream(OutputStream out) {
this(out, out);
}
SynchronizedOutputStream(OutputStream out, Object lock) {
this.out = out;
this.lock = lock;
}
public void write(int datum) throws IOException {
synchronized (lock) {
out.write(datum);
}
}
public void write(byte[] data) throws IOException {
synchronized (lock) {
out.write(data);
}
}
public void write(byte[] data, int offset, int length) throws IOException {
synchronized (lock) {
out.write(data, offset, length);
}
}
public void flush() throws IOException {
synchronized (lock) {
out.flush();
}
}
public void close() throws IOException {
synchronized (lock) {
out.close();
}
}
}
}
package com.jz.dm.gateway.common.util;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
/**
*
* @author Admin
*/
public final class TtpayUtils {
/**
* 除去数组中的空值和签名参数
* 为了兼容健康商城签名问题,过滤sign2参数
* @param sArray 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map<String, String> filter(Map<String, String> sArray) {
Map<String, String> result = new HashMap<String, String>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
if (StringUtils.isEmpty(value) || key.equalsIgnoreCase("sign")) {
continue;
}
result.put(key, value);
}
return result;
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
* @param params 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
// 第一步:把字典按Key的字母顺序排序,参数使用TreeMap已经完成排序
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
// 第二步:把所有参数名和参数值串在一起
StringBuilder sb = new StringBuilder();
for (String key : keys) {
String value = params.get(key);
if (!StringUtils.isEmpty(value)) {
sb.append(key).append("=").append(value);
}
}
return sb.toString();
}
/**
* 方法说明:根据运单号返回还有校验位
*
* @param no
* @return
*/
public static String createId(String mobile, int length) {
int count = 0;
String no = mobile.substring(0, length);//计算前6位校验码
int len = no.length();
for (int i=0;i<len;i++) {
int p = (no.charAt(len - i -1)) * (i * 2 + 1);
int q = divide(p, 10);
int r = p - q * 10;
count += (q + r);
}
return ((divide(count, 10) + 1) * 10 - count) % 10 + mobile.substring(mobile.length() - length + 1);
}
public static int divide(int x, int y) {
if (y == 0) {
return 0;
}
BigDecimal bigX = new BigDecimal(x);
BigDecimal bigY = new BigDecimal(y);
return bigX.divide(bigY, 0, RoundingMode.HALF_UP).intValue();
}
public static void main(String[] args) {
System.out.println(TtpayUtils.createId("15000000013", 7));
}
}
package com.jz.dm.gateway.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
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.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.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
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;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Slf4j
public final class WebUtils {
private static final int CONNECT_TIMEOUT = Config.getHttpConnectTimeout();// 设置连接建立的超时时间为10s
private static final int SOCKET_TIMEOUT = Config.getHttpSocketTimeout();
private static final int MAX_CONN = Config.getHttpMaxPoolSize(); // 最大连接数
private static final int MAX_PRE_ROUTE = Config.getHttpMaxPoolSize();
private static final int MAX_ROUTE = Config.getHttpMaxPoolSize();
private static CloseableHttpClient httpClient; // 发送请求的客户端单例
private static PoolingHttpClientConnectionManager manager; // 连接池管理类
private static ScheduledExecutorService monitorExecutor;
private final static Object syncLock = new Object(); // 相当于线程锁,用于线程安全
/**
* http 请求
*
* @param url
* @param params
* @return
* @throws Exception
*/
public static String post(String url, Map<String, String> params) throws Exception {
CloseableHttpClient client = getHttpClient(url);
String responseText = "";
CloseableHttpResponse response = null;
try {
HttpPost method = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
method.setConfig(requestConfig);
if (params != null) {
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
for (Entry<String, String> param : params.entrySet()) {
NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
paramList.add(pair);
}
method.setEntity(new UrlEncodedFormEntity(paramList, "UTF-8"));
}
response = client.execute(method, HttpClientContext.create());
HttpEntity entity = response.getEntity();
if (entity != null) {
responseText = EntityUtils.toString(entity);
}
} catch (Exception e) {
throw e;
} finally {
try {
if (null != response) {
response.close();
}
} catch (Exception e) {
throw e;
}
}
return responseText;
}
public static String post(String url, Map<String, String> headers, Map<String, String> params) throws Exception {
CloseableHttpClient client = getHttpClient(url);
String responseText = "";
CloseableHttpResponse response = null;
try {
HttpPost method = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
method.setConfig(requestConfig);
if (null != headers && !headers.isEmpty()) {
for (Entry<String, String> entry : headers.entrySet()) {
method.setHeader(entry.getKey(), entry.getValue());
}
}
if (params != null) {
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
for (Entry<String, String> param : params.entrySet()) {
NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue());
paramList.add(pair);
}
method.setEntity(new UrlEncodedFormEntity(paramList, "UTF-8"));
}
response = client.execute(method, HttpClientContext.create());
HttpEntity entity = response.getEntity();
if (entity != null) {
responseText = EntityUtils.toString(entity);
}
} catch (Exception e) {
throw e;
} finally {
try {
if (null != response) {
response.close();
}
} catch (Exception e) {
throw e;
}
}
return responseText;
}
/**
* 通过流方式传数据
*
* @param uri
* @param data
* @return
*/
public static String post(String uri, String data) {
log.info("向银行发起参数:{}", data);
CloseableHttpClient httpClient = getHttpClient(uri);
HttpPost method = new HttpPost(uri);
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
method.setConfig(requestConfig);
String readContent = null;
try {
method.addHeader("Content-type", "application/xml; charset=ISO-8859-1");
method.setHeader("Accept", "application/xml");
method.setEntity(new StringEntity(data, Charset.forName("utf-8")));
HttpResponse response = httpClient.execute(method, HttpClientContext.create());
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
return "failed";
}
HttpEntity entity = response.getEntity();
InputStream in = entity.getContent();
int count = 0;
while (count == 0) {
count = Integer.parseInt("" + entity.getContentLength());// in.available();
}
if (count <= 0) {
return EntityUtils.toString(entity);
}
byte[] bytes = new byte[count];
int readCount = 0; // 已经成功读取的字节的个数
while (readCount <= count) {
if (readCount == count) {
break;
}
readCount += in.read(bytes, readCount, count - readCount);
}
readContent = new String(bytes, 0, readCount, "UTF-8");
log.info("Get Response Content():\n {}", readContent);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return readContent;
}
/**
* 关闭连接池
*/
public static void closeConnectionPool() {
try {
httpClient.close();
manager.close();
monitorExecutor.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 把map转为xml
*
* @param parameters
* @return
*/
public static String parseXML(Map<String, String> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Iterator<Entry<String, String>> itor = parameters.entrySet().iterator();
while (itor.hasNext()) {
Entry<String, String> entry = itor.next();
String k = entry.getKey();
String v = entry.getValue();
if (null != v && !"".equals(v) && !"appkey".equals(k)) {
sb.append("<" + k + ">" + parameters.get(k) + "</" + k + ">\n");
}
}
sb.append("</xml>");
return sb.toString();
}
/**
* 把map转为xml
*
* @param parameters
* @return
*/
public static String parseJSON(Map<String, String> parameters) {
return new JSONWriter().write(parameters);
}
/**
* 从URL中提取所有的参数。
*
* @param query URL地址
* @return 参数映射
*/
public static Map<String, String> splitUrlQuery(String query) {
Map<String, String> result = new HashMap<String, String>();
String[] pairs = query.split("&");
if (pairs != null && pairs.length > 0) {
for (String pair : pairs) {
String[] param = pair.split("=", 2);
if (param != null && param.length == 2) {
result.put(param[0], param[1]);
}
}
}
return result;
}
public static CloseableHttpClient getHttpClient(String url) {
int port = 80;
String hostName = url.split("/")[2];
if (hostName.contains(":")){
String[] args = hostName.split(":");
hostName = args[0];
port = Integer.parseInt(args[1]);
}
if (httpClient == null) {
// 多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁
synchronized (syncLock) {
if (httpClient == null) {
httpClient = createHttpClient(hostName, port);
// 开启监控线程,对异常和空闲线程进行关闭
monitorExecutor = Executors.newScheduledThreadPool(1);
monitorExecutor.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// 关闭异常连接
manager.closeExpiredConnections();
// 关闭5s空闲的连接
manager.closeIdleConnections(Config.getHttpIdelTimeout(), TimeUnit.MILLISECONDS);
}
}, Config.getHttpMonitorInterval(), Config.getHttpMonitorInterval(), TimeUnit.MILLISECONDS);
}
}
}
return httpClient;
}
/**
* 根据host和port构建httpclient实例
*
* @param host 要访问的域名
* @param port 要访问的端口
* @return
*/
public static CloseableHttpClient createHttpClient(String host, int port) {
ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
LayeredConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainSocketFactory).register("https", sslSocketFactory).build();
manager = new PoolingHttpClientConnectionManager(registry);
// 设置连接参数
manager.setMaxTotal(MAX_CONN); // 最大连接数
manager.setDefaultMaxPerRoute(MAX_PRE_ROUTE); // 路由最大连接数
HttpHost httpHost = new HttpHost(host, port);
manager.setMaxPerRoute(new HttpRoute(httpHost), MAX_ROUTE);
// 请求失败时,进行请求重试
HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
if (i > 3) {
// 重试超过3次,放弃请求
log.error("retry has more than 3 time, give up request");
return false;
}
if (e instanceof NoHttpResponseException) {
// 服务器没有响应,可能是服务器断开了连接,应该重试
log.error("receive no response from server, retry");
return true;
}
if (e instanceof SSLHandshakeException) {
// SSL握手异常
log.error("SSL hand shake exception");
return false;
}
if (e instanceof InterruptedIOException) {
// 超时
log.error("InterruptedIOException");
return false;
}
if (e instanceof UnknownHostException) {
// 服务器不可达
log.error("server host unknown");
return false;
}
if (e instanceof ConnectTimeoutException) {
// 连接超时
log.error("Connection Time out");
return false;
}
if (e instanceof SSLException) {
log.error("SSLException");
return false;
}
HttpClientContext context = HttpClientContext.adapt(httpContext);
HttpRequest request = context.getRequest();
if (!(request instanceof HttpEntityEnclosingRequest)) {
// 如果请求不是关闭连接的请求
return true;
}
return false;
}
};
return HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler).build();
}
}
class Config {
static int httpConnectTimeout = 3000;
static int httpSocketTimeout = 60000;
static int httpMaxPoolSize = 2000;
static int httpMonitorInterval = 3000;
static int httpIdelTimeout = 2000;
public static int getHttpIdelTimeout() {
return httpIdelTimeout;
}
public static int getHttpSocketTimeout() {
return httpSocketTimeout;
}
public static int getHttpMaxPoolSize() {
return httpMaxPoolSize;
}
public static int getHttpMonitorInterval() {
return httpMonitorInterval;
}
public static int getHttpConnectTimeout() {
return httpConnectTimeout;
}
}
/**
* Copyright (c) 2011-2014 All Rights Reserved.
*/
package com.jz.dm.gateway.config;
/**
*
* @author Admin
* @version $Id: Property.java 2014年8月27日 下午6:28:46 $
*/
public class Property {
private static java.util.Properties property = null;
private Property() {
}
public static void init(java.util.Properties props) {
property = props;
}
public static void setProperty(String key, Object value) {
property.put(key, value);
}
public static String getProperty(String key) {
return property.getProperty(key);
}
public static String getProperty(String key, String defaultValue) {
return property.getProperty(key, defaultValue);
}
}
package com.jz.dm.gateway.common;
package com.jz.dm.gateway.constant;
/**
* 常量
......@@ -19,7 +19,7 @@ public class Constants {
public static final String ENCRYPT_TYPE_AES = "AES";
public static final String APP_ID = "app_id";
public static final String APP_KEY = "app_key";
public static final String FORMAT = "format";
......@@ -35,9 +35,9 @@ public class Constants {
public static final String CHARSET = "charset";
public static final String NOTIFY_URL = "notify_url";
public static final String RETURN_URL = "return_url";
//public static final String NOTIFY_URL = "notify_url";
//
//public static final String RETURN_URL = "return_url";
public static final String ENCRYPT_TYPE = "encrypt_type";
......@@ -47,12 +47,6 @@ public class Constants {
public static final String SUCCESS = "SUCCESS";
public static final String BUSINESS_ID = "business_id";
public static final String NOTIFY_TYPE = "notify_type";
public static final String NOTIFY_TIME = "notify_time";
/** 默认时间格式 **/
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
......
package com.jz.dm.gateway.config;
package com.jz.dm.gateway.constant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
......@@ -49,10 +49,6 @@ public class GatewayController {
requestContext.setRequest(httpServletRequest);
requestContext.setResponse(httpServletResponse);
GatewayResponse gatewayResponse = gatewayService.invoke(gatewayRequest);
/**
* see https://github.com/alibaba/fastjson/issues/2780
*/
JSONObject result = new JSONObject();
convertResponse(result, gatewayResponse);
return JsonUtil.toJSONString(result, PropertyNamingStrategy.SnakeCase);
......
package com.jz.dm.gateway.filter;
import com.jz.dm.gateway.common.StringUtil;
import com.jz.dm.gateway.common.util.StringUtil;
import com.jz.dm.gateway.common.exception.GatewayException;
import com.jz.dm.gateway.common.util.SignType;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.model.Format;
import com.jz.dm.gateway.model.enums.Format;
import com.jz.dm.gateway.model.GatewayRequest;
import com.jz.dm.gateway.model.GatewayResponse;
import com.jz.dm.gateway.model.GatewayResultCode;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;
/**
* 参数检查
* 参数检查过滤器
*
* @author key
*/
......@@ -25,7 +25,7 @@ public class CheckArgsFilter extends AbstractFilter {
FilterChain chain) {
// 校验参数非空
if (StringUtil.isEmpty(request.getAppId()) || StringUtil.isEmpty(request.getMethod())
if (StringUtil.isEmpty(request.getAppKey()) || StringUtil.isEmpty(request.getMethod())
|| StringUtil.isEmpty(request.getCharset()) || StringUtil.isEmpty(request.getSignType())
|| StringUtil.isEmpty(request.getSign()) || StringUtil.isEmpty(request.getTimestamp())
|| StringUtil.isEmpty(request.getVersion())
......
......@@ -4,7 +4,7 @@ import com.jz.dm.gateway.common.exception.GatewayException;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.model.GatewayRequest;
import com.jz.dm.gateway.model.GatewayResponse;
import com.jz.dm.gateway.model.GatewayResultCode;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import com.jz.dm.gateway.model.RequestContext;
import org.springframework.stereotype.Component;
......
......@@ -4,7 +4,7 @@ import com.jz.dm.gateway.common.exception.GatewayException;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.model.GatewayRequest;
import com.jz.dm.gateway.model.GatewayResponse;
import com.jz.dm.gateway.model.GatewayResultCode;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
......@@ -34,11 +34,10 @@ public class CheckTimestampFilter extends AbstractFilter {
} catch (Exception ex) {
throw new GatewayException(GatewayResultCode.ILLEGAL_ARGUMENT);
}
if (System.currentTimeMillis() - time > max) {
throw new GatewayException(GatewayResultCode.ILLEGAL_REQUEST);
if (System.currentTimeMillis() - time > max) {//无效时间戳
throw new GatewayException(GatewayResultCode.ILLEGAL_TIMETEMP);
}
}
chain.doFilter(request, response);
}
......
......@@ -13,7 +13,8 @@ public interface Filter {
/**
* Returns the filter-name of this filter as defined in the deployment
* descriptor.
* descriptor.
* @return
*/
public String getFilterName();
......
......@@ -5,7 +5,7 @@ import com.jz.dm.gateway.common.util.LogUtil;
import com.jz.dm.gateway.common.util.ResultCode;
import com.jz.dm.gateway.model.GatewayRequest;
import com.jz.dm.gateway.model.GatewayResponse;
import com.jz.dm.gateway.model.GatewayResultCode;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
......@@ -4,10 +4,12 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jz.dm.gateway.common.exception.GatewayException;
import com.jz.dm.gateway.common.util.LogUtil;
import com.jz.dm.gateway.config.LoggingConstants;
import com.jz.dm.gateway.constant.LoggingConstants;
import com.jz.dm.gateway.gateway.DefaultOpenApiDispatcher;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.model.*;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import com.jz.dm.gateway.model.enums.RouteType;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
......@@ -29,6 +31,7 @@ public class InvokeRouteFilter extends AbstractFilter {
protected void internalDoFilter(GatewayRequest request, GatewayResponse response,
FilterChain chain) {
String openApiResponse = null;
//当前系统时间戳
long startTime = System.currentTimeMillis();
try {
OpenApi openApi = (OpenApi) RequestContext.getCurrentContext().get("openApi");
......@@ -41,7 +44,7 @@ public class InvokeRouteFilter extends AbstractFilter {
}
DispatchContext context = new DispatchContext();
context.setAppId(request.getAppId());
context.setAppId(request.getAppKey());
context.setApplication(openApi.getApplication());
context.setOpenApiMethod(request.getMethod());
context.setOpenApiParams(request.getParams());
......
......@@ -2,21 +2,19 @@ package com.jz.dm.gateway.filter;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.jz.dm.gateway.common.StringUtil;
import com.jz.dm.gateway.common.util.StringUtil;
import com.jz.dm.gateway.common.exception.SignatureException;
import com.jz.dm.gateway.common.util.*;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.model.GatewayRequest;
import com.jz.dm.gateway.model.GatewayResponse;
import com.jz.dm.gateway.model.GatewayResultCode;
import com.jz.dm.gateway.model.enums.GatewayResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.security.interfaces.RSAPrivateKey;
import java.util.HashMap;
import java.util.Map;
......@@ -44,7 +42,7 @@ public class SignatureFilter extends AbstractFilter {
String responseJson = null;
String sign = StringUtil.EMPTY_STRING;
String privatekey = null;
if (StringUtil.isEmpty(request.getAppId())) {
if (StringUtil.isEmpty(request.getAppKey())) {
return;
}
//ApiWhite apiWhite = apiWhiteService.byMerchantId(request.getAppId());
......
package com.jz.dm.gateway.filter;
import com.jz.dm.gateway.common.util.HddHashMap;
import com.jz.dm.gateway.common.util.RSAUtils;
import com.jz.dm.gateway.gateway.common.Constants;
import com.jz.dm.gateway.constant.Constants;
import com.jz.dm.gateway.model.*;
import com.jz.dm.gateway.model.enums.RouteType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
......@@ -28,7 +29,7 @@ public class VerifySignFilter extends AbstractFilter {
protected void internalDoFilter(GatewayRequest request, GatewayResponse response,
FilterChain chain) {
HddHashMap params = new HddHashMap();
params.put("app_id", request.getAppId());
params.put("app_id", request.getAppKey());
params.put("method", request.getMethod());
params.put("charset", request.getCharset());
params.put("sign", request.getSign());
......
package com.jz.dm.gateway.gateway;
import com.alibaba.fastjson.JSON;
import com.jz.dm.gateway.common.StringUtil;
import com.jz.dm.gateway.common.util.StringUtil;
import com.jz.dm.gateway.common.exception.OpenApiException;
import com.jz.dm.gateway.common.util.OpenApiRequest;
import com.jz.dm.gateway.common.util.OpenApiResponse;
......
package com.jz.dm.gateway.gateway.common;
/**
* 常量
*
*/
public class Constants {
public static final String SIGN_TYPE_RSA = "RSA";
/**
* sha256WithRsa 算法请求类型
*/
public static final String SIGN_TYPE_RSA2 = "RSA2";
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
public static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
public static final String ENCRYPT_TYPE_AES = "AES";
public static final String APP_ID = "app_id";
public static final String FORMAT = "format";
public static final String METHOD = "method";
public static final String TIMESTAMP = "timestamp";
public static final String VERSION = "version";
public static final String SIGN_TYPE = "sign_type";
public static final String SIGN = "sign";
public static final String CHARSET = "charset";
public static final String NOTIFY_URL = "notify_url";
public static final String RETURN_URL = "return_url";
public static final String ENCRYPT_TYPE = "encrypt_type";
public static final String PARAMS = "params";
public static final String RESPONSE = "response";
public static final String SUCCESS = "SUCCESS";
public static final String BUSINESS_ID = "business_id";
public static final String NOTIFY_TYPE = "notify_type";
public static final String NOTIFY_TIME = "notify_time";
/** 默认时间格式 **/
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/** Date默认时区 **/
public static final String DATE_TIMEZONE = "GMT+8";
/** UTF-8字符集 **/
public static final String CHARSET_UTF8 = "UTF-8";
/** GBK字符集 **/
public static final String CHARSET_GBK = "GBK";
/** JSON 应格式 */
public static final String FORMAT_JSON = "JSON";
/** XML 应格式 */
public static final String FORMAT_XML = "XML";
/** 默认版本 */
public static final String DEFAULT_VERSION = "1.0.0";