今天我们讨论一下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文件是必须的(我没有仔细研究,不过根据网上搜索的结果看,以及在实际运行过程中报错的情况看,的确是):
这些jar文件具体的作用,我没有仔细研究,不过加上就对了。
其实上面所说的那个插件,无非是定义了一个名字叫json-default的package,定义在这个包下的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 bean在spring容器中的名字,而不是类名。然后这个action会返回一个类型是json的result。
这里,需要注意的是,我们需要增加一个常量:<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)。由这个类定义,我们可以发现几点:
在这里,我在定义属性时,曾将犯了一个错误,导致我长时间没有办法得到正确的结果,那就是我把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字段;
至于ExtJS的GridPanel如何定义,我就不赘述了,可以从网上找到。
之后我会讨论GridPanel的分页问题。