您的位置:首页 > 其它

wechat4j获取用户昵称乱码修复

2016-12-10 17:09 176 查看
项目对接微信公众号平台时,微信的官方给出的建议是使用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源码的目录:

apache.http就是httpcore-4.3.3.jar的源码。

sword是wechat4j.jar的源码。

tomcat 7 是把该项目引入到一个web项目后,自动出现的,我顺带把wechat4j所需要的jar包添加到lib包下。

本来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 乱码