天天看點

為JAXB和response設定編碼,解決wechat4j中文亂碼(2)

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調整如下

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

好了,萬事大吉了。

繼續閱讀