经一同行朋友介绍,目前正在学习由国内某开源团队开源的J2EE MVC框架EasyJWEB(等同于大家熟悉的struts)。EasyJWEB中提供了优秀的查询方式,是一种完全基于面向对象并支持AJAX动态的查询方式。不需要开发人员过多的去熟悉JDBC查询式的SQL语句就能随意的查询,并且提供了更大的查询弹性。
下面我以项目中应用到EasyJWEB的一个CRUD为例,演示一下EasyJWEB是如何进行数据查询的,并且在Views层使用到了EasyJWEB提供的AJAX动态来加载查询到的数据,
首先Views层中新建一个HTML模板文件名为list.html,内容如下:
代码:
< script type ='text/javascript' src ='/ejf/easyajax/prototype.js' ></ script >
< script type ='text/javascript' src ='/ejf/easyajax/engine.js' ></ script >
< script type ='text/javascript' src ='include/easyjweb-util.js' ></ script >
< script type ="text/javascript" > ...
F=new FORM("customer.ejf","ListForm",true);
gotoPage=function(n)...{
$("currentPage").value=n;
quickSearchCustomer();
}
</ script >
< span >
< table width ="100%" height ="97%" align ="center" cellspacing ="0" style ="margin-top:4px;" >
< tr >
< td height ="20" bgcolor ="#FFFFFF" class ="tablehead" > 客户信息查询 </ td >
</ tr >
< tr >
< td valign ="top" >< table height ="100%" cellspacing ="0" style =" margin:-2px -4px -2px -4px; width:101%" >
< form id ="ListForm" name ="ListForm" method ="post" action ="customer.ejf" >
< input type ="hidden" name ="easyJWebCommand" value ="quickSearchList" />
< input type ="hidden" name ="id" value ="$!id" />
< input type ="hidden" name ="mulitId" value ="$!mulitId" />
< input type ="hidden" name ="currentPage" id ="currentPage" value ="$!currentPage" />
< input name ="orderBy" type ="hidden" value ="$!orderBy" />
< input name ="orderType" type ="hidden" value ="$!orderType" />
< tr class ="tablehead3" >
< td height ="25" > 电话号码:
< input name ="customerTel" type ="text" class ="form_text" id ="customerTel" onKeyUp ="if(this.value.length>1)quickSearchCustomer();" /></ td >
< td height ="25" > 名 称:
< input name ="customerTitle" type ="text" class ="form_text" id ="customerTitle" onKeyUp ="if(this.value.length>0)quickSearchCustomer();" /></ td >
</ tr >
< tr class ="tablehead3" >
< td height ="25" > 编 号:
< input name ="customerSn" type ="text" class ="form_text" id ="customer-sn" onKeyUp ="if(this.value.length>1)quickSearchCustomer();" /></ td >
< td height ="25" > 地 址:
< input name ="customerAddress" type ="text" class ="form_text" id ="customer-address" onKeyUp ="if(this.value.length>1)quickSearchCustomer();" />
< input name ="add" type ="button" id ="add" value ="添加" onClick ="loadPage('customer.ejf?cmd=add');" class ="button" />
</ td >
</ tr >
</ form >
< tr align ="center" >
< td height ="20" colspan ="2" valign ="top" class ="tablehead" > 查询结果 </ td >
</ tr >
< tr align ="center" >
< td colspan ="2" valign ="top" class ="tablehead2" >< div id ="mainTable" class ="tablehead3" style ="height:100%;overflow:auto;" > </ div ></ td >
</ tr >
< tr align ="center" >
< td height ="25" colspan ="2" valign ="top" class ="tablehead" >< span id ="pageInfo" ></ span ></ td >
</ tr >
</ table ></ td >
</ tr >
</ table >
< script > ...
quickSearchCustomer=function()...{
EasyAjaxUtil.ajaxSubmit("ListForm","mainTable");
}
quickSearchCustomer();
</ script >
</ span >
List.html页面就是用于显示查询得到的数据列表,其中重点看一下这句JS:EasyAjaxUtil.ajaxSubmit("ListForm","mainTable");EasyAjaxUtil支持通过ajax的方式提交表单的内容,其中ajaxSubmit方法就是用来实现表单以Ajax局部刷新的方式提交的功能。使用方法EasyAjaxUtil.ajaxSubmit(formName,targetId)。
来提交表单ListForm,并把表单执行的结果返回到页面上ID为mainTable中。
再来看一下这两句:
< input type ="hidden" name ="easyJWebCommand" value ="quickSearchList" />
注意:需要使用到EasyJWEB提供的AJAX支持的页面,都必须在页面中先引入如下JS文件:
< script type ='text/javascript' src ='/ejf/easyajax/engine.js' ></ script >
< script type ='text/javascript' src ='include/easyjweb-util.js' ></ script >
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.easyjf.container.annonation.Inject;
import com.easyjf.core.support.query.IQueryObject;
import com.easyjf.core.support.query.QueryObject;
import com.easyjf.microerp.domain.Customer;
import com.easyjf.microerp.query.CustomerQueryObject;
import com.easyjf.microerp.service.ICustomerService;
import com.easyjf.web.Module;
import com.easyjf.web.Page;
import com.easyjf.web.WebForm;
import com.easyjf.web.tools.AbstractCrudAction;
import com.easyjf.web.tools.IPageList;
/** */ /**
* CustomerAction
*
* @author 冷雨
*
*/
public class CustomerAction extends AbstractCrudAction ... {
@Inject
private ICustomerService service;
public void setService(ICustomerService service) ...{
this.service = service;
}
public void doQuickSearchList(WebForm form) ...{
this.doList(form);
}
/**//*
* to get the entity class
*/
@SuppressWarnings("unchecked")
protected Class entityClass() ...{
return Customer.class;
}
/**//*
* to find the entity object
*/
protected Object findEntityObject(Serializable id) ...{
return service.getCustomer((Long) id);
}
/**//*
* to get the entity query param queryObject return IPageList
*/
protected IPageList queryEntity(IQueryObject queryObject) ...{
((QueryObject) queryObject).setPageSize(15);
return service.getCustomerBy(queryObject);
}
/**//*
* to remove an entity param id
*/
protected void removeEntity(Serializable id) ...{
service.delCustomer((Long) id);
}
/**//*
* to batch remove the entities param ids
*/
protected void batchRemoveEntity(List<Serializable> ids) ...{
service.batchDelCustomers(ids);
}
/**//*
* save object to entity
*/
protected void saveEntity(Object object) ...{
service.addCustomer((Customer) object);
}
/**//*
* update an entited object
*/
protected void updateEntity(Object object) ...{
service.updateCustomer(((Customer) object).getId(), (Customer) object);
}
@Override
protected Class getQueryClass() ...{
return CustomerQueryObject.class;
}
}
这里重点说一下两个地方:
方法doQuickSearchList:
this.doList(form);
}
((QueryObject) queryObject).setPageSize(15);
return service.getCustomerBy(queryObject);
}
查询参数queryObject里封装了用户的查询条件,在业务逻辑层中会根据指定的查询参数,查询实体。并返回一个又是封装了分页信息等的IPageList。
2。方法getQueryClass与父类中的方法doList:
在上面说到了查询参数,那EasyJWEB是如何知道我们的查询条件的呢,比如在这里我有一个查询条件是这样的:查询电话号码以132开头,并且地址是在“重庆市”这个范围内的客户。
请重点看一下方法getQueryClass 与父类中的方法doList()
protected Class getQueryClass() ... {
return CustomerQueryObject.class;
}
public void doList(WebForm form) ... {
IPageList pageList = queryEntity((IQueryObject) form
.toPo(getQueryClass()));
CommUtil.saveIPageList2WebForm(pageList, form);
}
如果你手中没有EasyJWEB的源代码(ftp://ftp1.easyjf.com/easyjweb/easyjweb-1.0-m3/easyjweb-1.0-m3.zip)将无法看到doList方法,不过你可以通过上面的链接去下载得到它的源代码,以便能更清楚的明白这里Action的工作方式。首先看一下doList()方法,
form.toPo(getQueryClass())将把form表单中的数据转换成getQueryClass()方法返回的类中,默认为通用查询对象QueryObject.class,由于这里我们在子类CustomerAction中重构了getQueryClass()方法。所以这里将把FORM表单中的数据转换成CustomerQueryObject.class这个类中对应的属性值。
如:在前台FORM表单中有一个input
在后台查询类CustomerQueryObject.class中也有一个对应的属性customerTel,这样通过form.toPo(CustomerQueryObject.class)就能把前台name="customerTel"的值加载到该类中。当然,这里只是为了查询才建立的一个查询对象,如果是只为了得到前台某一个对象的值,采用这种方式是不可取的,而可以改用String strName = (String)form.get("name");这样得到的将是一个字符串。
3。查询核心类CustomerQueryObject.class
import com.easyjf.core.support.query.QueryObject;
/** */ /**
* Customer查询对象
*
* @author 冷雨
*
*/
public class CustomerQueryObject extends QueryObject ... {
private String customerTel = "";
private String customerTitle = "";
private String customerSn = "";
private String customerAddress = "";
@Override
public void customizeQuery() ...{
if (!"".equals(customerTel)) ...{
this.addQuery("obj.tel", customerTel + "%", "like");
}
if (!"".equals(customerTitle)) ...{
this.addQuery("obj.title", "%" + customerTitle + "%", "like");
}
if (!"".equals(customerSn)) ...{
this.addQuery("obj.sn", customerSn, "=");
}
if (!"".equals(customerAddress)) ...{
this.addQuery("obj.address", "%" + customerAddress + "%", "like");
}
super.customizeQuery();
}
public void setCustomerTel(String customerTel) ...{
this.customerTel = customerTel;
}
public void setCustomerTitle(String customerTitle) ...{
this.customerTitle = customerTitle;
}
public void setCustomerSn(String customerSn) ...{
this.customerSn = customerSn;
}
public void setCustomerAddress(String customerAddress) ...{
this.customerAddress = customerAddress;
}
}
this.addQuery("obj.tel", customerTel + "%", "like");
}
this.addQuery("obj.email", email+ "%", "like");
}
注意:
一定要先在CustomerQueryObject.class对象中增加一个属性private String email = "";
if (!"".equals(email)) 这里的"email"名称一定要与上面的属性名称一致并且与前台表单中的name名称一致。
this.addQuery("obj.email", email+ "%", "like");这里的第一个email一定要与域对象中属性名称一致,第二个email也就是上面从前台得到的email值。
新增加一个查询属性,都必须有一个对应的set方法。
最后Action层会调用业务逻辑层相应的方法进行查询,并返回包含了分页信息的IPageList,
quickSearchList.html中的代码为:
< thead >
< tr align ="center" class ="tablehead3" >
< td width ="30" height ="25" > 序号 </ td >
< td height ="25" > 客户编号 </ td >
< td height ="25" > 客户名称 </ td >
< td height ="25" > 电话 </ td >
< td height ="25" > 地址 </ td >
< td height ="25" > 欠空桶 </ td >
< td height ="25" > 赠机 </ td >
< td height ="25" > 赠水 </ td >
< td height ="25" > 赠票 </ td >
< td height ="25" > 操作 </ td >
</ tr >
</ thead >
< tbody >
#foreach( $info in $!list)
< tr align ="center" class ="tablehead3" >
< td height ="25" > $!velocityCount </ td >
< td height ="25" > $!info.sn </ td >
< td height ="25" > $!info.title </ td >
< td height ="25" > $!info.tel </ td >
< td height ="25" > $!info.address </ td >
< td height ="25" > $!info.balanceBarrel </ td >
< td height ="25" > $!info.machine </ td >
< td height ="25" > $!info.presentWater.intValue() </ td >
< td height ="25" > $!info.presentTicket.intValue() </ td >
< td width ="12%" height ="25" >< input type ='button' onClick ="F.doEdit($!info.id)" value ='编辑' class ='button' >
< input type ='button' onClick ="if(confirm('是否真的要删除?')){F.doDel($!info.id);}" value ='删除' class ='button' ></ td >
</ tr >
#end
</ tbody >
</ table >
< span id ="thePageInfo" style ="display:none;" > $!paginationDC </ span >
< script > ...
$("pageInfo").innerHTML=$("thePageInfo").innerHTML;
$("currentPage").value="$!page";
</ script >
以下是EasyJWEB从前台到后台一体的查询结构图: