如果有哪一個做程式員的小夥伴說自己沒有遇到中文亂碼問題,我是不願意相信的。今天在做微信訂閱号的智能回複時,又一時迷亂的跳進了中文亂碼這個火坑。剛解決問題時,都歡呼雀躍了,完全忘記了她曾經帶給我的痛苦。
一、問題描述

看到沒,紅色框框内的亂碼赤裸裸的對我進行挑釁,而我卻無可奈何,真是糟糕透頂。
二、尋求解決之道
面對問題,隻有拿着刀逼自己去解決啊,能怎麼樣呢?
首先,必須搞清楚微信智能回複的機制,畫圖如下:
ps,工具用得不好,請見諒。
接下來,我們抓重點,看亂碼重要發生在什麼位置。
1.controller傳回給使用者
response.setHeader("content-type", "text/html;charset=UTF-8");// 浏覽器編碼
response.getOutputStream().write(result.getBytes());
就這段代碼了,指定response的編碼方式為UTF-8,按理說亂碼問題應該出現好轉,但是結果依然是沒有。
2.JAXB的toXML
public String toXML(Object obj) {
String result = null;
try {
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(Marshaller.JAXB_FRAGMENT, true);// 去掉封包頭
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLSerializer serializer = getXMLSerializer(os);
m.marshal(obj, serializer.asContentHandler());
result = os.toString("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
logger.info("response text:" + result);
return result;
}
private XMLSerializer getXMLSerializer(OutputStream os) {
OutputFormat of = new OutputFormat();
formatCDataTag();
of.setCDataElements(cdataNode);
of.setPreserveSpace(true);
of.setIndenting(true);
of.setOmitXMLDeclaration(true);
of.setEncoding("UTF-8");
XMLSerializer serializer = new XMLSerializer(of);
serializer.setOutputByteStream(os);
return serializer;
}
這裡有三個關鍵的點:
1. m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
2. getXMLSerializer(os)
3. os.toString("UTF-8");
可以看到以上三個地方均會涉及到轉碼,第1處,設定Marshaller的編碼;第二處,設定整個XMLSerializer的編碼;第三處,設定傳回的ByteArrayOutputStream的string編碼。三處缺一不可。
這次這麼透徹,應該解決了問題了吧,但是解決依然中文亂碼,那該如何是好呢?