首先这是一个人员与机构信息的管理模块,在这里主要是为了阐述一下利用ExtJS与SSH进行前后台交互的几种方式:
下面我就把页面中所用用到的一些业务逻辑类贴一下:
请求action类:
@Controller("personAction")
@Scope("prototype")
public class PersonAction extends BaseAction implements ModelDriven{
@Resource
private PersonManager personManager;
private Person person;
private int orgId;
private int[] ids;
public Object getModel() {
if(person == null){
person = new Person();
}
return person;
}
public void execute(){
//{"datas":[{id:xx},{name:xx},{...}],"totals":xx}
toJSON(personManager.searchPersons());
}
public void save() {
if(person.getId() == null || person.getId() == 0){
personManager.addPerson(person, orgId);
}else{
personManager.updatePerson(person, orgId);
}
//需要向客户端应答成功或失败
Map success = new HashMap();
success.put("success", true);
//{success:true}
toJSON(success);
//return "pub_add_success";
}
public void updateInput() {
Person p = personManager.findPerson(person.getId());
//Ext表单加载模型
ExtLoadModel elm = new ExtLoadModel();
elm.setSuccess(true);
elm.setData(p);
//
// 也可以采用Map的方式:
// Map map = new HashMap();
// map.put("success",true);
// map.put("data", p);
//转换后格式:{success:true,data:{id:xx,name:xxx,sex:xx,address:xx}}
toJSON(elm);
}
public void del() {
//person!del.action?ids=24&ids=21&
System.out.println(ids.toString());
if(ids != null){
for(int i=0; i<ids.length; i++){
personManager.delPerson(ids[i]);
}
}
}
public int getOrgId() {
return orgId;
}
public void setOrgId(int orgId) {
this.orgId = orgId;
}
public int[] getIds() {
return ids;
}
public void setIds(int[] ids) {
this.ids = ids;
}
}
下面贴一下在我们action类中所用到一下类:
基类BaseAction
public class BaseAction {
static{
//避免对象的解释陷入死循环,添加自己的JsonMapper解释器
JSONMapper.addHelper(new MyJsonObjectMapper());
}
/**
* 将一个对象转换为JSON的字符串,并写入HTTP SERVLET OUTPUT STREAM
* @param o
*/
protected void toJSON(Object o){
try {
ServletActionContext.getResponse().setCharacterEncoding("GB18030");
ServletActionContext.getResponse().setContentType("text/html");
//System.out.println(JSONMapper.toJSON( o ).render(true));
ServletActionContext.getResponse().getOutputStream().write(
JSONMapper.toJSON( o ).render(false).getBytes("GB18030")
);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (MapperException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
//清空
MyJsonObjectMapper.clean();
}
}
}
封装数据
/**
* 封装数据
* @author Administrator
*
*/
public class ExtLoadModel {
private boolean success;
private Object data;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
在基类中用到处理JSON数据的类
/**
* 在jsonMapper处理之前做一个简单处理
* 记录已经处理的对象,如果已经处理了。就不在处理否则交给jsonMapper去处理
* @author Administrator
*
*/
public class MyJsonObjectMapper extends ObjectMapper {
public static ThreadLocal dealedObject = new ThreadLocal();
/**
* 判断该对象是否已处理
* 利用Map中key value来存放记录信息
* @param o
* @return
*/
public static boolean hasDealed(Object o){
Map map = (Map)dealedObject.get();
if(map == null){
map = new HashMap();
dealedObject.set(map);//首次放到ThreadLocal中
}
//如果处理对象为空则不进行判断,交由父类处理
if(o == null){
return true;
}
//利用map中key记录处理对象的记录信息
if(map.containsKey(o.toString())){
return true;
}else{
//向map中添加一个key值,记录此对象
map.put(o.toString(), null);
return false;
}
}
/**
* 清空ThreadLocal中的数据
*/
public static void clean(){
dealedObject.remove();
}
@Override
public JSONValue toJSON(Object obj) throws MapperException {
//如果该对象没有处理则交给父类ObjectMapper去处理,完成后返回json格式的对象
if(!hasDealed(obj)){
return super.toJSON(obj);
}
return new JSONObject();
}
}
下面就来看看我们js文件:看看是如何与后台进行交互数据的。
Ext.onReady(function(){ Ext.QuickTips.init(); //显示提示信息 // 相当于一个数据源 var store = new Ext.data.JsonStore({ url:"person.action", root:"datas", totalProperty:"total", fields:["id","name","sex","age","address","duty"] }); //1将向后台发出一个请求,请求中包含的参数是start和limit(每页显示的行数) store.load({params:{start:0,limit:20}}); //CheckBox选择框 var sm = new Ext.grid.CheckboxSelectionModel(); //创建表单的窗口 var createFormWindow = function(){ var postForm = new Ext.form.FormPanel({ baseCls: 'x-plain', defaultType: 'textfield', items: [ { xtype:"hidden", name:"id" }, { fieldLabel:"姓名", name:"name" }, { fieldLabel:"性别", name:"sex" }, { fieldLabel:"年龄", name:"age" }, { fieldLabel:"职务", name:"duty" }, { fieldLabel:"电话", name:"phone" }, { fieldLabel:"地址", name:"address" } ], buttons: [ { xtype:'button', text: '保存', handler:function(){ Ext.MessageBox.show({ msg: '正在保存,请稍等...', progressText: 'Saving...', width:300, wait:true, waitConfig: {interval:200}, icon:'download' }); postForm.form.doAction('submit',{//2通过form向后台发出请求 url:"person!save.action", method:'post', params:'', success:function(form,action){ Ext.MessageBox.hide(); Ext.Msg.alert('恭喜','保存目标成功'); store.reload(); postWindow.destroy(); }, failure:function(){ Ext.Msg.alert('错误','服务器出现错误请稍后再试!'); } }); } }, { text: '取消', handler:function(){ postWindow.destroy(); } } ] }); //将表单放到一个窗口中,并显示 var postWindow = new Ext.Window({ title: "人员信息表单", width: 600, height:500, collapsible:true, maximizable:true, layout: 'fit', plain:true, bodyStyle:'padding:5px;', modal:true, items: postForm }); postWindow.show(); return postForm; }; var tbars = [ //在GridPanel列表界面头部的按钮,包括:添加、删除按钮 //添加按钮 { text:'添加', tooltip:'添加记录', handler:createFormWindow }, {xtype:'tbseparator'}, //删除按钮 { text:'删除', tooltip:'删除选中的记录', handler:function(){ var _record = sm.getSelected(); if(_record){ //提示是否删除数据 Ext.Msg.confirm("是否要删除?","是否要删除这些被选择的数据?", function(btn){ if(btn == "yes"){ var ss = sm.getSelections(); var delUrl = "person!del.action?"; for(var i=0; i<ss.length; i++){ delUrl = delUrl + "ids=" + ss[i].data.id + "&"; //ds.remove(ss[i]); } //3发出AJAX请求删除相应的数据! //delUrl=person!del.action?ids=1&ids=2&ids=3&; Ext.Ajax.request({ url:delUrl, success:function(){ Ext.Msg.alert("删除信息成功","您已经成功删除信息!"); store.reload(); }, failure:function(){ Ext.Msg.alert('错误','服务器出现错误请稍后再试!'); } }); } } ); }else{ Ext.Msg.alert('删除操作','您必须选择一行数据以便删除!'); } } } ]; // create the Grid var grid = new Ext.grid.GridPanel({ store: store, columns: [ sm, {header: "序号", width: 50, sortable: true, dataIndex: 'id'}, {header: "姓名", width: 275, sortable: true, dataIndex: 'name'}, {header: "性别", width: 100, sortable: true, dataIndex: 'sex'}, {header: "年龄", width: 100, sortable: true, dataIndex: 'age'}, {header: "地址", width: 300, sortable: true, dataIndex: 'address'}, {header: "职务", width: 200, sortable: true, dataIndex: 'duty'} ], height:350, width:900, title:'人员数据信息列表', sm : sm, bbar:new Ext.PagingToolbar({ pageSize: 20, store: store, displayInfo: true, displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条', emptyMsg: "没有记录" }), tbar:tbars }); grid.on("rowdblclick",function(){ var _record = sm.getSelected(); if(_record){ var postForm = createFormWindow(); postForm.load({//4加载后台数据另一种方式 url : 'person!updateInput.action?id='+_record.get("id"), waitMsg : '正在载入数据...', method:"get", failure : function(e) { Ext.Msg.alert('编辑', '载入失败'+e); } }); }else{ Ext.Msg.alert('修改操作','您必须选择一行数据以便修改!'); } }); grid.render('grid-example'); });
在我们jsp页面中只需要引入这些js文件即可:
<link rel="stylesheet" type="text/css"
href="ext-3.1.1/resources/css/ext-all.css" />
<script type="text/javascript"
src="ext-3.1.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript"
src="ext-3.1.1/ext-all.js"></script>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<div id="grid-example"></div>
</body>
关于分页,我在这里并没有贴出相关代码,因为我在前面也说了。主要是为了看看ExtJS与后台业务逻辑进行交互传递数据的方式过程,在细节方面这里还是有许多需要改进的。下面贴出效果图: