在前一篇中<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);
}
}
如上所示,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) {
//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());
}
}
第一句,也就是一般我们进行处理的地方,调用result进行最后的处理.而第二句,则是对resultCode进行判断,而第三句什么都不做.所以,对于其他的处理,可以从resultCode下手.方法有两种,一是返回无类型,即void类型,二是返回Action.NONE.当是这两种类型的时候,struts2就不会对result进行主动处理了.详细可参见struts2对Action.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());
}
上面的返回类别是一种取巧的方法,更好的方法是返回Action.NONE.这样在struts.xml配置就像这样:
<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;
}
支持如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, 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();
}
}
相关的转换方法都参照了其他的处理方式,具体解析方法请参照附件中的JsonUtils类.
这篇文章只是说明了一种对于json的一种新的处理方式,并不是对于json插件的不满,当然我还是喜欢自己的处理方式.加上前面对乱码的处理,算是对struts2的一种补充吧.
分享到:
相关推荐
struts2-json-plugin,Struts JSON插件
struts2整合json的插件struts2-json-plugin源码,不是jar包
为了方便ajax调用传输数据,在struts2中加入的json插件用来做对象的序列化和反序列化,json插件的下载地址 http://code.google.com/p/jsonplugin/ 1. 下载json插件包,将jar包拷贝到WEB-INF/lib目录 注:struts2...
struts2的json插件实例
两个版本的插件,找了很久的哦!需要的速度下载!
Struts 2并没有开发新的AJAX框架,而是使用时下Java EE平台中比较流行的AJAX框架——Dojo...最近在Musachy Barroso等同志的无私奉献下,开发了Struts 2的JSON插件(Plugin),极大地方便了我们输出JSON结果(Result)。
java相关的Struts2-Json插件的使用例子.pdfjava相关的Struts2-Json插件的使用例子.pdf
struts 2.0 与 2.1 对应需要的json插件
http://blog.csdn.net/gxy1317/article/details/52409360
myeclipse8下STRUTS(自带JSON插件)的JSON传值例子.解决包冲突问题,不用下载GOOGLE插件
struts插件,放入classpath中即用!
Textfilter源和struts.xml配置文件. 博文链接:https://flym.iteye.com/blog/183534
JSON插件是Struts2的Ajax插件,通过利用JSON插件,允许开发者以非常灵活的方式开发AJAX应用。 struts2在配置文件中可以指定返回的结果集的类型为:json.
从正式发行包里,提取,整理的json相关插件jar包