开发者社区> 沉默王二> 正文

DataTables的服务器端(SpringMVC)分页模式

简介: 版权声明:欢迎转载,请注明沉默王二原创。 https://blog.csdn.net/qing_gee/article/details/82285030 Datatables是一款jquery表格插件。
+关注继续查看
版权声明:欢迎转载,请注明沉默王二原创。 https://blog.csdn.net/qing_gee/article/details/82285030

Datatables是一款jquery表格插件。它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能。

分页,即时搜索和排序
几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理
支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation
各式各样的扩展: Editor, TableTools, FixedColumns ……
丰富多样的option和强大的API
支持国际化
免费开源 ( MIT license )! 商业支持

因此这一款非常值得推荐的表格插件。今天借此机会我们来记录一下使用服务器端(SpringMVC)分页的方法。

首先,来看客户端的JavaScript代码:

var self_order_table = $("#self_order_table").DataTable({
            "processing": true,
            "serverSide": true,
            "paging": true,
            language : QINGE._set.table_language,
             "ajax": {
                   "url": CONFIG.mec_datable.index + "otm/order/list?p=self",
                   "type": "POST",
                   "data": function (d) {
                      //删除多余请求参数
                      for(var key in d){
                          if(key.indexOf("columns")==0||key.indexOf("order")==0||key.indexOf("search")==0){ //以columns开头的参数删除
                              delete d[key];
                          }
                      }
                      var searchParams= {
                              page : d.start == 0 ? 1 : (d.start/d.length + 1),
                              rows : d.length,
                       };
                      //附加查询参数
                      if(searchParams){
                          $.extend(d,searchParams); //给d扩展参数
                      }
                   },
                   "dataType" : "json",
                   "dataFilter": function (response) {//json是服务器端返回的数据
                       var json = QINGE.jsonEval(response);

                        if (json[QINGE.keys.statusCode] == QINGE.statusCode.error) {
                            if (json[QINGE.keys.message])
                                $.showErr(json[QINGE.keys.message]);
                        } else {
                               var returnData = {};
                               returnData.draw = json.result.vo.mo.draw;
                               returnData.recordsTotal = json.result.count;//返回数据全部记录
                               returnData.recordsFiltered = json.result.count;//后台不实现过滤功能,每次查询均视作全部结果
                               returnData.data = json.result.list;//返回的数据列表
                               return JSON.stringify(returnData);//这几个参数都是datatable需要的,必须要
                        }

                   }
               },
            deferRender : true,
            "scrollX" : true,
            scrollCollapse : true,
            fixedColumns : {
                leftColumns : 1,
            },
            "columnDefs" : [
                    {
                        targets : 0,
                        data : "scode",
                        title : "商品",
                        render : function(data, type, row) {
                            return "</div><div style='color: #676b6e;font-size: 10px; '>" + row.scode + "</div>";
                        }
                    }, {
                        targets : 1,
                        "data" : "order_count",
                        title : "委托量",
                    }, {
                        targets : 2,
                        "data" : "chengjiao_count",
                        title : "成交量",
                    }, {
                        targets : 3,
                        "data" : "order_price",
                        title : "委托价",
                    } ],
            "rowCallback" : function(row, data, index) {
            },
        });

需要注意的内容就是,如果使用服务器端分页,需要开启:

"processing": true,
"serverSide": true,
"paging": true,

然后借助ajax选项来定制发往服务器端的分页参数和服务器端返回的分页参数,先来看分页请求参数:

   "data": function (d) {
  //删除多余请求参数
  for(var key in d){
      if(key.indexOf("columns")==0||key.indexOf("order")==0||key.indexOf("search")==0){ //以columns开头的参数删除
          delete d[key];
      }
  }
  var searchParams= {
          page : d.start == 0 ? 1 : (d.start/d.length + 1),
          rows : d.length,
   };
  //附加查询参数
  if(searchParams){
      $.extend(d,searchParams); //给d扩展参数
      }
   },

其中page为第几页,rows为一页显示多少行,这两个是必须参数。这个时候,发往服务器端的参数都有哪一些呢?看下图。

这里写图片描述

