您的位置:首页 > 编程语言 > Java开发

Jdk中 String类的getBytes方法的编码问题

2011-07-13 08:16 267 查看

错误案例

这几天生意经的taglist的页面上一直存在缓存不一致的情况,而在本地调试始终不能重现线上的问题。
系统中出现了这样一种情况:在我们新增“doclist_84_饮食健康”的静态位的时候提示已经存在,但在memcached中并不存在。
查看代码发现在把一个key放到Memcached cache中的时候经过了下面的过程.
Object (key) -> 调用对象的toString方法 -> String.getBytes -> 将字节数组md5编码 -> newKeyString
代码如下
public Object get(Object key) throws CacheException {
return manager.get(getKey(key));
}

private String getKey(Object key) {
if (key == null) {
throw new IllegalArgumentException("Cache key not be null");
}
MessageDigest alga;
try {
alga = MessageDigest.getInstance("SHA");
alga.update(region.getBytes());
alga.update(String.valueOf(key).getBytes());
byte[] digest = alga.digest();
return new String(Hex.encodeHex(digest));
} catch (NoSuchAlgorithmException e) {
// nothing
}
return null;
}
上线后发现 “doclist_84_饮食健康” 和 “doclist_84_饮食健康”编码后就都变成了 “doclist_84_????”。

错误分析

java的String.getBytes的时候,默认是按照系统的编码方式对字符串进行编码,系统编码方式不明就按照“ISO-8859-1”方式对字符串编码。 这就导致线上服务器使用 “ISO-8859-1”方式对字符串编码, 这样 Jdk中StringCoding的代码:
static byte[] encode(String charsetName, char[] ca, int off, int len)
throws UnsupportedEncodingException
{
StringEncoder se = (StringEncoder)deref(encoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
因此建议memcached中存放的key最好不要使用中文,防止由于系统编码不同而导致故障。

正确用法

从这次事件的到的教训是:
1.在涉及到中文存储的时候,需要考虑到中文编码可能带来的影响。
2.Linux, windows的不同环境可以导致不同的测试结果, 如果涉及到编码问题,最好在两个系统下都测试一下。
在二方库 com.alibaba.china.biz.cache.store.CacheStore.MemcachedStore类中调用String 的getBytes())的时候指定编码,例如utf8。

测试关注点

Jdk中 String类的getBytes方法的编码问题:有些编码是同环境相关的,在windows系统上可能发现不了问题。 这需要测试在做测试能模拟出生产环境
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