最近要用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的一種補充吧.
|