最近要用struts2做一个体育类的系统,由于系统本身的原因(要求可操作性强,用户交互性高),所以不可避免地要用到ajax.在我的前一篇文章里已经提到了有关在struts2中运用ajax的一些东西了.这次重新再拾起来,仔细对比下其中的差别.
在前一个例子性系统中,由于所有的编码都是以UTF-8进行编码的,所以也没有碰到过有关乱码的问题.普通调用和ajax调用都很正常地运行了.而在新的系统中,要求所有的页面(包括数据库)都要求运用GBK编码.这样,一些有关于乱码的问题就出现了,乱码...与struts2有关.
大家都知道,在struts2的配置文件中,有一个配置项直接跟编码有关."struts.i18n.encoding"这个配置项表示struts2将对数据进行何种形式的编码操作,默认的编码为utf-8,这也是为什么在前一个新闻系统中没有乱码的原因,因为它本身都和系统默认编码一致.而在新的系统中,由于要求必须将编码改成GBK,配置如下:
- <constant name="struts.i18n.encoding" value="GBK"/>
<constant name="struts.i18n.encoding" value="GBK"/>
在这种情况下,加上在tomcat serve.xml中修改URIEncoding=GBK,保证传送到服务器的数据都是GBK格式.实际测试中,这种方式是正确的,编码正确.
然而好境不长,当运用到ajax时,问题出现了.我最先采用的是struts2的json插件,看它的要求,它要求工程编码应该为UTF-8,而我的工程编码实际为GBK,这是不可能改回去的事情.先不管它,在页面中配置完成,进行ajax调用.果然,数据乱码.在action中,对数据进行了测试,发现数据在进行action时已经是乱码.对数据进行转码操作,发现将数据按
- x = new String(x.getBytes("GBK"),"UTF-8");
x = new String(x.getBytes("GBK"),"UTF-8");
时,数据正常了.这就表示数据是按照utf-8格式进行传送的,而在sturts中可能将数据又转回了gbk,导致乱码产生.一开始从js入手,因为我用的prototype.js采用post进行传送.设置的encoding为"UTF-8",修改js的encoding为"GBK",发现并没有按照想像的方向发展,仍然乱码.而采用get方式发送时,数据仍然是乱码.
只有从java方向入手了,处理方向有两种,就像我在前面两篇有关jsp乱码中提到一样.第一种是加拦截器,拦截到ajax请求时,将编码重新转码操作.第二种就是像过滤器一样,在进行参数编码前设置正确的编码.在struts2中采用的是第二种方法.其实struts.i18n.encoding采用的也是这种方法.相应的代码如下:
- public void prepare(HttpServletRequest request, HttpServletResponse response) {
- String encoding = null;
- if (defaultEncoding != null) {
- encoding = defaultEncoding;
- }
-
- Locale locale = null;
-
- if (defaultLocale != null) {
- locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
- }
- if (encoding != null) {
- try {
- request.setCharacterEncoding(encoding);
- } catch (Exception e) {
- LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
- }
- }
- if (locale != null) {
- response.setLocale(locale);
- }
- if (paramsWorkaroundEnabled) {
- request.getParameter("foo");
- }
- }
public void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = null;
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
}
}
这个方法这是org.apache.struts2.dispatcher.Dispatcher中而被FilterDispatcher调用,后都大家都知道吧,是struts2的标准过滤器.它调用的地方如下:
- protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
-
- Dispatcher du = Dispatcher.getInstance();
-
-
-
-
- if (du == null) {
-
- Dispatcher.setInstance(dispatcher);
-
-
-
- dispatcher.prepare(request, response);
- } else {
- dispatcher = du;
- }
-
- try {
-
-
- request = dispatcher.wrapRequest(request, getServletContext());
- } catch (IOException e) {
- String message = "Could not wrap servlet request with MultipartRequestWrapper!";
- LOG.error(message, e);
- throw new ServletException(message, e);
- }
-
- return request;
- }
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Dispatcher du = Dispatcher.getInstance();
// Prepare and wrap the request if the cleanup filter hasn't already, cleanup filter should be
// configured first before struts2 dispatcher filter, hence when its cleanup filter's turn,
// static instance of Dispatcher should be null.
if (du == null) {
Dispatcher.setInstance(dispatcher);
// prepare the request no matter what - this ensures that the proper character encoding
// is used before invoking the mapper (see WW-9127)
dispatcher.prepare(request, response);
} else {
dispatcher = du;
}
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding (ww-1278)
request = dispatcher.wrapRequest(request, getServletContext());
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
return request;
}
由上可以看出,filter在实例化dispatcher后,调用其的prepare方法,而prepare方法中,好像涉及到的其他相关操作不多,只是操作request 和 response的,在prepare方法中,判断encoding是不是空,如果不为空则将其设置编码入request中.而在defaultEncoding的设置上,可以看出这个参数是跟struts.i18n.encoding相关的,相关代码如下:
- @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
- public static void setEncoding(String val) {
- encoding = val;
- }
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public static void setEncoding(String val) {
encoding = val;
}
在上面这个方法中,将把struts.i18n.encoding注入到encoding中,也就是说,如果我们设置encoding为GBK,无论在何种条件下,它就是GBK编码了.
尝试修改这种方式,因为直接影响的就是
- prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response)
prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response)
这个方法,于是直接修改如为如下:
- public class TextFilter extends FilterDispatcher{
- private static final Log log = LogFactory.getLog(TextFilter.class);
- private FilterConfig filterConfig;
-
- private static String defaultEncoding;
- private static String defaultLocale;
- private static String paramsWorkaroundEnabled = "false";
-
- @Inject(org.apache.struts2.StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND)
- public static void setParamsWorkaroundEnabled(String enabled) {
- paramsWorkaroundEnabled = enabled;
- }
-
- @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
- public static void setEncoding(String encoding) {
- defaultEncoding = encoding;
- }
-
- @Inject(value = StrutsConstants.STRUTS_LOCALE, required = false)
- public static void setLocale(String locale) {
- defaultLocale = locale;
- }
-
- public void init(FilterConfig filterConfig) throws ServletException {
- super.init(filterConfig);
- this.filterConfig = filterConfig;
- }
-
- protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
- Dispatcher du = Dispatcher.getInstance();
-
- if(du == null) {
- Dispatcher.setInstance(dispatcher);
- prepare(request, response);
- } else {
- dispatcher = du;
- }
-
- try {
- request = dispatcher.wrapRequest(request, getServletContext());
- } catch(IOException e) {
- String message = "Could not wrap servlet request with MultipartRequestWrapper!";
- log.error(message, e);
- throw new ServletException(message, e);
- }
-
- return request;
- }
-
- private void prepare(HttpServletRequest request, HttpServletResponse response) {
- String encoding = request.getCharacterEncoding();
- if(encoding == null) {
- encoding = defaultEncoding;
- }
-
- Locale locale = null;
- if(defaultLocale != null) {
- locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
- }
-
- if(encoding != null) {
- try {
- request.setCharacterEncoding(encoding);
- } catch(Exception e) {
- log.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
- }
- }
-
- if(locale != null) {
- response.setLocale(locale);
- }
-
- if(isParamsWorkaroundEnabled()) {
- request.getParameter("foo");
- }
- }
-
- public boolean isParamsWorkaroundEnabled() {
- ServletContext servletContext = filterConfig.getServletContext();
- return servletContext != null && servletContext.getServerInfo() != null && servletContext.getServerInfo().indexOf("WebLogic") >= 0 ||
- paramsWorkaroundEnabled.equalsIgnoreCase("true");
- }
- }
-
public class TextFilter extends FilterDispatcher{
private static final Log log = LogFactory.getLog(TextFilter.class);
private FilterConfig filterConfig;
private static String defaultEncoding;
private static String defaultLocale;
private static String paramsWorkaroundEnabled = "false";
@Inject(org.apache.struts2.StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND)
public static void setParamsWorkaroundEnabled(String enabled) {
paramsWorkaroundEnabled = enabled;
}
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public static void setEncoding(String encoding) {
defaultEncoding = encoding;
}
@Inject(value = StrutsConstants.STRUTS_LOCALE, required = false)
public static void setLocale(String locale) {
defaultLocale = locale;
}
public void init(FilterConfig filterConfig) throws ServletException {
super.init(filterConfig);
this.filterConfig = filterConfig;
}
protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {
Dispatcher du = Dispatcher.getInstance();
if(du == null) {
Dispatcher.setInstance(dispatcher);
prepare(request, response);
} else {
dispatcher = du;
}
try {
request = dispatcher.wrapRequest(request, getServletContext());
} catch(IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
log.error(message, e);
throw new ServletException(message, e);
}
return request;
}
private void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = request.getCharacterEncoding();
if(encoding == null) {
encoding = defaultEncoding;
}
Locale locale = null;
if(defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if(encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch(Exception e) {
log.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if(locale != null) {
response.setLocale(locale);
}
if(isParamsWorkaroundEnabled()) {
request.getParameter("foo");
}
}
public boolean isParamsWorkaroundEnabled() {
ServletContext servletContext = filterConfig.getServletContext();
return servletContext != null && servletContext.getServerInfo() != null && servletContext.getServerInfo().indexOf("WebLogic") >= 0 ||
paramsWorkaroundEnabled.equalsIgnoreCase("true");
}
}
可以看出,整个就是继承filterDispatcher,再修改其中的一个方法.将dispatcher.prepare()这一名改成filter.prepare的形式,实际上效果是一样的.惟一让人感觉不爽的就是,由于在filter中设置的各种变量都是私有而且是是静态的(我尝试用反射都不能得到它的值),导致直接不能得到父类的属性值,没办法,只有再加变量了.在上面的prepare中,判断request中的编码是不是为空,一般来说,从jsp页面传送的编码都是空的.当由js进行传送时,由于已经设置传送编码为UTF-8,故getCharacterEncoding()不为空,则不再进行设置编码了.其他由设置传送编码为defaultEncoding(即sturts.i18n.encoding).
在上面的有一句
- if(isParamsWorkaroundEnabled()) { request.getParameter("foo"); }
if(isParamsWorkaroundEnabled()) { request.getParameter("foo"); }
专为weblogic设置,由于没有接触过,略过.值得不提的是,request.getParamter("foo").这一句,在tomcat里面是直接将编码固定化,即只要调用了这一句,都将使得request(在tomcat的实现中)不能再接受其他编码(参数已经被转化了).
最后,将filter设置在struts.xml中,以便窗口将参数@inject注入到filter中.
- <bean class="m_ylf.cs.sicau.struts2.TextFilter" static="true"/>
<bean class="m_ylf.cs.sicau.struts2.TextFilter" static="true"/>
上面一句必须要,不然相应的静态参数都没有被注入,是会产生NullPointerException的哦.
先解决这一个问题,下一个问题将介绍struts2的json插件,及改进方法.
在前一篇中<struts2与json插件(1)> ,讲到了解决在struts2中出现的一点点乱码问题,就想看看json中的数据处理方式.由struts2的处理流程来看,主要处理result的代码如下在defaultActionInvocation中:
- private void executeResult() throws Exception {
- result = createResult();
-
- String timerKey = "executeResult: "+getResultCode();
- try {
- UtilTimerStack.push(timerKey);
- if (result != null) {
- result.execute(this);
- } else if (resultCode != null && !Action.NONE.equals(resultCode)) {
- throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
- + " and result " + getResultCode(), proxy.getConfig());
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());
- }
- }
- } finally {
- UtilTimerStack.pop(timerKey);
- }
- }
private void executeResult() throws Exception {
result = createResult();
String timerKey = "executeResult: "+getResultCode();
try {
UtilTimerStack.push(timerKey);
if (result != null) {
result.execute(this);
} else if (resultCode != null && !Action.NONE.equals(resultCode)) {
throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
+ " and result " + getResultCode(), proxy.getConfig());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());
}
}
} finally {
UtilTimerStack.pop(timerKey);
}
}
如上所示,result就是返回的result,而resultCode就是我们通用的String返回类型了.而json插件中,采用默认值Action.Success来得到json类型,而在result中处理,即调用上面的result.invoke(this).json中的主要处理代码如下(省略中间一些代码):
- public void execute(ActionInvocation invocation) throws Exception {
- ActionContext actionContext = invocation.getInvocationContext();
- HttpServletRequest request = (HttpServletRequest) actionContext
- .get(StrutsStatics.HTTP_REQUEST);
- HttpServletResponse response = (HttpServletResponse) actionContext
- .get(StrutsStatics.HTTP_RESPONSE);
-
- try {
- String json;
- Object rootObject;
- if (this.enableSMD) {
-
- rootObject = this.writeSMD(invocation);
- } else {
-
- if (this.root != null) {
- ValueStack stack = invocation.getStack();
- rootObject = stack.findValue(this.root);
- } else {
- rootObject = invocation.getAction();
- }
- }
- json = JSONUtil
- .serialize(rootObject, this.excludeProperties, ignoreHierarchy, enumAsBean);
-
- boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);
-
- JSONUtil.writeJSONToResponse(response, this.defaultEncoding,
- isWrapWithComments(), json, false, writeGzip);
-
- } catch (IOException exception) {
- log.error(exception);
- throw exception;
- }
- }
public void execute(ActionInvocation invocation) throws Exception {
ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) actionContext
.get(StrutsStatics.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) actionContext
.get(StrutsStatics.HTTP_RESPONSE);
try {
String json;
Object rootObject;
if (this.enableSMD) {
//generate SMD
rootObject = this.writeSMD(invocation);
} else {
// generate JSON
if (this.root != null) {
ValueStack stack = invocation.getStack();
rootObject = stack.findValue(this.root);
} else {
rootObject = invocation.getAction();
}
}
json = JSONUtil
.serialize(rootObject, this.excludeProperties, ignoreHierarchy, enumAsBean);
boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);
JSONUtil.writeJSONToResponse(response, this.defaultEncoding,
isWrapWithComments(), json, false, writeGzip);
} catch (IOException exception) {
log.error(exception);
throw exception;
}
}
可以看出,json插件的功能(在处理json上),就是将invocation中的action对象转化成json对象,再输出到页面上.
在上面的应用上来看,用json插件必须注册json的resultType,而且,返回类型一定是json,也就是说,你必须给每一个json调用定义一个json的返回类型,而实际上这个类型就是转向jsonResult上,和一般的调用不一样,它不返回任何视图.即json这个返回类型感觉上完全是多余的,除了标明是json返回之外没有其他作用.而且对于解析来说,它是解析一个action对象,所就是说,如果你的action是富对象,里面有很多的属性,而实际你需要的不多时,那这个解析就完全失去了作用了.
话说这么多,改进方法,从根本上来说,就是改进这种解析机制.是不解析当前的action对象,而是像spring一样,解析只需要解析的对象一样.如返回a,就只需要解析a.查看上面的executeResult()方法,其中对result和resultCode进行了处理.其中有这么一句
- if (result != null) {
- result.execute(this);
- } else if (resultCode != null && !Action.NONE.equals(resultCode)) {
- throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
- + " and result " + getResultCode(), proxy.getConfig());
- } else {
- if (LOG.isDebugEnabled()) {
- LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());
- }
- }
if (result != null) {
result.execute(this);
} else if (resultCode != null && !Action.NONE.equals(resultCode)) {
throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
+ " and result " + getResultCode(), proxy.getConfig());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());
}
}
第一句,也就是一般我们进行处理的地方,调用result进行最后的处理.而第二句,则是对resultCode进行判断,而第三句什么都不做.所以,对于其他的处理,可以从resultCode下手.方法有两种,一是返回无类型,即void类型,二是返回Action.NONE.当是这两种类型的时候,struts2就不会对result进行主动处理了.详细可参见struts2对Action.NONE的说明,如下:
-
-
-
-
-
- public static final String NONE = "none";
/**
* The action execution was successful but do not
* show a view. This is useful for actions that are
* handling the view in another fashion like redirect.
*/
public static final String NONE = "none";
即我们只需要在action方法中,处理ajax调用,而返回void或者"none"就行了.参考方法调用就如下:
- public void showCategoryListAjax2() throws Exception {
- this.category = this.service.getCategory(this.id);
-
- if(this.category == null) {
- AjaxResponse.sendAjaxText(null, ServletActionContext.getResponse());
- return;
- }
-
- this.categoryList = this.service.getCategoryListBySuperCategory(this.category);
-
- AjaxResponse.sendAjaxText(this.categoryList, ServletActionContext.getResponse());
- }
public void showCategoryListAjax2() throws Exception {
this.category = this.service.getCategory(this.id);
/** 如果该类别为空 **/
if(this.category == null) {
AjaxResponse.sendAjaxText(null, ServletActionContext.getResponse());
return;
}
this.categoryList = this.service.getCategoryListBySuperCategory(this.category);
AjaxResponse.sendAjaxText(this.categoryList, ServletActionContext.getResponse());
}
上面的返回类别是一种取巧的方法,更好的方法是返回Action.NONE.这样在struts.xml配置就像这样:
- <action name="taa" class="articleAction" method="topArticleAjax"/>
<action name="taa" class="articleAction" method="topArticleAjax"/>
是不是更好,惟一要做的就是在action方法处理json转换.不过这不是主要问题,在参考json的转换模式上,我对json转换进行了改进.在Fly_m的注解上如下:
- public @Interface Fly_m{
- String name() default "";
- String format() default "";
- boolean exclude() default false;
- }
public @Interface Fly_m{
String name() default "";
String format() default "";
boolean exclude() default false;
}
支持如json一样的名称和format以及exclude(如果为真则不进行转换).另外,支持排除指定类(如果转换对象类型和排除类一致而不进行转换)和指定名称的对象(如果对象名称和排除对象名称一致,则被忽略,只限于对象和map.这对于hibernate这种相互调用的持久层对象最好了).如对象a.b.c的形式.默认的json转换是完全转换,在json插件上,如果在b上设定json(exclude),则无论如何b都不会被转换,这种方法太过固定,不支持临时配置.而在改进中,只需要加一个"a.b"形式的excludeProperties参数就可以了.如果想转换时,把参数去掉就行了.相应的转换方法如下:
- public static String convertToJson(Object obj, String... excludeProperties) {
- return convertToJson(obj, null, null, excludeProperties);
- }
public static String convertToJson(Object obj, String... excludeProperties) {
return convertToJson(obj, null, null, excludeProperties);
}
- public static String convertToJson(Object obj, Format format, Class[] excludeClasses, String... excludeProperties) {
- JsonHandle jsonHandle = new JsonHandle();
- jsonHandle.excludeProperties = excludeProperties;
- jsonHandle.excludeClasses = excludeClasses;
- if(format != null)
- jsonHandle.defaultFormat = format;
- return jsonHandle.convertToJson(null, 0, obj);
- }
public static String convertToJson(Object obj, Format format, Class[] excludeClasses, String... excludeProperties) {
JsonHandle jsonHandle = new JsonHandle();
jsonHandle.excludeProperties = excludeProperties;
jsonHandle.excludeClasses = excludeClasses;
if(format != null)
jsonHandle.defaultFormat = format;
return jsonHandle.convertToJson(null, 0, obj);
}
而在jsonHandle中是这样处理的.
- public String convertToJson(String s, int depth, Object obj) {
- if(obj == null || obj.getClass().getName().indexOf("$$EnhancerByCGLIB$$") != -1 || contains(excludeClasses, obj.getClass())) {
- sb.append("null");
- } else if(isSimpleType(obj.getClass())) {
- if(obj instanceof Character) {
- sb.append("'").append(obj).append("'");
- } else {
- sb.append(obj);
- }
- } else
- if(String.class.isAssignableFrom(obj.getClass()) || StringBuffer.class.isAssignableFrom(obj.getClass())
- || StringBuilder.class.isAssignableFrom(obj.getClass())) {
- sb.append('"');
- CharacterIterator it = new StringCharacterIterator(obj.toString());
-
- for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
- if(c == '"') {
- sb.append("\\\"");
- } else if(c == '\\') {
- sb.append("\\\\");
- } else if(c == '/') {
- sb.append("\\/");
- } else if(c == '\b') {
- sb.append("\\b");
- } else if(c == '\f') {
- sb.append("\\f");
- } else if(c == '\n') {
- sb.append("\\n");
- } else if(c == '\r') {
- sb.append("\\r");
- } else if(c == '\t') {
- sb.append("\\t");
- } else if(Character.isISOControl(c)) {
- sb.append(unicode(c));
- } else {
- sb.append(c);
- }
- }
-
- sb.append('"');
- } else if(obj instanceof Collection) {
- boolean hibernateFlag;
- try {
- ((Collection) obj).size();
- hibernateFlag = true;
- } catch(Exception ex) {
- hibernateFlag = false;
- }
-
- if(hibernateFlag) {
- sb.append("[");
-
- for(Iterator iterator = ((Collection) obj).iterator(); iterator.hasNext();) {
- convertToJson(s, depth, iterator.next());
-
- if(iterator.hasNext()) {
- sb.append(",\n");
- }
- }
-
- sb.append("]");
- } else {
- sb.append("null");
- }
-
- } else if(obj.getClass().isArray()) {
- sb.append("[");
-
- int max = java.lang.reflect.Array.getLength(obj);
-
- for(int i = 0; i < max; i++) {
- if(i > 0) {
- sb.append(",");
- }
- convertToJson(s, depth, java.lang.reflect.Array.get(obj, i));
- }
-
- sb.append("]");
- } else if(java.util.Map.class.isAssignableFrom(obj.getClass())) {
- if(sb.length() > 0 && sb.lastIndexOf(",") != -1) {
- sb.insert(sb.lastIndexOf(",") + 1, "\n");
- }
- sb.append("{");
-
- for(Map.Entry e : ((Map<?, ?>) obj).entrySet()) {
- if(!(e.getKey() instanceof String))
- continue;
- if(contains(excludeProperties, e.getKey().toString())) {
- continue;
- }
- if(sb.length() > 0 && sb.charAt(sb.length() - 1) == ',' && sb.charAt(sb.length() - 2) == '}') {
- sb.insert(sb.length(), "\n");
- }
- sb.append("\"").append(e.getKey()).append("\"").append(":");
-
- if(depth <= DEFAULT_DEPTH) {
- convertToJson(add(s, e.getKey().toString()), depth + 1, e.getValue());
- } else {
- sb.append("undefined");
- }
-
- sb.append(",");
- }
-
- if(sb.length() > 3) {
- sb.deleteCharAt(sb.length() - 1);
- }
-
- sb.append("}");
- } else {
- Map map = null;
- try {
- map = getPropertiesByReflect(this, obj);
- } catch(Exception ex) {
- ex.printStackTrace();
- }
-
- convertToJson(s, depth, map);
- }
- return sb.toString();
- }
- }
public String convertToJson(String s, int depth, Object obj) {
if(obj == null || obj.getClass().getName().indexOf("$$EnhancerByCGLIB$$") != -1 || contains(excludeClasses, obj.getClass())) {
sb.append("null");
} else if(isSimpleType(obj.getClass())) {
if(obj instanceof Character) {
sb.append("'").append(obj).append("'");
} else {
sb.append(obj);
}
} else
if(String.class.isAssignableFrom(obj.getClass()) || StringBuffer.class.isAssignableFrom(obj.getClass())
|| StringBuilder.class.isAssignableFrom(obj.getClass())) {
sb.append('"');
CharacterIterator it = new StringCharacterIterator(obj.toString());
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if(c == '"') {
sb.append("\\\"");
} else if(c == '\\') {
sb.append("\\\\");
} else if(c == '/') {
sb.append("\\/");
} else if(c == '\b') {
sb.append("\\b");
} else if(c == '\f') {
sb.append("\\f");
} else if(c == '\n') {
sb.append("\\n");
} else if(c == '\r') {
sb.append("\\r");
} else if(c == '\t') {
sb.append("\\t");
} else if(Character.isISOControl(c)) {
sb.append(unicode(c));
} else {
sb.append(c);
}
}
sb.append('"');
} else if(obj instanceof Collection) {
boolean hibernateFlag;
try {
((Collection) obj).size();
hibernateFlag = true;
} catch(Exception ex) {
hibernateFlag = false;
}
if(hibernateFlag) {
sb.append("[");
for(Iterator iterator = ((Collection) obj).iterator(); iterator.hasNext();) {
convertToJson(s, depth, iterator.next());
if(iterator.hasNext()) {
sb.append(",\n");
}
}
sb.append("]");
} else {
sb.append("null");
}
} else if(obj.getClass().isArray()) {
sb.append("[");
int max = java.lang.reflect.Array.getLength(obj);
for(int i = 0; i < max; i++) {
if(i > 0) {
sb.append(",");
}
convertToJson(s, depth, java.lang.reflect.Array.get(obj, i));
}
sb.append("]");
} else if(java.util.Map.class.isAssignableFrom(obj.getClass())) {
if(sb.length() > 0 && sb.lastIndexOf(",") != -1) {
sb.insert(sb.lastIndexOf(",") + 1, "\n");
}
sb.append("{");
for(Map.Entry e : ((Map<?, ?>) obj).entrySet()) {
if(!(e.getKey() instanceof String))
continue;
if(contains(excludeProperties, e.getKey().toString())) {
continue;
}
if(sb.length() > 0 && sb.charAt(sb.length() - 1) == ',' && sb.charAt(sb.length() - 2) == '}') {
sb.insert(sb.length(), "\n");
}
sb.append("\"").append(e.getKey()).append("\"").append(":");
if(depth <= DEFAULT_DEPTH) {
convertToJson(add(s, e.getKey().toString()), depth + 1, e.getValue());
} else {
sb.append("undefined");
}
sb.append(",");
}
if(sb.length() > 3) {
sb.deleteCharAt(sb.length() - 1);
}
sb.append("}");
} else {
Map map = null;
try {
map = getPropertiesByReflect(this, obj);
} catch(Exception ex) {
ex.printStackTrace();
}
convertToJson(s, depth, map);
}
return sb.toString();
}
}
相关的转换方法都参照了其他的处理方式,具体解析方法请参照附件中的JsonUtils类.
这篇文章只是说明了一种对于json的一种新的处理方式,并不是对于json插件的不满,当然我还是喜欢自己的处理方式.加上前面对乱码的处理,算是对struts2的一种补充吧.
|