最近的项目中用到了很多ajax的操作,需要向struts2后台提交、然后接收后台返回的json对象。为这个事情折腾了好久,现在有点空闲了,把过程记录一下。


通用配置

建议用maven来管理jar包。虽然有些大材小用,但一般不会有遗漏。

除struts2的jar包外,还需要struts2-json-plugin.jar。需要注意的是这个插件包和strut2的版本相匹配。我们这次把struts2升级到了2.3.14,导致此前用的struts2-json-plugin-1.8.1.jar抛出ClassNotFoundException。原因就是两个jar包版本不匹配。升级后就ok了。


从struts2返回json对象

最基本的配置就是为action的result属性增加type="json"字段,如下所示:


    

有一点需要注意的是,在返回json的默认处理中,struts2只会将当前root对象(默认就是当前请求的action对象)自己的get方法或属性加入json对象中,而不会处理它的父类中的方法或属性。因此,在action中应该把自己需要输出到json中的方法、属性明确的进行定义,不能指望从父类继承。

如:

public class Father {
    private String name;
    private int age;
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}
public class Son extends Father {
    @Override
    public String getName(){
        return this.name;
    }
    public String execute(){
        return "success";
    }
}

当把Son.java用作一个action时,它的<resultname="success"type="json"/>将只会输出

{
    "name" : "xxx"
}

而不会把父类中的age属性也输出到json对象中。如果需要输出age,则Son中还要定义getAge()方法才行。

从根子上说,这是因为struts2的json拦截器中,有一个属性"ignoreHierarchy"默认设置为"true"。看名字就能猜到,它的意思是“忽略继承等层级关系”。如果在拦截器的配置中将其设置为false,那么输出的json对象将把root的所有父类方法都遍历一遍,直到Object。这就有点矫枉过正了。



向struts2提交json对象

这个需求稍微复杂一点。比上面那个需求多两步:

1、前端发起的ajax请求中,要定义 contentType : "application/json" 这个属性;

2、struts2的拦截器堆栈中,要显式增加json的拦截器:

此外,就是通用的,get和set方法了。

在提交json对象时也遇到了不能用调用父类方法的问题,解决方法和返回json时是一样的。

另外还遇到一个问题。在spring中,为action配置了parent="parentAction"属性;而parentAction的配置中又有abstract="true"的配置。结果,有的开发人员就无法将json对象提交到action中,而同样的配置,另一位开发人员就可以提交。还没有找到原因。