对 jsonplugin的修改,消除了,与Hibernate 结合是no session的问题

下面说明一下,修改的功能,和方法,如有不对的地方多多包涵
小弟是菜鸟,拍砖就免了,希望大家提一些好的建议,并帮忙测试我好优化

发一个正常零配置的 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配置就可以

恩,希望大家帮帮测试,谢谢了
我的邮箱[email protected],

你可能感兴趣的:(json,Hibernate,bean,struts)