SSH2 + ExtJS + JSON

今天我们讨论一下SSH2结合ExtJS并通过JSON方式提供数据给客户端的问题。

SSH2的整合问题,我们就不讨论了。这可以在我的其他Blog中找到,我们需要讨论的是如何将服务器端查询到的数据,通过JSON格式提供给ExtJS的表格GridPanel显示的问题。

首先,如果我们希望服务器端的action能够返回JSON格式的数据的话,在struts2中,我们可以使用一个JSON插件,struts2-json-plugin-2.1.8.1.jar,因为我用的struts2的版本是2.1.8,所以这个插件的版本是2.1.8.1,如果使用其他版本的struts2的话,插件的版本也许会不同。此外,还有几个jar文件是必须的(我没有仔细研究,不过根据网上搜索的结果看,以及在实际运行过程中报错的情况看,的确是):

  • commons-beanutils-1.7.0.jar
  • commons-lang-2.3.jar
  • ezmorph-1.0.3.jar
  • json-lib-2.1.jar

这些jar文件具体的作用,我没有仔细研究,不过加上就对了。

 

其实上面所说的那个插件,无非是定义了一个名字叫json-defaultpackage,定义在这个包下的action可以返回一个type="json"result,而这个result不必定义jsp页面。其内部机理是将这个action中定义属性(记住是属性,不是字段),以JSON格式返回给客户端。缺省情况下,属性的返回顺序是属性的定义顺序。一个简单的例子就是:

 

    <package name="mydefault" namespace="/test" extends="json-default" >

        <action name="curr" class="currAction">

            <result type="json" />

        </action>

    </package>

 

通过上面的例子,我们可以看出我们定义了一个包,扩展自json-default,这个包下有一个action名字叫curr,它的实现类是currAction,这里之所以类名不是全类名,是因为我们使用了spring类管理所有的action bean,而currAction是这个action beanspring容器中的名字,而不是类名。然后这个action会返回一个类型是jsonresult

这里,需要注意的是,我们需要增加一个常量:<constant name="struts.i18n.encoding" value="UTF-8"/>

 

下面,我们看看相应的action类到底是如何定义的。

@Controller

@Scope("prototype")

public class CurrAction {

    @Resource private CurrencyServiceIntf currencyService;

    private BigDecimal count;

    private JSONArray currencies;

 

    public BigDecimal getCount() {

        return count;

    }

 

    public JSONArray getCurrencies() {

        return currencies;

    }

 

    public String execute() {

        try {

            currencies = JSONArray.fromObject(currencyService.queryList());

            count = currencyService.queryCount();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return "success";

    }

}

这里,我没有列出导入的包(省略了import)。由这个类定义,我们可以发现几点:

  • 这个类由spring管理,这可以通过@Controller注释知道,而且由于spring缺省是singleton,为了线程安全,我们把它设置为prototype
  • 我们使用了spring的依赖注入,将一个service bean注入到了我们的action bean中,这可以通过@Resource注解知道;
  • 我们定义了两个属性:countcurrencies;这两个属性在execute方法中被赋值;那么当这个action被执行后,我们就能够得到JSON类型的数据了;数据的格式是:
    • {"count":431,"currencies":[{"id":500107,"name":"Afghan Afghani"}, {}, {},……{}]};
  • 其中,count表示了当前返回的记录个数是多少,而currencies是真正的数据;当把这一数据传递给前台的ExtJS时,JSON数据的root就是currencies

在这里,我在定义属性时,曾将犯了一个错误,导致我长时间没有办法得到正确的结果,那就是我把JSONArray类型的currencies定义为了String,然后调用了JSONArray.fromObject().toString()方法返回一个字符串。结果错了。因为那样的话,不仅上述数据中的所有引号【"】都被java转义为【\"】,而且会在currencies之后的数据之上打上引号,变成【"currencies": "[{}, {}]"】,这样的话,就是使出吃奶的劲,也别想显示数据了。

 

最后看看,在JS中如何定义data stored吧:

var store = new Ext.data.Store({

            proxy: new Ext.data.HttpProxy({

                url: "curr.action"

            }),

            reader: new Ext.data.JsonReader(

                {

                    totalProperty: 'count',

                    root: 'currencies',

                    id: 'id'

                },

                [

                    {name: 'id', mapping: 'id'},

                    {name: 'name', mapping: 'name'}

                ]

            )

        });

store.load();

 

我们这里为store定义了一个proxy,它负责从服务器端获取数据,由于服务器端的数据获取是一个action,因此这里我们只要写上curr.action即可。然后是一个JSON数据读取器reader,这个读取器需要知道数据个数totalProperty和,数据的根root。以及数据的breakdown字段;

 

至于ExtJSGridPanel如何定义,我就不赘述了,可以从网上找到。

 

之后我会讨论GridPanel的分页问题。

posted on 2011-02-21 11:46  wayne.wang  阅读(4160)  评论(1编辑  收藏  举报

导航