如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的。今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑。刚解决问题时,都欢呼雀跃了,完全忘记了她曾经带给我的痛苦。
一、问题描述
看到没,红色框框内的乱码赤裸裸的对我进行挑衅,而我却无可奈何,真是糟糕透顶。
二、寻求解决之道
面对问题,只有拿着刀逼自己去解决啊,能怎么样呢?
首先,必须搞清楚微信智能回复的机制,画图如下:
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编码。三处缺一不可。
这次这么透彻,应该解决了问题了吧,但是解决依然中文乱码,那该如何是好呢?