简易版 DataTable.js 服务端分页(Java)
引入 js 和 css 文件
可以直接到官网首页,找到下面图片的位置,点击右边的小箭头按钮,你会看到对应的 css 和 js 源码,然后 ctrl+A 把源码复制下来,自己新建个文件存放,再引入到 html 中就行。
实现原理
dataTable 实现服务端的分页,主要是通过 AJAX 异步请求。先在 js 配置中开启了服务端分页的功能 “serverSide: true”,然后 dataTable 会传指定参数给后台去进行分页操作,然后返回指定参数给前台的 dataTable,dataTable 就会自动渲染表格数据并实现分页。
dataTable 传给服务端的三个必须分页参数:
sEcho:dataTable 用于本身计算次数的,接收等会直接返回即可,不需要作处理。
iDisplayStart:表示从第几行开始查询,比如第一页的话,标识从第 0 行开始查数据,与 mysql 的 limit 的第一个参数吻合,可直接使用,在 Java 代码会介绍到。
iDisplayLength:表示查询多少条,dataTable 默认最少是查询 10 条。
服务端返回给 dataTable 的三个必须分页参数:
draw:将 dataTable 传过来的 sEcho 原封不动赋值给他就行。
recordsTotal:总数据量
recordsFiltered:总数据量
data:返回的数据列表
导入对应的文件
html 代码
<table class="table-sort" >
<thead>
<tr class="text-c">
<th width="25"><input type="checkbox" name="" value="" id="allCheck"></th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
</tr>
</thead>
<tbody></tbody>
</table>
js 代码
代码比较清晰简单,该有的注释都有了。比较需要注意的是:fnServerParams
,这个参数。是用来设置自定义参数的,比如:你实现了搜索框,搜索框内输入的值要传到后台,就得再 fnServerParams
里面设置过去。
注意:
fnServerParams 参数是用来添加自定义传给后台的参数的。
比如:我们实现搜索功能的时候,也希望将搜索的信息列表能够分页展示出来,这时就需要将 “搜索条件” 通过 fnServerParams 来 push 进去 aoData 中,然后传给后台。
<script type="text/javascript">
$(function(){
$('.table-sort').dataTable({
bProcessing: true, //DataTables 载入数据时,是否显示‘进度’提示
bAutoWidth: false, //自动宽度
bSort: false, //排序功能
bInfo: true, //页脚信息,默认为 true
bStateSave: true, //状态保存
sPaginationType: "full_numbers", //分页显示样式
serverSide: true, //启用服务器分页
sAjaxSource: "http://localhost:8080/user/list", //服务端请求数据接口
searching: false, //关闭 datatables 的搜索框
destroy: true, //解决重新渲染问题
iDisplayLength: 10, //每页显示数量
// 自定义参数
fnServerParams: function(aoData){
aoData.push(
{
name: "nickname",
value: "dongdong"
}
);
},
// post 方法提交
fnServerData: function(sSource,aoData,fnCallback){
$.ajax({
type: 'post',
url: sSource,
dataType: 'json',
data: aoData,
success: function (res) {
fnCallback(res);
}
});
},
aoColumns:[
// mDataProp:绑定数据属性
// sDefaultContent:设置默认值
// sClass:添加 class 属性,不懂的直接去掉
// sTtile:设置列标题
// sWidth:设置列宽度
// mRender:添加 html 代码或者自定义的值
// 更多关于 aoColumns 的参数请查看下面的附件
{
mDataProp:"id",
mRender: function(mDataProp,type,row){
var html = '<td width="25" class="text-c"><input type="checkbox" value="' + mDataProp + '"></td> ';
return html;
}
},
// sTtile 设置的内容,会替换到 html thead 中的“标题”
{mDataProp:"id", sDefaultContent:"", sClass:"text-c", sTitle:"编号"},
{mDataProp:"city", sDefaultContent:"", sClass:"text-c", sTitle:"城市"},
{mDataProp:"avatarUrl", sDefaultContent:"", sClass:"text-c", sTitle:"头像",sWidth:200},
{mDataProp:"jobIntention", sDefaultContent:"", sClass:"text-c", sTitle:"标签"},
{mDataProp:"nickName",sDefaultContent:"", sClass:"text-c", sTitle:"微信暱称"},
{mDataProp:"openid",sDefaultContent:"", sClass:"text-c", sTitle:"openID"},
{mDataProp:"province",sDefaultContent:"", sClass:"text-c", sTitle:"省份"},
{mDataProp:"state",sDefaultContent:"", sClass:"text-c", sTitle:"状态"}
],
oLanguage: { //国际化配置
sProcessing : "正在获取数据,请稍后...",
sLengthMenu : "显示 _MENU_ 条",
sZeroRecords : "没有您要搜索的内容",
sInfo : "从 _START_ 到 _END_ 条记录 总记录数为 _TOTAL_ 条",
sInfoEmpty : "记录数为0",
sInfoFiltered : "(全部记录数 _MAX_ 条)",
sInfoPostFix : "",
sSearch : "从当前数据中检索: ",
sUrl : "",
oPaginate: {
sFirst : "首页",
sPrevious : "上一页",
sNext : "下一页",
sLast : "尾页"
}
}
});
});
</script>
Java 代码
import com.google.gson.Gson;
@RequestMapping(value = "/user/list")
@ResponseBody
public String userList(Integer sEcho, Integer iDisplayStart, Integer iDisplayLength,
String nickname, ModelMap modelMap){
User query = new User();
List<User> list = userService.queryUser(query,PageParams.build(iDisplayStart,iDisplayLength));
Integer count = userService.getPageCount();
System.out.println(nickname);
modelMap.put("draw",sEcho);
modelMap.put("recordsTotal",5);
modelMap.put("recordsFiltered",50);
modelMap.put("data", list); //返回查询的数据列表
Gosn gson = new Gson();
return gson.toJson(modelMap);
// return JsonUtils.Object2Json(sEcho,count,list);
//这是我自己对数据进行了封装,封装的类放在后面的附录,如果看不懂可以不用,直接用上面 modelMap 这种形式返回也一样
}
sEcho,iDisplayStart,iDisplayLength:前台传过来的分页参数。
nickname:前台传过来的自定义参数
iDisplayStart 表示从第几行开始查,iDisplayLength 表示查询多少条,dataTable 传过来的分页参数,跟 mysql 的 limit 需要的分页参数是完全吻合的。我们不需要进行数据处理,直接使用即可。如下面:
select *
from user
limit iDisplayStart,iDisplayLength
draw,recordsTotal,recordsFiltered,data:这几个返回给前端的数据名称不能写错,不然会对接不上。还有,dataTable 要求返回的是 json 格式的数据,这里不采用原生的 JsonObject 写,而是使用 Google 的一个工具类 Gson 来将数据转成 Json 格式的数据。使用方法如下,注意:com.google.gson 包是要自己导入的。
select *
from user
limit iDisplayStart,iDisplayLength
后台返回的 json 数据格式为:
页面效果图:
另外一种写法:
上面介绍的是用 fnServerData
进行异步获取数据,我们也能直接使用 ajax 来开发。把下面的这段代码删掉。
// 自定义参数
fnServerParams: function(aoData){
aoData.push(
{
name: "nickname",
value: "dongdong"
}
);
},
// post 方法提交
fnServerData: function(sSource,aoData,fnCallback){
$.ajax({
type: 'post',
url: sSource,
dataType: 'json',
data: aoData,
success: function (res) {
fnCallback(res);
}
});
},
换成下面这段代码:
ajax:{
url: "http://localhost:8080/user/list",
type: "POST",
contentType: "application/x-www-form-urlencoded",
async: false,
dataType: "json",
data: function(data){
data.name = "dongdong";
}
dataFilter: function(json){
return json;
}
}
两种写法的区别在于:直接使用 ajax ,dataTables 传递给后台的参数不一样。
fnServerData 传给后台的参数:sEcho、iDisplayStart、iDisplayLength
ajax 传给后台的参数:draw、start、length
后台接收的参数如下:
@RequestMapping(value = "/user/list")
public String userList(Integer draw,Integer start, Integer length,String name){
System.out.println("draw:"+draw);
System.out.println("start:"+start);
System.out.println("length:"+length);
System.out.println("name:"+name);
}
附录(个人笔记)
JsonUtils.java
import com.google.gson.Gson;
import com.zwd.house.common.page.PageData;
import java.util.List;
public class JsonUtils<T> {
private static Gson gson = new Gson();
public static <T> String Object2Json(Integer sEcho, Integer count, List<T> list) {
PageData<T> pageData = PageData.buildPage(sEcho,count,list);
return gson.toJson(pageData);
}
}
PageParams.java
public class PageParams {
private static final Integer PAGE_SIZE = 0;
private Integer offset; // 从第 offset+1 行开始检索
private Integer limit; // 检索条数
public static PageParams build(Integer offset, Integer limit){
if (offset == null){
offset = 0;
}
if (limit == null){
limit = PAGE_SIZE;
}
return new PageParams(offset, limit);
}
public PageParams(){
this(PAGE_SIZE, 1);
}
public PageParams(Integer offset, Integer limit){
this.offset = offset;
this.limit = limit;
}
// get and set
}
PageData.java
import java.util.List;
public class PageData<T> {
// 下面的用来封装数据的参数名都不能变,需要与 dataTables 对应
private Integer draw; //前台传过来的 sEcho 原封返回
private Integer recordsTotal; //存放总条数
private Integer recordsFiltered; //存放总条数
private List<T> data;
public PageData(Integer draw,Integer recordsTotal,Integer recordsFiltered,List<T> data){
this.draw = draw;
this.recordsTotal = recordsTotal;
this.recordsFiltered = recordsFiltered;
this.data = data;
}
public static <T> PageData<T> buildPage(Integer draw, Integer total,List<T> data){
return new PageData<>(draw,total,total,data);
}
//get adn set
}