最近一直在写基于Extjs+SSH的界面,学了不少的东西。教科书上的太繁杂,而很多大牛的博客并没有跟上包更新的速度,造成很多不错的工程没有办法直接下载配置和学习,写了关于双向1-N表的查询,用Extjs表现支持分页的表格自动读取返回的json值。本文基于http://www.cnblogs.com/yongfeng/archive/2010/10/29/1864785.html所写,由于Extjs已经升级,还有myeclipse强大的反向工程的功能写了一下的文字。
1.配置struts
我在这个问题的上面就耽误不少的时间,用的是Myeclipse10.0自带struts2,相较于struts官网上的版本还是比较老的,正是因为这样,WebContent/lib中的struts2文件一定要与classpath中的包相同,可以在myeclipse安装文件夹中找到并复制,不然会造成class找不到的错误。
2 在Mysql中建立两个表Student和Mark
DROP TABLE IF EXISTS `test`.`student`;
CREATE TABLE `test`.`student` (
`stuid` varchar(20) NOT NULL,
`stuname` varchar(20) NOT NULL,
`stusex` varchar(20) NOT NULL,
`stuaddress` varchar(20) NOT NULL,
PRIMARY KEY (`stuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `test`.`mark`;
CREATE TABLE `test`.`mark` (
`stuid` varchar(20) DEFAULT NULL,
`stumath` int(11) NOT NULL,
`stuchinese` int(11) NOT NULL,
`stuenglish` int(11) NOT NULL,
PRIKEY `stuid` (`stuid`),
CONSTRAINT `stuid` FOREIGN KEY (`stuid`) REFERENCES `student` (`stuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3 使用hibernate反向工程
3.1 转到Myeclipse Database Explorer
链接到Student和Mark表所在的数据库:参见http://www.cnblogs.com/hoojo/archive/2011/01/07/1929577.html不同的是人家用的MS SQL Server,我用的是MySQL
3.2 配置一下hibernate吧:回到MyEclipse Java Enterprise视图。右键:工程名->MyEclipse->add HibernateXXX 在第二步还是第三步的时候一定选择将包copy到lib文件夹下,省却了复制的麻烦,不然也会产生同上的错误。这样hibernate.cfg.xml也自动的生成了。可以添加一些辅助的语句还是参见:http://www.cnblogs.com/hoojo/archive/2011/01/07/1929577.html,不同的是在配置hibernate的最后一步,要把sessionFactory选中便于自动生成HibernateSessionFactory类,因为我们并不使用spring的包。
3.3 生成表的配置文件:MyEclipse的Database Explorer视图,找到连接数据库下的Student和Mark的table,右键hibernate Reverse Engineering,在弹出的对话框中将many-to-many选中(这一点我并不肯定),剩下的就交给hibernate完成吧,在scr目录下就生成了Student.hbm.xml和Mark.hbm.xml,生成了DAO文件和类文件(什么get……set……和构造函数,以及继承java.io.Serializable都有了)。同时hibernate.cfg.xml中多了
<mapping resource="XX/Mark.hbm.xml" />
<mapping resource="XX/Student.hbm.xml" />
这样两条语句
4. 补充DAO文件中所缺的函数
DAO是自动生成的,无法满足查询需要的函数,借助于HQL和Query类,可以自由地查询返回我们需要的参数
public List QueryAll(int start, int limit) {
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
String sql = "select p.stuid as stuid,p.stuname as stuname,p.stusex as stusex,p.stuaddress as stuaddress,"
+ "q.stumath as stumath,q.stuchinese as stuchinese,q.stuenglish as stuenglish from Student p, Mark q where p.stuid=q.stuid";
Query query = session.createQuery(sql);
session.getTransaction().commit();
if (query != null) {
return query.setFirstResult(start).setMaxResults(limit).list();
}
return null;
}
上面是我的查询函数,写在自己的DAO文件中,因为自动生成的只有StudentDAO和MarkDAO,而没有StudentMarkDAO
5.写Service文件, 由于只是取几个属性就不用json了(需要导入包而且经常出错),直接用String打印输出
@Override
public String execute() throws Exception {
HttpServletResponse response = ServletActionContext.getResponse();
// 编制响应的格式
response.setContentType("text/html;charset=UTF-8");
List<Object[]> finder = studentmark.QueryAll(getStart(), getLimit());
String json = "[";
for (Object[] obj: finder) {
json += "{\"id\":"+"\""+(String)obj[0]+"\""+",";
json += "\"stuname\":"+"\""+(String)obj[1]+"\""+",";
json += "\"stusex\":"+"\""+(String)obj[2]+"\""+",";
json += "\"stuadress\":"+"\""+(String)obj[3]+"\""+",";
json += "\"stumath\":"+obj[4].toString()+",";
json += "\"stuchinese\":"+obj[5].toString()+",";
json += "\"stuenglish\":"+obj[6].toString()+"},";
}
json +="]";
//JSONArray json = JSONArray.fromObject(finder);
response.getWriter().write(
"{\"totalCount\":" + studentmark.FindAllRows() + ",\"data\":" + json.toString() + "}");
System.out.println("{\"totalCount\":" + studentmark.FindAllRows() + ",\"data\":" + json.toString() + "}");
return null;
}
配置struts2.xml中的action到该Service
<action name="getnodes" class="edu.tsinghua.ada.Service.TreeService"></action>
6. Extjs做表现层
6.1 配置extjs4:Extjs4的改动还是相当大的,将包ext-all.js、bootstrap.js(代替了Extjs3中的build.js)、ext-all.css和ext-debug.js(还没用到过)导入到WebContent中,同时导入icon文件夹不然很多按钮没有图标。
6.2 写表现层
Ext.onReady(function() {
var start=0;
var limit=5;
Ext.QuickTips.init();
// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
/**
* Custom function used for column renderer
* @param {Object} val
*/
var store = Ext.create('Ext.data.Store', {
id:'simpsonStore',
autoLoad: false,
fields: [
{name: 'id', type: 'string'},
{name: 'stuname', type: 'string'},
{name: 'stusex', type: 'string'},
{name: 'stuaddress', type: 'string'},
{name: 'stumath', type: 'int'},
{name: 'stuchinese', type: 'int'},
{name: 'stuenglish', type: 'int'},
],
pageSize: limit,
proxy: {
type: 'ajax',
url : 'showdata.action',
reader: {
type: 'json',
root: 'data',
totalProperty: 'totalCount'
}
}
});
store.load({
params:{
start:0,
limit:limit
}
});
// create the Grid
Ext.create('Ext.grid.Panel', {
title: '学生信息',
store: store,
columns: [
{text: '学号', width: 75, sortable: true, dataIndex: 'id'},
{text: '学生姓名', width: 75, sortable : true, dataIndex: 'stuname'},
{text: '学生性别', width: 75, sortable : true, dataIndex: 'stusex'},
{text: '学生地址', width: 75, sortable : true, dataIndex: 'stuaddress'},
{text: '数学成绩', width: 85, sortable : true, dataIndex: 'stumath'},
{text: '语文成绩', width: 85, sortable : true, dataIndex: 'stuchinese'},
{text: '英语成绩', width: 85, sortable : true, dataIndex: 'stuenglish'}
],
height: 200,
width: 600,
renderTo: 'grid-example',
dockedItems: [{
xtype: 'pagingtoolbar',
store: store, // same store GridPanel is using
dock: 'bottom',
displayInfo: true
}]
});
});
在语法上Extjs4比较3更新了很多。
showdata.action通过store中的url与action关联起来,同时找到Service
结语:很简单的程序,自己属于入门级,看了几天的struts2和hibernate,Spring没有怎么看,就开始上手写这个程序了。写的时候参考了很多的博客,以此文分享给大家,期望大家多批评指正。源程序很如果需要请留言!