①、其中draw是DataTables一个必须参数,是记录第几次分页的一个关键参数,服务器端还需要返回。
②、通过start和length参数可以计算出当前请求是第几页,比如说上图中的start为40,length为10,即page等于5(计算公式为:d.start == 0 ? 1 : (d.start/d.length + 1)
③、rows和length是相同的,只不过本次我们的SpringMVC端只认rows,不认length,所以需要转换一下。

再来看服务器端返回的数据处理,此时需要用到Ajax的dataFilter:

"dataFilter": function (response) {//json是服务器端返回的数据
 var json = QINGE.jsonEval(response);

if (json[QINGE.keys.statusCode] == QINGE.statusCode.error) {
    if (json[QINGE.keys.message])
        $.showErr(json[QINGE.keys.message]);
    } else {
        var returnData = {};
          returnData.draw = json.result.vo.mo.draw;
          returnData.recordsTotal = json.result.count;//返回数据全部记录
          returnData.recordsFiltered = json.result.count;//后台不实现过滤功能,每次查询均视作全部结果
          returnData.data = json.result.list;//返回的数据列表
          return JSON.stringify(returnData);//这几个参数都是datatable需要的,必须要
    }
}

服务器端返回的是json字符串,因此可以通过jsonEval函数来转换成json对象。然后从中取出datatables需要的关键数据:

var returnData = {};
returnData.draw = json.result.vo.mo.draw;
returnData.recordsTotal = json.result.count;//返回数据全部记录
returnData.recordsFiltered = json.result.count;//后台不实现过滤功能,每次查询均视作全部结果
returnData.data = json.result.list;//返回的数据列表
return JSON.stringify(returnData);//这几个参数都是datatable需要的,必须要

QINGE.jsonEval(response)函数的具体内容如下:

jsonEval : function(data) {
    try {
        if ($.type(data) == 'string')
            return eval('(' + data + ')');
        else
            return data;
    } catch (e) {
        return {};
    }
},

这样的话,针对客户端传递到服务器端的参数和接收服务器端返回的数据就处理完成了,接下来我们来看Java端(也就是SpringMVC)来如何接收分页请求和响应分页数据。

首先来看controller:

@SuppressWarnings({ "rawtypes", "unchecked" })
@RequestMapping(value = "list")
public void list(HttpServletResponse response) {
    Map result = new HashMap();

    // 获取列表参数
    BaseConditionVO vo = getBaseConditionVOForTable();
    vo.addParams("uid", InfoEL.getMemberUid());

    String p = getPara("p", "trade");
    if ("self".equals(p)) {
        result.put("vo", vo);
        result.put("count", selfOrderService.countTotal(vo));
        result.put("list", selfOrderService.getList(vo, vo.createRowBounds()));
        renderJsonDone(response, result);
    }
}

其中BaseConditionVO 为分页的请求参数,里面包含如下属性:

public static int PAGE_SHOW_COUNT = 50;// 默认一页为50行
private int pageNum = 1;//第几页
private int numPerPage = 0;// 一页显示多少行数据
private long totalCount = 0;// 总页数
private String orderField = "";// 排序字段
private String orderDirection = "";// 排序方式

/**
 * @Fields ps : 对参数类型进行封装,同时方便存储其他参数
 */
private Map<String, Object> mo = new HashMap<String, Object>();

其中renderJsonDone为返回json字符串的方法:

    private void renderJson(HttpServletResponse response, String jsonText) {
        PrintWriter writer = null;
        try {
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);

            response.setContentType(contentType);
            writer = response.getWriter();
            writer.write(jsonText);
            writer.flush();
        } catch (IOException e) {
            throw new OrderException(e.getMessage());
        } finally {
            if (writer != null)
                writer.close();
        }
    }

    protected void renderJsonDone(HttpServletResponse response, final Object value) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("statusCode", 200);
        map.put("result", value);
        String jsonText = JSON.toJSONString(map);

        renderJson(response, jsonText);
    }

那么,SpringMVC是怎么分页的呢?关键方法就在:

result.put("count", selfOrderService.countTotal(vo));// 计算总页数
result.put("list", selfOrderService.getList(vo, vo.createRowBounds()));// 获取分页

