项目对接微信公众号平台时,微信的官方给出的建议是使用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;
}

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

wechat4j获取用户昵称乱码修复的更多相关文章

  1. 微信小程序 获取用户昵称、头像

    前段时间微信小程序对获取用户昵称和头像方法进行了更新,网上很多的文章都已经不适用了,这里简单总结一下,首先,传统接口wx.getUserInfo的效果会弹出一个给用户的弹窗,需要用户授权,经过测试传统 ...

  2. 微信开放接口获取用户昵称保存到MySQL中为空白

    微信昵称中包含emoji表情标签,某些标签是使用了4字节编码的UTF8. 而大多数MySQL数据库现在使用的是3字节UTF8编码,这样会导致保存为空,且不会提示失败. 解决方法有2个,一个是升级到My ...

  3. mysql保存emoji表情(微信开发用户昵称..)

      java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x94' for colum n 'name' at row 1 at c ...

  4. 小程序wx.getUserInfo获取用户信息方案介绍

    问题模块 框架类型 问题类型 API/组件名称 终端类型 操作系统 微信版本 基础库版本 API和组件 - -   - -     背景 小程序一个比较重要的能力就是获取用户信息,也就是使用 wx.g ...

  5. 微信扫码登录(3)---授权码code获取用户基本信息

    授权码code获取用户基本信息 上一遍已经获得微信回调的code,网址:回调获取code     那这篇通过code和其它参数去获得用户基本信息. 1.UserServiceImpl关键代码 @Ove ...

  6. 微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆

    原创声明:本文为本人原创作品,绝非他处转账,转载请联系博主 从接触公众号到现在,开发维护了2个公众号,开发过程中遇到很多问题,现在把部分模块功能在这备案一下,做个总结也希望能给其他人帮助 工欲善其事, ...

  7. 微信网页开发之获取用户unionID的两种方法--基于微信的多点登录用户识别

    假设网站A有以下功能需求:1,pc端微信扫码登录:2,微信浏览器中的静默登录功能需求,这两种需求就需要用到用户的unionID,这样才能在多个登录点(终端)识别用户.那么这两种需求下用户的unionI ...

  8. .NET微信开发通过Access Token和OpenID获取用户信息

    本文介绍如何获得微信公众平台关注用户的基本信息,包括昵称.头像.性别.国家.省份.城市.语言. 本文的方法将囊括订阅号和服务号以及自定义菜单各种场景,无论是否有高级接口权限,都有办法来获得用户基本信息 ...

  9. 微信公众平台如何获取用户的OpenID(一)

    如何获取用户的OpenID,对于微信开发模式下的开发来说,那就是一个非常简单的小功能了.简单介绍一下我是怎样去获取OpenID的. 微信服务器与公众账号服务器交互的信息可以分为3类:请求消息.事件和响 ...

随机推荐

  1. bootloader,kernel,initrc

    http://www.ibm.com/developerworks/cn/linux/l-k26initrd/index.html http://www.68idc.cn/help/server/li ...

  2. phpstrom 常用默认快捷键

    ctrl+j 插入活动代码提示ctrl+alt+t 当前位置插入环绕代码alt+insert 生成代码菜单ctrl+shift+n 查找文件 ctrl+q 查看代码注释ctrl+d 复制当前行ctrl ...

  3. 将vi or vim中的内容复制到terminal中

    1. 查看 vim 是否支持 clipboard 功能 $ vim --version | grep clipboard 2. 如果有 +clipboard 则跳过这一步; 如果显示的是 -clipb ...

  4. 吉哥系列故事——完美队形II---hdu4513(最长回文子串manacher)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4513 题意比最长回文串就多了一个前面的人要比后面的人低这个条件,所以在p[i]++的时候判断一下s[i ...

  5. 使用nginx搭建文件下载服务器

    搭建一个文件服务器的方式有很多,本文介绍笔者曾经用过的两种: 使用nginx 使用java服务,通过controller提供 一.使用nginx搭建 在nginx.conf中直接配置server即可, ...

  6. rabbitMQ 安装,集群搭建, 编码

    RabbitMQ 一.背景 命令行工具: http://www.rabbitmq.com/man/rabbitmqctl.1.man.html 介绍入门文章: http://blog.csdn.net ...

  7. apt-get tips

    1.通过apt-get安装指定版本的软件 apt-get install <package name>=<version> 2.通过apt-cache列举所有可获取的版本 ap ...

  8. java-mybaits-00501-案例-映射分析-订单商品数据模型

    1.数据模型分析思路 1.每张表记录的数据内容          分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程. 2.每张表重要的字段设置          非空字段.外键 ...

  9. Java 运算符及优先级

    运算符 分割符: , ; [] () 算数运算符: + - * / % ++ -- 关系运算符: > < >= <= == != 逻辑运算符: ! & | ^ & ...

  10. Spring第一弹—-全面阐述Spring及轻重量级容器的划分

    Spring是什么? Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架,它的主要目得是简化企业开发. IOC 控制反转 :   1 ...