对 jsonplugin的修改,消除了,与Hibernate 结合是no session的问题(struts2.1.x零配置)

hanjk1234 2009-12-19 08:24:04
首先提供下载地址
http://download.csdn.net/source/1917608
下面说明一下,修改的功能,和方法,如有不对的地方多多包涵
小弟是菜鸟,拍砖就免了,希望大家提一些好的建议,并帮忙测试我好优化

发一个正常零配置的 struts 代码

@ParentPackage("json-default")
@Result(type="json", name = "success")
public class ProvinceJsonAction extends PersistAction<Province>{
private static final long serialVersionUID = -3508124153476681702L;

private List<Province> provinces;


@Autowired
private ProvinceService provinceService;


public String getProvincesJson() {
provinces = provinceService.findAll();
return SUCCESS;
}

@JSON
public List<Province> getProvinces() {
return provinces;
}
public void setProvinces(List<Province> provinces) {
this.provinces = provinces;
}

}


正常情况下, struts的jsonplugin能帮我们把provinces ,或者其他的对象转为json,
并发送到前台,他已经帮我们实现了很好了
但是,有时候,需求,还是不能满足,
1. 当你封装的对象,比如Province ,里面的还有city,school, teacher,等,对象
当你只需要Province,city ,school ,不需要teacher的时候,你需要在school 里面getTeacher() 方法上面
配置@JSON(serialize=false) ,但是请注意,你用了hibernate,teacher是一个底层实体 ,
当你取其他对象的时候,级联了school,也需要teacher,并且,这个teacher 是必须的时候??
你是无法取出的,因为你已经配置了,

2 .Hibernate的查询(q.)一般默认为三层,但是,jsonplugin 是把你的所有对象都给找出来,
这个时侯很容易造成数据冗余,我就是为了要Province ,
但是他吧city ,school,也给我了,我不需要啊,你或许说,恩可以配置,@JSON(serialize=false) ,请看问题1

3 ,jsonplugin 对Hibernate one-to -many,one-to-one 的处理,存在一点小问题,
当他们配置为lazy的时候,jsonplugin处理的方式是,抛出异常

下面是我对他的修改,希望大家,多多提意见

为json.java 添加一个属性

package com.googlecode.jsonplugin.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JSON {
String name() default "";

String exclude() default "";
boolean serialize() default true;

boolean deserialize() default true;

String format() default "";
}
新增加exclude()
//这个意思你不需要在Hibernate实体bean里面配置@json(serialize=false)

// 在当前action配置就可以

@JSON(exclude="city,school")
public List<Province> getProvinces() {
return provinces;
}
他忽略 Province下的city,school,

修改jsonWriter.java ,源代码就去全发了,太长,有兴趣的,可以自己去下

private Integer acount = 1 ;
private String excludeBean = "" ;


/**
* Instrospect bean and serialize its properties
*/
private void bean(Object object) throws JSONException {
/**
*当大于四层的时候,忽略
*/
if(this.acount>4) {
log.warn(" bean name["+object.getClass().getName()+"]beyond 4 level ,has ignore ");
this.add(null) ;
return ;
}
this.add("{");

BeanInfo info;

try {
Class clazz = object.getClass();
info = ((object == this.root) && this.ignoreHierarchy) ? Introspector
.getBeanInfo(clazz, clazz.getSuperclass()) : Introspector
.getBeanInfo(clazz);

PropertyDescriptor[] props = info.getPropertyDescriptors();

boolean hasData = false;
for (int i = 0; i < props.length; ++i) {
PropertyDescriptor prop = props[i];
String name = prop.getName();
Method accessor = prop.getReadMethod();
Method baseAccessor = null;
/*
* jsonplugin已经解决了一部分问题...clazz.getName().indexOf("$$EnhancerByCGLIB$$") > -1
*但是还不够
*/
if (clazz.getName().indexOf("$$EnhancerByCGLIB$$") > -1) {
try {
baseAccessor = Class.forName(
clazz.getName().substring(0, clazz.getName().indexOf("$$")))
.getMethod(accessor.getName(), accessor.getParameterTypes());
} catch (Exception ex) {
log.debug(ex.getMessage(), ex);
}
} else
baseAccessor = accessor;

if (baseAccessor != null) {

JSON json = baseAccessor.getAnnotation(JSON.class);
if (json != null) {
if (!json.serialize())
continue;
if (json.name().length() > 0)
name = json.name();
/*
* 取出曾经添加的忽略的属性
*/
else if(json.exclude().length()>0) {
this.excludeBean += json.exclude()+","
}
}
//忽略
if(excludeBean.length()>0) {
if(name.indexOf(excludeBean)>-1) {
log.debug("excludeBean["+name+"] ignore") ;
continue;
}
}

//ignore "class" and others
if (this.shouldExcludeProperty(clazz, prop)) {
continue;
}
String expr = null;
if (this.buildExpr) {
expr = this.expandExpr(name);
if (this.shouldExcludeProperty(expr)) {
continue;
}
expr = this.setExprStack(expr);
}
Object value = accessor.invoke(object, new Object[0]);
//计数
this.acount+=1;
//当one-to-one的时候,value的值的格式,(去不出来) ,设置为空
if(value!=null) {
if(value.getClass().getName().indexOf("$$EnhancerByCGLIB$$") > -1){
log.debug("hibernate one to one ,name["+name+"] set value=null");
value = null;
}
}
boolean propertyPrinted = this.add(name, value, accessor, hasData);
hasData = hasData || propertyPrinted;
if (this.buildExpr) {
this.setExprStack(expr);
}
}
}
// special-case handling for an Enumeration - include the name() as a property */
if (object instanceof Enum) {
Object value = ((Enum) object).name();
this.add("_name", value, object.getClass().getMethod("name"), hasData);
}
} catch (Exception e) {
throw new JSONException(e);
}

this.add("}");
}


/**
* Add name/value pair to buffer
*/
private boolean add(String name, Object value, Method method, boolean hasData) throws JSONException {

if (!excludeNullProperties || value != null) {
if (hasData) {
this.add(',');
}
this.add('"');
this.add(name);
this.add("\":");
//当value 是one-to-mang的hashset的集合时,设为null
if(value instanceof PersistentSet){
log.debug("hibernate one-to -many,name["+name+"] set value =null") ;
this.value(null, method) ;
}else{
this.value(value, method) ;
}
//计数
this.acount-=1;
return true;
}

return false;
}


----------------end------------------------------------
这样子,就可以解决json与Hibernate之间的大部分问题
1.数据只取三层
2.对one-ton-many ,one-to-one ,值设为null(被设置为延迟加载的时候)
3.不需要配置底层实体,在当前action配置就可以

恩,希望大家帮帮测试,谢谢了
我的邮箱hanjk1234@163.com,
...全文
186 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