为JAXB和response设置编码,解决wechat4j中文乱码
来源:互联网 发布:淘宝外卖点麻辣烫 编辑:程序博客网 时间:2024/04/30 23:12
如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的。今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑。刚解决问题时,都欢呼雀跃了,完全忘记了她曾经带给我的痛苦。
一、问题描述
看到没,红色框框内的乱码赤裸裸的对我进行挑衅,而我却无可奈何,真是糟糕透顶。
二、寻求解决之道
面对问题,只有拿着刀逼自己去解决啊,能怎么样呢?
首先,必须搞清楚微信智能回复的机制,画图如下:
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编码。三处缺一不可。
这次这么透彻,应该解决了问题了吧,但是解决依然中文乱码,那该如何是好呢?
3.tomcat的输出环境作怪
针对这一点,网上有人提供这样的解决思路。
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER% -Dfile.encoding=UTF-8
设置后重启tomcat,问题是能够解决,但副作用是整个tomcat在服务器上运行输出(tomcat的cmd窗口)一直是乱码,我认为这种方案不可取。
在运行的war中加入以下代码
System.getProperty("file.encoding");
你会惊奇的发现,tomcat的运行环境(window server 2008)竟然是GBK,不知道你是否不惊奇,我是吓到了,为什么不是UTF-8呢?如果是GBK的话,上面两个步骤中我加入再多的UTF-8页扯淡啊,不解。
三、解决问题
有了以上的经验,我们修改以下wechat4j的代码,主要是第二点。
public String toXML(Object obj) { String result = null; try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller m = context.createMarshaller(); String encoding = Config.instance().getJaxb_encoding(); logger.debug("toXML encoding " + encoding + "System file.encoding " + System.getProperty("file.encoding")); m.setProperty(Marshaller.JAXB_ENCODING, encoding); 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(encoding); } 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); String encoding = Config.instance().getJaxb_encoding(); of.setEncoding(encoding); XMLSerializer serializer = new XMLSerializer(of); serializer.setOutputByteStream(os); return serializer;}
这两个方法中,对encoding我们加上可配置的编码方式,可手动设置GBK(我的服务器上配置了GBK)、GB2312、UTF-8。
如此,会发现wechat4j的后台输出就不再是中文乱码了,但返回给用户的信息更乱了。
怎么能这样呢,耍我这枚程序员啊,真想吐两句脏话。但别怕啊,既然wechat4j的logger日志不再中文乱码,那么只能说是第1个环节又出现问题了。
调整嘛
response.setHeader("content-type", "text/html;charset=UTF-8");// 浏览器编码response.getOutputStream().write(result.getBytes("UTF-8"));
注意,这里不能是GBK,只能是UTF-8,我表示不清楚为什么,微信的产品经理给出来解释下。
重点,JAXB和response合伙解决wechat4j中文乱码的 方法再次声明如下:
WeChatController.java,就是你配给微信公众开发平台的URL处,response调整如下
response.setHeader("content-type", "text/html;charset=UTF-8");// 浏览器编码response.getOutputStream().write(result.getBytes("UTF-8"));
wechat4j的JaxbParser.java,分别调整toXML(Object obj)和getXMLSerializer(OutputStream os)方法:
public String toXML(Object obj) { String result = null; try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller m = context.createMarshaller(); String encoding = Config.instance().getJaxb_encoding();// GBK logger.debug("toXML encoding " + encoding + "System file.encoding " + System.getProperty("file.encoding")); m.setProperty(Marshaller.JAXB_ENCODING, encoding); 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(encoding); } 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); String encoding = Config.instance().getJaxb_encoding();//GBK of.setEncoding(encoding); XMLSerializer serializer = new XMLSerializer(of); serializer.setOutputByteStream(os); return serializer;}
好了,万事大吉了。
- 为JAXB和response设置编码,解决wechat4j中文乱码
- response字符编码解决中文乱码
- CentOS下设置中文编码设置和中文乱码解决
- 解决Response中文乱码
- JBOSS7编码设置(解决中文乱码有关)
- mysql编码设置(解决中文乱码)
- 设置MySql5.5数据库的字符编码为UTF8,解决中文乱码问题
- dojo+JBoss7设置URI编码为UTF-8,解决传参中文乱码问题
- 解决Charles Response 中文乱码
- sublime text 设置用cmd输出结果时中文是乱码,设置为用gbk编码就可以解决了
- request和response中文乱码
- xajax0.5中文乱码解决 服务器编码为gb2312时
- 中文乱码问题及tomcat设置编码为utf-8
- linux下mysql编码设置学习(解决中文乱码)
- java_javadoc 生成项目文档(设置编码解决中文乱码问题)
- Windows下MySQL UTF8 编码设置(解决中文乱码)
- Eclipse编码设置(解决中文字符乱码)
- mysql字符编码的设置--解决中文乱码问题
- ROS常用三維機器人仿真工具Gazebo教程匯總
- Extjs中treeStore自动提交leaf字段
- 选择时间日历控件DatePickerDialog实现(从外包项目中挖出来整理的)
- A*寻路算法学习及实现
- 分析函数:first_value,last_value用法
- 为JAXB和response设置编码,解决wechat4j中文乱码
- 备忘录模式——对象行为型模式
- bitmap的oom问题
- Redis 配置文件 详解
- C语言中宏定义(#define)时do{...}while(0)的价值
- js函数的闭包
- js事件的分类和介绍
- Composer更新缓慢的解决方案
- 在布局中使用include引入其他layout时引发click事件不触发的问题