1. 本章任务
已经可以使用学校管理员登录,我们来实现学校管理员的第一个主要功能:管理奖助学金项目。
奖助学金项目是系统的基础档案,需要学校管理员将项目信息建好后,学生才能申请相关项目。
本章首先来实现下分页显示奖学金项目的功能。
2. 构建测试数据
在数据库项目表构建一些测试数据:
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (1, 'award', '奖学金1', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (2, 'award', '奖学金2', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (3, 'award', '奖学金3', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (4, 'award', '奖学金4', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (5, 'award', '奖学金5', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (6, 'award', '奖学金6', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (7, 'award', '奖学金7', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (8, 'award', '奖学金8', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (9, 'award', '奖学金9', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (10, 'award', '奖学金10', '');
INSERT INTO `scholar-system`.`project`(`id`, `type`, `name`, `about`) VALUES (11, 'help', '助学金11', '');
3. 前端页面开发
3.1 新建页面
新建projectManage.html前端页面,并引入easyui相关的css和js文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="easyui/themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="easyui/themes/icon.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="easyui/jquery.min.js"></script>
<script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>
</head>
<body>
</body>
</html>
3.2 新建数据表格
我们需要通过表格展示项目信息,所以新建数据表格如下:
<table id="mainTable" title="项目列表" class="easyui-datagrid"
url="CoreServlet?method=getProjectPage" pagination="true"
singleSelect="true">
<thead>
<tr>
<th data-options="field:'id'">序号</th>
<th data-options="field:'type'">类型</th>
<th data-options="field:'name'">名称</th>
<th data-options="field:'about'">简介</th>
</tr>
</thead>
</table>
这段代码很关键,我们来仔细解释下。
class="easyui-datagrid"
,说明当前的表格是easyui的datagrid组件,也就是数据表格。url="CoreServlet?method=getProjectPage"
,说明了数据表格请求的数据地址,注意当页面初始化,或者请求页码变化时,数据表格会主动再次请求url指向的地址,并将返回数据加载到表格中。pagination="true"
表示启用分页,启用分页后,每次请求url都会携带当前页码信息,默认会携带page=1 rows=10
给后端的Servlet,表示请求第一页,每页展示10行。singleSelect="true"
表示启用单选,每次只能选中1行数据。<th field="id">序号</th>
,这个很有意思,注意有一个field="id"
,也就是Servlet返回值中键为id的属性对应该列。
根据上面的描述,数据表格会自动请求url,而且还携带分页信息,最强大的是还会将返回数据根据列–属性对应关系显示到数据表格中。
这些动作都是datagrid自动完成的,不需要我们手写ajax方法请求url,然后根据返回值生成table的行。所以easyui是比较完整的封装,用起来比较方便。
4. 返回值封装
在之前的案例中,都是返回Result对象,code表示成功标识,data表示数据域。
但是EasyUI要求返回数据中必须包含total和rows,total表示数据总的条数,rows是数据的集合。EasyUI的数据表格会自动的去分析total和rows的值,然后计算出有多少页,将rows的值显示到数据表格中。
所以我们改造下Result对象,在分页的情况下,可以返回total和rows。注意rows由于可能是各种对象的集合,所以我们直接用T泛型来表示即可。
/**
* 统一返回结果类
*/
public class Result<T> {
/**
* 0成功 9999失败
*/
private int code;
/**
* 提示信息
*/
private String msg;
/**
* 返回数据
*/
private T data;
/**
* 分页总数
*/
private int total;
/**
* 分页数据
*/
private T rows;
// 省略get set
}
5. Servlet返回分页数据
这部分比较简单了,首先在Servlet中获取前端请求的页码page和每页展示行数rows。
public Result handleRequest(HttpServletRequest request) throws Exception {
Result result = new Result();
String method = request.getParameter("method");
// 请求页码、每页显示行数、总数
int page = 1, rows = 10, total = 0;
if (method.contains("Page") == true) {// 当前为分页请求
// 获取
String inputPage = request.getParameter("page");
String inputRows = request.getParameter("rows");
page = (inputPage == null) ? 1 : Integer.parseInt(inputPage);
rows = (inputRows == null) ? 10 : Integer.parseInt(inputRows);
}
// ......省略部分不相关代码
// 获取项目分页
else if (method.equals("getProjectPage")) {
ProjectDao projectDao = new ProjectDao();
total = projectDao.getCount();
result.setTotal(total);
result.setRows(projectDao.getPage(page, rows));
}
return result;
}
此处解释下:
if (method.contains("Page") == true) {
,分页请求时url中都含有Page字样,便于我们后端判断是否分页请求。total = projectDao.getCount();
,封装一个方法返回项目的总数量。projectDao.getPage(page, rows)
,封装一个方法,根据页码和每页显示个数返回对应的数据库记录。
6. 封装数据库方法
就是获取条数和指定页记录的方法。
/**
* 获取数量
*/
public int getCount() throws Exception {
Connection conn = ConnectionUtils.getConnection();
String sql = "select count(id) from project ";
QueryRunner runner = new QueryRunner();
Number number = (Number) runner.query(conn, sql, new ScalarHandler());
int value = number.intValue();
ConnectionUtils.releaseConnection(conn);
return value;
}
/**
* 分页查询
*/
public List<Project> getPage(int page, int rows) throws Exception {
Connection conn = ConnectionUtils.getConnection();
String sql = "select * from project limit ?,?";
QueryRunner runner = new QueryRunner();
Object[] params = { (page - 1) * rows, rows };
List<Project> projects = runner.query(conn, sql, new BeanListHandler<Project>(Project.class), params);
ConnectionUtils.releaseConnection(conn);
return projects;
}
7. 测试
样式有点丑,我们添加下fitColumns
属性让列适应宽度,然后设置下列的宽度比例:
<table id="mainTable" title="项目列表" class="easyui-datagrid" url="CoreServlet?method=getProjectPage" pagination="true"
singleSelect="true" fitColumns="true">
<thead>
<tr>
<th data-options="field:'id',width:50">序号</th>
<th data-options="field:'type',width:50">类型</th>
<th data-options="field:'name',width:50">名称</th>
<th data-options="field:'about',width:100">简介</th>
</tr>
</thead>
</table>
最终效果如下,大功告成: