openfire控制台乱码问题
2019-08-27openfire攻城狮4207°c
A+ A-最近在折腾openfire,源码在IDEA里面跑起来后,发现IDEA控制台输出中文是乱码,而且访问管理端地址,语言不管选中文还是英文,菜单部分依然还是有乱码存在,找了好久,总算是解决了问题,通过百度查到的,千篇一律的都说啥国际化文件里面少了部分属性,所以导致乱码,我也跟着尝试了,并没有什么用,最后还是自己调试源码解决了问题。
openfire版本:4.4.0
选择的语言是中文。
下面是乱码的控制台界面。(其实已经修复了中间部分的乱码了,中间部分已经是正常显示了)
其实这种乱码,主要有两个地方,首先第一个地方是JSTL的jar包,jar包的名字是 taglibs-standard-impl-1.2.5.jar 出问题的类是org.apache.taglibs.standard.tag.common.fmt.MessageSupport.java
这个类主要影响的是所有写了<fmt:message key="index.title.info"/> 标签的JSP页面,上面我标记出来的类就是负责将该标签中的"index.title.info"通过i18n国际化文件转换为对应语言的字符串。
在转换的过程中我不知道为啥它取到的是乱码,但是我在它下面添加了几行代码,重新给字符串编码,就解决了这个问题。
主要该的是这个类中的doEndTag()方法中的几行代码,整个类我就不贴出来了,这个方法的代码如下:
@Override public int doEndTag() throws JspException { String key = null; LocalizationContext locCtxt = null; // determine the message key by... if (keySpecified) { // ... reading 'key' attribute key = keyAttrValue; } else { // ... retrieving and trimming our body if (bodyContent != null && bodyContent.getString() != null) { key = bodyContent.getString().trim(); } } if ((key == null) || key.equals("")) { try { pageContext.getOut().print("??????"); } catch (IOException ioe) { throw new JspTagException(ioe.toString(), ioe); } return EVAL_PAGE; } String prefix = null; if (!bundleSpecified) { Tag t = findAncestorWithClass(this, BundleSupport.class); if (t != null) { // use resource bundle from parent <bundle> tag BundleSupport parent = (BundleSupport) t; locCtxt = parent.getLocalizationContext(); prefix = parent.getPrefix(); } else { locCtxt = BundleSupport.getLocalizationContext(pageContext); } } else { // localization context taken from 'bundle' attribute locCtxt = bundleAttrValue; if (locCtxt.getLocale() != null) { SetLocaleSupport.setResponseLocale(pageContext, locCtxt.getLocale()); } } //注意这里,这里就是我改过的地方---start //String message = UNDEFINED_KEY + key + UNDEFINED_KEY; String message = key; if (locCtxt != null) { ResourceBundle bundle = locCtxt.getResourceBundle(); if (bundle != null) { try { // prepend 'prefix' attribute from parent bundle if (prefix != null) { key = prefix + key; } //message = bundle.getString(key); try{ message = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8"); }catch (Exception e){ }finally { try{ message = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8"); }catch (Exception e){ } } //这里是结束地方 ----end // Perform parametric replacement if required if (!params.isEmpty()) { Object[] messageArgs = params.toArray(); MessageFormat formatter = new MessageFormat(""); // empty pattern, default Locale if (locCtxt.getLocale() != null) { formatter.setLocale(locCtxt.getLocale()); } else { // For consistency with the <fmt:formatXXX> actions, // we try to get a locale that matches the user's preferences // as well as the locales supported by 'date' and 'number'. //System.out.println("LOCALE-LESS LOCCTXT: GETTING FORMATTING LOCALE"); Locale locale = SetLocaleSupport.getFormattingLocale(pageContext); //System.out.println("LOCALE: " + locale); if (locale != null) { formatter.setLocale(locale); } } formatter.applyPattern(message); message = formatter.format(messageArgs); } } catch (MissingResourceException mre) { message = UNDEFINED_KEY + key + UNDEFINED_KEY; } } } if (var != null) { pageContext.setAttribute(var, message, scope); } else { try { pageContext.getOut().print(message); } catch (IOException ioe) { throw new JspTagException(ioe.toString(), ioe); } } return EVAL_PAGE; }
因为这个是该的是jar包的源码,因此在编译后要覆盖Openfire-4.4.0\distribution\target\distribution-base\lib 这个路径下的taglibs-standard-impl-1.2.5.jar这个包中的类,下图是我的路径,根据自己项目的路径参考一下
替换完成后,至少登录页面已经是中文了。
但是登陆成功后还是看到了文章一开始的那个截图页面,菜单啥的都还是乱码,所以我又继续深入跟踪了一下,发现openfire的管理端用的是dwr技术,因此花了好些事件又找到
D:\tempfile\openfire\Openfire-4.4.0\xmppserver\src\main\java\org\jivesoftware\util\LocaleUtils.java
这个类,跟上面的方法一样,也是在
String getLocalizedString(String key, Locale locale, List arguments, ResourceBundle bundle)
这个方法中,更改字符串编码:
public static String getLocalizedString(String key, Locale locale, List arguments, ResourceBundle bundle) { if (key == null) { throw new NullPointerException("Key cannot be null"); } if (locale == null) { locale = JiveGlobals.getLocale(); } String value = getDefaultLocalizedString(key); // See if the bundle has a value try { // The jdk caches resource bundles on it's own, so we won't bother. //value = bundle.getString(key); //这里更改字符串编码 try{ String value1 = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8"); value = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8"); }catch (Exception e){ }finally { try{ value = new String(bundle.getString(key).getBytes("ISO-8859-1"), "UTF-8"); }catch (Exception e){ } } //修改结束 // perform argument substitutions if (arguments != null) { MessageFormat messageFormat = new MessageFormat(""); messageFormat.setLocale(bundle.getLocale()); messageFormat.applyPattern(value); try { // This isn't fool-proof, but it's better than nothing // The idea is to try and convert strings into the // types of objects that the formatters expects // i.e. Numbers and Dates Format[] formats = messageFormat.getFormats(); for (int i = 0; i < formats.length; i++) { Format format = formats[i]; if (format != null) { if (format instanceof DateFormat) { if (arguments.size() > i) { Object val = arguments.get(i); if (val instanceof String) { DateFormat dateFmt = (DateFormat)format; try { val = dateFmt.parse((String)val); arguments.set(i, val); } catch (ParseException e) { Log.error(e.getMessage(), e); } } } } else if (format instanceof NumberFormat) { if (arguments.size() > i) { Object val = arguments.get(i); if (val instanceof String) { NumberFormat nbrFmt = (NumberFormat)format; try { val = nbrFmt.parse((String)val); arguments.set(i, val); } catch (ParseException e) { Log.error(e.getMessage(), e); } } } } } } value = messageFormat.format(arguments.toArray()); } catch (IllegalArgumentException e) { Log.error("Unable to format resource string for key: " + key + ", argument type not supported"); } } } catch (java.util.MissingResourceException mre) { Log.warn("Missing resource for key: " + key + " in locale " + locale.toString()); } return value; }
改完之后重新编译一下,不好使的话,将class文件覆盖到xmppserver-4.4.0.jar 这个jar包中对应的路径:
重启服务器,可以看到已经解决了乱码问题: