谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题

如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的。今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑。刚解决问题时,都欢呼雀跃了,完全忘记了她曾经带给我的痛苦。

一、问题描述

看到没,红色框框内的乱码赤裸裸的对我进行挑衅,而我却无可奈何,真是糟糕透顶。

二、寻求解决之道

面对问题,只有拿着刀逼自己去解决啊,能怎么样呢?

首先,必须搞清楚微信智能回复的机制,画图如下:

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;
}

好了,万事大吉了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java使用jaxb操作xml示例

    首先定义两个示例类ClassA,ClassB,用于后续的示例演示 复制代码 代码如下: package cn.lzrabbit; public class ClassA {     private int classAId;     private String classAName; private ClassB classB; public int getClassAId() {         return classAId;     } public void setClassAId(i

  • 深入jaxb xjc编码问题的详细介绍

    平时喜欢根据写一个xjc批处理命令,根据xsd批量生成java类,觉得很方便也很酷.但是有时候xsd生成的java类中含有汉字,结果总是有些问题.可是xjc命令参数又没有encoding参数之类的.在网上搜了一通,忽然发现了一个好东东:xjc是由com.sun.tools.internal.xjc.Driver实现的,因此批处理命令可以如下:java -Dfile.encoding=UTF-8 -cp D:\java\jdk1.6.0_03\lib\tools.jar com.sun.tools

  • JAXB简介_动力节点Java学院整理

    一.jaxb是什么  JAXB是Java Architecture for XML Binding的缩写.可以将一个Java对象转变成为XML格式,反之亦然.      我们把对象与关系数据库之间的映射称为ORM,其实也可以把对象与XML之间的映射称为OXM(Object XML Mapping).原来JAXB是Java EE的一部分,在JDK1.6中,SUN将其放到了Java SE中,这也是SUN的一贯做法.JDK1.6中自带的这个JAXB版本是2.0,比起1.0(JSR 31)来,JAXB2

  • Jaxb2实现JavaBean与xml互转的方法详解

    本文实例讲述了Jaxb2实现JavaBean与xml互转的方法.分享给大家供大家参考,具体如下: 一.简介 JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到 XML实例文档. Jaxb 2.0是JDK 1.6的组成部分.我们不需要下载第三方jar包 即可做到轻松转换.Jaxb2使用了JD

  • JAXB命名空间_动力节点Java学院整理

    本篇介绍下JAXB进阶使用,命名空间处理 使用package-info.java添加默认命名空间 在需要添加命名空间的包下面添加package-info.java文件,然后添加@XmlSchema注解,这样整个包序列化时就都会自动加上命名空间了 @XmlSchema(namespace = "http://www.lzrabbit.cn") package com.bjpowernode.test; import javax.xml.bind.annotation.XmlSchema;

  • 谈谈为JAXB和response设置编码,解决wechat4j中文乱码的问题

    如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的.今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑.刚解决问题时,都欢呼雀跃了,完全忘记了她曾经带给我的痛苦. 一.问题描述 看到没,红色框框内的乱码赤裸裸的对我进行挑衅,而我却无可奈何,真是糟糕透顶. 二.寻求解决之道 面对问题,只有拿着刀逼自己去解决啊,能怎么样呢? 首先,必须搞清楚微信智能回复的机制,画图如下: ps,工具用得不好,请见谅. 接下来,我们抓重点,看乱码重要发生在什么位置. 1.cont

  • 解决python中文乱码问题方法总结

    在运行这样类似的代码: #!/usr/bin/env pythons="中文"print s 最近经常遇到这样的问题: 问题一: SyntaxError: Non-ASCII character '\xe4' in file E:\coding\python\Untitled 6.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details 问题二: Un

  • JSP利用过滤器解决request中文乱码问题

    本文为大家分享了JSP用过滤器解决request中文乱码问题,具体内容如下 (1)客户端的数据一般是通过HTTP  GET/POST方式提交给服务器,在服务器端用request.getParameter() 读取参数时,很容易出现中文乱码现象. (2)用过滤器解决request中文乱码问题. (3)代码如下: package my; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public clas

  • PHP解决输出中文乱码问题讲解

    解决 PHP 输出中文乱码的问题 问题描述 今天给导航狗(https://daohanggou.cn/)的 PHP 程序和数据库文件迁移了服务器, 但是迁移到新的服务器上之后 PHP 输出的中文和 PHP 输出的从 MySQL 数据库查询出来的数据中的中文都出现了乱码的情况. 下面记录一下我解决该问题的过程. 解决步骤 首先解决的是 PHP 程序直接输出 (输出的不是从数据库中查询的数据) 的中文乱码的问题. 由于我使用的是一台虚拟主机, 没有管理员权限, 无法修改 PHP 的配置文件, 因此,

  • 解决phpmyadmin中文乱码问题。。。

    解决phpmyadmin中文乱码问题... 去phpMyAdmin的根目录下,打开以下这个文件: libraries/select_lang.lib.php 1.找到有"zh-gb2312"的那一行,把'zh-gb2312' 改成 'zh-gb2312-utf-8' 为什么这样加?那是因为服务器会把没有"-utf-8"的语言过滤掉,在libraries/database_interface.lib.php 第168行,根据英文说:"为了防止混淆"

  • Java实现ftp文件上传下载解决慢中文乱码多个文件下载等问题

    废话不多说了,直接给大家贴代码了,具体代码如下所示: //文件上传 public static boolean uploadToFTP(String url,int port,String username,String password,String path,String filename,InputStream input) { boolean success=false; FTPClient ftp=new FTPClient();//org.apache.commons.net.ftp

  • java中文乱码之解决URL中文乱码问题的方法

    我们主要通过两种形式提交向服务器发送请求:URL.表单.而表单形式一般都不会出现乱码问题,乱码问题主要是在URL上面.通过前面几篇博客的介绍我们知道URL向服务器发送请求编码过程实在是实在太混乱了.不同的操作系统.不同的浏览器.不同的网页字符集,将导致完全不同的编码结果.如果程序员要把每一种结果都考虑进去,是不是太恐怖了?有没有办法,能够保证客户端只用一种编码方法向服务器发出请求? 有!这里我主要提供以下几种方法 一.javascript 使用javascript编码不给浏览器插手的机会,编码之

  • MySQL字符集 GBK、GB2312、UTF8区别 解决MYSQL中文乱码问题

    MySQL中涉及的几个字符集 character-set-server/default-character-set:服务器字符集,默认情况下所采用的. character-set-database:数据库字符集. character-set-table:数据库表字符集. 优先级依次增加.所以一般情况下只需要设置character-set-server,而在创建数据库和表时不特别指定字符集,这样统一采用character-set-server字符集. character-set-client:客户

  • 一句话解决AJAX中文乱码问题[推荐]

    下面是我的程序 HTML :  复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <tit

  • 解决mysql5中文乱码问题的方法

    MySQL5的乱码问题可以用下面的方法解决: 1.设置phpMyAdmin 复制代码 代码如下: Language:Chinese simplified (zh-utf-8) MySQL 字符集:UTF-8 Unicode (utf8) MySQL 连接校对 gbk_chinese_ci 2.创建数据库时 整理设置成 gbk_chinese_ci 3.用SQL建立表中 复制代码 代码如下: ENGINE=MyISAM DEFAULT CHARSET=gbk; ENGINE=InnoDB DEFA

随机推荐