wechat4j获取用户昵称乱码修复

项目对接微信公众号平台时,微信的官方给出的建议是使用wechat4j。官方建议的,自然心里踏实,但实际用起来时发现wechat4j埋有很多雷,最让人心烦意乱的就是中文乱码问题。

之前写过一篇为JAXB和response设置编码,解决wechat4j中文乱码,解决的是智能输入时反馈信息的乱码,遇到同样问题的伙伴可以去参考一下解决方案。

今天要写的是利用wechat4j获取用户昵称乱码的问题。

一、问题描述

UserManager userManager = new UserManager();
org.sword.wechat4j.user.User user = userManager.getUserInfo(tokenResponse.getOpenid());
thirdLoginMember.setThird_name(user.getNickName());

项目运行时,一旦昵称为中文,此方法获得的昵称就是乱码,引发乱码的原因其实很直白,无非就是编码方式不匹配。

二、问题分析

我们来追本溯源,看看以下的代码,我们能感受到问题具体出在哪。

wechat4j中的代码

public User getUserInfo(String openId) {
    return getUserInfo(openId, null);
}

public User getUserInfo(String openId, LanguageType lang) {
    String url = USER_INFO_GET_URL + TokenProxy.accessToken() + "&openid=" + openId;
    if (lang != null) {
        url += "&lang=" + lang.name();
    }
    String resultStr = HttpUtils.get(url);
    logger.info("return data " + resultStr);
    try {
        WeChatUtil.isSuccess(resultStr);
    } catch (WeChatException e) {
        logger.error(e.getMessage());
        e.printStackTrace();
        return null;
    }

    User user = JSONObject.parseObject(resultStr, User.class);
    return user;
}

public static String get(String url){
    return httpGet(url);
}

private static String httpGet(String url) {
    try {
        HttpEntity entity = Request.Get(url).
                execute().returnResponse().getEntity();
        return entity != null ? EntityUtils.toString(entity) : null;
    } catch (Exception e) {
        logger.error("get请求异常," + e.getMessage() + "\n get url:" + url);
        e.printStackTrace();
    }
    return null;
}

httpcore-4.3.3.jar中的代码

public static String toString(final HttpEntity entity)
    throws IOException, ParseException {
    return toString(entity, (Charset)null);
}

public static String toString(
        final HttpEntity entity, final Charset defaultCharset) throws IOException, ParseException {
    Args.notNull(entity, "Entity");
    final InputStream instream = entity.getContent();
    if (instream == null) {
        return null;
    }
    try {
        Args.check(entity.getContentLength() <= Integer.MAX_VALUE,
                "HTTP entity too large to be buffered in memory");
        int i = (int)entity.getContentLength();
        if (i < 0) {
            i = 4096;
        }
        Charset charset = null;
        try {
            final ContentType contentType = ContentType.get(entity);
            if (contentType != null) {
                charset = contentType.getCharset();
            }
        } catch (final UnsupportedCharsetException ex) {
            if (defaultCharset == null) {
                throw new UnsupportedEncodingException(ex.getMessage());
            }
        }
        if (charset == null) {
            charset = HTTP.UTF8_CONTENT_CHARSET;
        }
        logger.info("输出流的转码方式为:" + charset);

        final Reader reader = new InputStreamReader(instream, charset);
        final CharArrayBuffer buffer = new CharArrayBuffer(i);
        final char[] tmp = new char[1024];
        int l;
        while((l = reader.read(tmp)) != -1) {
            buffer.append(tmp, 0, l);
        }
        return buffer.toString();
    } finally {
        instream.close();
    }
}

从上述代码中可得知,wechat4j在取得到参数后,调用httpcore-4.3.3.jar中的EntityUtils类的toString()方法,该方法默认使用的编码方式是“ISO-8859-1”。看到这里,你也许就恍然大悟了,原来如此嘛。那,该如何改动呢?

三、问题解决之道

wechat4j是一个jar包,git上提供了源码下载,你可以选择直接在项目中引入wechat4j.jar,也可以选择把源码作为一个导入项目引入到项目中,我选择的是第二种做法,这种方案方便我们调试,以及修改源码。

在说解决之道之前,我先啰嗦一点关于eclipse中项目之间引用的注意事项。

这里写图片描述

上图是我项目中wechat4j源码的目录:

  1. apache.http就是httpcore-4.3.3.jar的源码。
  2. sword是wechat4j.jar的源码。
  3. tomcat 7 是把该项目引入到一个web项目后,自动出现的,我顺带把wechat4j所需要的jar包添加到lib包下。
  4. 本来wechat4j是一个Java项目。

这里写图片描述

关于deployment assembly我并没有很好的理解其作用(Define packaging structure for this Java EE Web Application project.),大致的意思是把被引入的项目编译成jar包供引用项目使用。

这里写图片描述

build path中引入项目。

这里写图片描述

project reference。

关于这三个之间的关联关系,我真是没有搞明白,敬请小伙伴们指导。

PS:请特别注入,针对wechat4j的引入,被引入项目(ymeng)中不能再放httpcore-4.3.3.jar,否则wechat4j中的httpcore将不会起作用。

那么接下来,我们该好好看看怎么解决了,其实方法依然可知。

第一种,EntityUtils.toString()方法中设置编码方式。

return entity != null ? EntityUtils.toString(entity,"utf-8") : null;

这个其实应该交由wechat4j来做的, 但它坑了。

第二种,EntityUtils.toString方法中设置默认的编码方式为utf-8.

if (charset == null) {
   charset = HTTP.UTF8_CONTENT_CHARSET;
}

看完本篇文章,大家是否略有所获?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉默王二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值