对于SpringMVC来说,其强大的集成功能就在于此,我们只需要按照这种方式将RowBounds:vo.createRowBounds()对象传递给Mybatis,Mybatis就会自己帮我们处理好分页,我们并不需要关注分页的具体细节。
先来来看Mybatis的处理:

    <!--列 -->
    <sql id="Base_Column_List">
        so.*
    </sql>

    <sql id="queryJoins">
    </sql>

    <sql id="Base4List">
        from otm_self_order so
        <include refid="queryJoins"/>
        where so.del_flag = 0
        <if test="mo.status != null">
            and so.status = #{mo.status}
        </if>
        <if test="mo.uid != null">
            and so.uid = #{mo.uid}
        </if>
        <if test="mo.cancel != null">
            and so.cancel = #{mo.cancel}
        </if>
    </sql>

    <select id="getList" resultMap="BaseResultMap" parameterType="map">
        select
        <include refid="Base_Column_List" />
        <include refid="Base4List" />
        <choose>
            <when test="orderField !=null and orderField !=''">
                ORDER BY ${orderField}
                <if test="orderDirection != null and orderDirection != ''">${orderDirection}</if>
            </when>
            <otherwise>
                order by so.update_date DESC
            </otherwise>
        </choose>
    </select>

    <select id="countTotal" resultType="java.lang.Integer" parameterType="map">
        select
            count(0)
        <include refid="Base4List" />
    </select>

好了,说完了客户端和服务器端的处理细节,我们来看一下具体的服务器端返回数据形式,通过Chrome浏览器的network面板就可以观察到,如下图:

这里写图片描述

另外,分页的效果图如下:

这里写图片描述

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
IDEA创建maven项目过慢,一直卡在resolving dependencies...的解决办法
作为一个从事 Java 开发的程序员,每天离不开ide的帮助。一开始学习java的时候基本都是使用eclipse进行开发, 后来接触了idea,发现是真的香,比eclipse好用太多了,能够大大提升开发的效率。
5 0
Gradle Logging
日志是构建工具的主要“ UI”。 如果太冗长,那么真正的警告和问题很容易被隐藏起来。 另一方面,你需要相关的信息来判断事情是否出了问题。 Gradle 定义了6个日志级别,如日志级别所示。 除了通常可以看到的日志级别之外,还有两个 gradle 特定的日志级别。 这些层次是安静和生命周期。 后者是默认的,用于报告构建进度。
4 0
Gradle Writing Build Scripts
The Gradle build language Gradle 构建语言 Gradle 提供了一种领域特定语言(DSL)来描述构建,这种构建语言在 Groovy 和 Kotlin 都可以使用。 Groovy 构建脚本可以包含任何 Groovy 语言元素。 Kotlin 构建脚本可以包含任何 Kotlin 语言元素。 Gradle 假设每个构建脚本都使用 UTF-8进行编码。
4 0
RocketMQ入门级使用演示-3
RocketMQ入门级使用演示-3
3 0
RocketMQ入门级使用演示-5
RocketMQ入门级使用演示-5
3 0
从零开始学设计模式(四):工厂模式(Factory Pattern)
工厂模式(Factory Pattern)也是 Java中最常用的设计模式之一。这种类型的设计模式也属于创建型模式,它提供了一种创建对象的最佳方式。
3 0
Gradle Authoring Tasks
在入门教程中,您学习了如何创建简单的任务。 稍后您还学习了如何向这些任务添加额外的行为,并学习了如何在任务之间创建依赖关系。 这一切都是关于简单的任务,但 Gradle 把任务的概念更进一步。 Gradle 支持增强型任务,这些任务具有自己的属性和方法。 这与您习惯使用 Ant 目标的情况大不相同。 这些强化的任务要么是你提供的,要么是内置在 Gradle 的。
3 0
Gradle 构建脚本基础(introductory tutorial)
Projects and tasks 项目和任务 每个 Gradle 构建都由一个或多个项目组成。 一个项目代表什么取决于你在 Gradle 上做什么。 例如,一个项目可能表示一个库 JAR 或一个 web 应用程序。 它可以表示从其他项目生成的 jar 组装起来的发行版 ZIP。 一个项目并不一定代表要构建的东西。 它可能代表要做的事情,比如将应用程序部署到登台或生产环境。 不要担心,如果这看起来有点含糊现在。 Gradle 的按惯例构建支持为项目增加了一个更具体的定义。
5 0
从零开始学设计模式(六):适配器模式(Adapter Pattern)
前面的几篇文章分别介绍了设计模式中的创建型设计模式,它们分别是:
5 0
+关注
沉默王二
微信搜索「沉默王二」,回复关键字「00」获取硬核计算机基础资料。
1084
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载
http://www.vxiaotou.com