问题:Struts2框架的rest-plugin插件中jsonlib库,在序列化时因对象循环引用时触发异常。为了在解决这个问题,修改该插件的源代码并重发编译。
思路:解决这个问题,用了一个简单的思路,就是将jsonlib序列化前,先将循环引用解除,在代码中使用递归和堆栈。
缺失:由于该方式采用如果存在循环引用就返回null值的方式,因此这种方式不具反序列化可行性,需要进一步改进思路。
参考:目前开源的fastjson已经解决了对象循环引用问题
// 处理数组的循环引用
private Object disCycleArray(Object obj, Object owner)
throws IllegalArgumentException, IllegalAccessException {
if (null != obj) {
if (!isRefObject(getComponetType(obj)))
return obj;
Object[] objects = (obj instanceof Collection) ? ((Collection) obj)
.toArray() : ((Object[]) obj);
for (int i = 0; i < objects.length; i++) {
objects[i] = disCycleObject(objects[i], owner);
}
if (obj instanceof Collection) {
Set collection = new HashSet();
CollectionUtils.addAll(collection, objects);
return collection;
}
return objects;
}
return null;
}
private Object disCycleObject(Object obj, Object owner)
throws IllegalArgumentException, IllegalAccessException {
if (null == obj)
return null;
else if (null == owner || obj == owner) {
roots.put(obj.hashCode(), obj);
} else {
if (!contains(roots, owner)) {
roots.put(owner.hashCode(), owner);
}
if (contains(roots, obj))
return null;
}
if (null != obj) {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
Object value = f.get(obj);
if (null != value && !"".equals(value))
if (isArray(value)) {
Object newvalue = disCycleArray(value, obj);
f.set(obj, newvalue);
} else {
if (isRefObject(f.getType())) {
if (contains(roots, value)) {
f.set(obj, null);
} else {
Object newvalue = disCycleObject(value, obj);
f.set(obj, newvalue);
}
}
}
}
//roots.remove(obj.getClass().getName());
roots.remove(obj.hashCode());
return obj;
}
return null;
}
private Class getComponetType(Object obj) {
if (null != obj) {
if (isArray(obj)) {
Object[] objects = (obj instanceof Collection) ? ((Collection) obj)
.toArray() : ((Object[]) obj);
return objects.length > 0 ? (objects[0] == null ? null
: objects[0].getClass()) : null;
}
}
return null;
}
private boolean isRefObject(Class<?> clz) {
if (null != clz)
if (!clz.isPrimitive()
&& !clz.getName().startsWith("java.util")
&& !clz.getName().matches(
"java.lang.(?!\\bObject\\b$)\\S+$")
&& !clz.getName().startsWith("java.io")) {
return true;
}
return false;
}
private boolean contains(Map<Integer, Object> roots, Object obj) {
if (null != obj) {
Object target = roots.get(obj.hashCode());
if (null != target) {
return true;
}
}
return false;
}
private boolean isArray(Object obj) {
return obj instanceof Collection || obj.getClass().isArray();
}
posted on 2013-03-27 11:46
Coundy 阅读(502)
评论(0) 编辑 收藏