一 序
再Redis升级都集群的过程中发现一个case比较有意思,记录下:
现在根据一堆入参,调用md5下返回字节数组,如下所示
DigestUtils.md5(source)
内部的实现,也能看到
/**
* Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
*
* @param data
* Data to digest; converted to bytes using {@link StringUtils#getBytesUtf8(String)}
* @return MD5 digest
*/
public static byte[] md5(final String data) {
return md5(StringUtils.getBytesUtf8(data));
}
现在的问题是:想把key 转换为string,因为切换到redisson之后,对于key还是String更方便。
看到底层编码是UTF8,尝试直接转String。
new String(bytes, org.apache.commons.codec.Charsets.UTF_8);
或者: Charsets.decode((byte[])obj, "UTF-8");
可惜不行啊,输出log都是乱码。
二 自定义转String
关于org.apache.commons.codec.digest.DigestUtils的这个类,看了下源码,觉得跟java 的MessageDigest 应该一样的。测试下
logger.info("orderNoKey DigestUtils.md5:{}",DigestUtils.md5(source));
//MD5表示加密算法,可以选择其他参数,如SHA-1等
MessageDigest digest = MessageDigest.getInstance("MD5");
//先调用update,再调动digest
digest.update(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(source));
byte[] byteResult = digest.digest();
logger.info("orderNoKey new.md5:{}",byteResult);
logger.info("toStr md5:{}",toStr(DigestUtils.md5(source)));
logger.info("toStr md5:{}",toStr(byteResult));
输出:
orderNoKey DigestUtils.md5:[-110, -79, 126, 106, -37, -98, 3, 1, -17, 86, -112, -68, 100, 87, 69, 18]
.md5:[-110, -79, 126, 106, -37, -98, 3, 1, -17, 86, -112, -68, 100, 87, 69, 18]
toStr md5:92B17E6ADB9E0301EF5690BC64574512
toStr md5:92B17E6ADB9E0301EF5690BC64574512
可见,md5效果一致。至于tostr:
private String toStr(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };
//4位代表一个16进制,所以长度需要变为原来2倍
char[] result = new char[bytes.length*2];
int index = 0;
for(byte b:bytes)
{
//先转换高4位
result[index++] = hexDigits[(b>>>4)& 0xf];
result[index++] = hexDigits[b& 0xf];
}
return new String(result);
}
总结:
实际上,如果可以话,不用二进制,换成16进制的md5.hexdigest() 就不用这么麻烦了。