上文书我们得知用cli操作Redis是不存在国际化问题的,那为何实际项目中时常会出现因为引入Redis导致大范围非英文字符显示为问号呢?本文我们将使用Java客户端Jedis来操作Redis,进一步分析产生问号现象的可能原因。首先来模拟并测试下Jedis的序列化和反序列化过程吧,通常情况下,这里都是国际化问题的重灾区。
1 |
//序列化 public staticbyte[] serialize(Object object) { ObjectOutputStreamobjectOutputStream = null; ByteArrayOutputStreambyteArrayOutputStream = null; try { byteArrayOutputStream =new ByteArrayOutputStream(); objectOutputStream = newObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object); byte[] bytes =byteArrayOutputStream.toByteArray(); return bytes; } catch (Exception e) { e.printStackTrace(); } return null; } // 反序列化 public staticObject deseialize(byte[] bytes) { ByteArrayInputStreambyteArrayOutputStream = null; try { byteArrayOutputStream =new ByteArrayInputStream(bytes); ObjectInputStreamobjectInputStream = new ObjectInputStream(byteArrayOutputStream); return objectInputStream.readObject(); } catch (Exception e) { System.out.println("deserializeexception"); } return null; } @Test public voidtestG11nJedis() { String s = "伯纳多-席尔瓦加盟曼城"; assertEquals(s,deseialize(serialize(s))); } |
测试结果显示——没毛病啊!Redis本身我们已经知晓对国际化的支持是ok的,那只能是Jedis的问题喽?走读下代码,做个地毯式检查吧,毕竟他是一切问题的根源和解药!
1 |
@Override publicList<String> mget(String... fields) { List<byte[]> arrFields = newArrayList<>(); for (String field : fields) { arrFields.add(field.getBytes()); } List<byte[]> results =redisTemplate.execute( (RedisCallback<List<byte[]>>) connection ->connection.mGet(arrFields.toArray(new byte[arrFields.size()][])) ); if (results == null) { return new ArrayList<>(); } final List<String> ret = newArrayList<>(); results.forEach(result -> { if (result != null) { try { ret.add(new String(result)); } catch(UnsupportedEncodingException e) { ret.add(null); } } else { ret.add(null); } }); return ret; } |
读到mget时,应该已经发现点儿什么了吧?作祟的不是Jedis而是override之后的getBytes和new String,明示charset后问题解决。
我们习惯性的把所有问题归结为新事物的引入,殊不知大部分情况下,经都是好经,不过是我们把它念歪了而已。