我们通过一个需求来引入问题。
首先,简单介绍一下需求:实现一个下图的页面,包含了过滤以及分页。数据是后台数据库获得到的。
那么关于如何实现过滤以及分页,考虑到通过前台实现或者后台实现,我们不妨来分析一下两种方法。
首先,前台实现:无非就是后台获取所有的list,传给前台暂存,然后前台按照用户的过滤或者分页,来处理list,展示给前台。
后台实现:前台要什么过滤,要第几页,我们就返回什么list。
那么在我看来,前台实现劣势有三:
1. 传输问题:现在开发过程数据库中的案例数很少,十几个案例没啥问题。可是当数据库中案例数增加后,几百甚至几千条的数据同时传输,传输速率肯定有所降低,前台加载一个页面可能要很久,用户体验极差。
2. 内存占用问题:同样是 当数据量过大时,不论后台还是前台,都需要一大片空间来存储,占据大量内存。其中又有很多是暂时用不上的数据,造成资源浪费。
3. 时效性问题:我们举个例子,按照后台一次性获取所有案例给前台,而这个获取过程可能是通过外部的一个点击事件触发,如果此时有用户对案例进行了修改,那么不论是翻页还是过滤,都看不出来用户的修改。而如果每次过滤或者翻页都是即时的从后台获取,就可以保证每次过滤或者分页都是最新的内容。
当然这只是我所认为分析出来的前台实现劣势,如果有什么前台的优化方法还请指出:)
====================================================================
所以接下来我们就考虑利用后台来进行实现,那么思考一下,前台告诉我们对哪些字段进行过滤,进行怎样的分页(每页有几个案例,第几页),然后我们根据这些参数来实现过滤或者分页。
最直接的方法,还是数据库直接获取所有案例,然后按照字段筛选,按照分页条件筛选。咦?直接获取的数据又不是我全都要,这样不还是占用了很多内存。那怎么办呢,我们不妨从数据库访问过程入手,通过sql来实现过滤分页呢。
那么就有了下面的方法: 关于过滤,前台传给我们一个包含过滤字段以及过滤字段关键字的json就可以啦,如下的<if></if>,判断对应字段是否存在,如果存在,那就利用like进行过滤。(代码使用Mybatis作为持久层框架,所以代码直接贴啦)
<select id="getCaseView" resultType="com.common.bean.CaseInfo">
select id, type, title, create_user as user, status
from t_tbl_case_info where
<choose>
<when test="tableBaseRequest.filter.viewType==0">
status = '3'
</when>
<when test="tableBaseRequest.filter.viewType==1">
status != '4' and create_user = #{curUser}
</when>
</choose>
<if test="tableBaseRequest.filter.title!=null">
and title like concat('%',#{tableBaseRequest.filter.title},'%')
</if>
<if test="tableBaseRequest.filter.type!=null">
and type in
<foreach collection="tableBaseRequest.filter.type" item="item"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="tableBaseRequest.filter.user!=null">
and user like concat('%',#{tableBaseRequest.filter.user},'%')
</if>
order by create_time desc
limit #{tableBaseRequest.offset}, #{tableBaseRequest.pageSize}
</select>
关于分页,可以看到实现在sql的最后,limit #{tableBaseRequest.offset}, #{tableBaseRequest.pageSize},使用limit即可,在一个经过计算的偏移量offset之后,选择 一页展示的数据,offset可以前台计算传到后台,也可以前台只传页码以及一页中案例数量 后台来计算。
tableBaseRequest.setOffset((tableBaseRequest.getCurPage() - 1) * tableBaseRequest.getPageSize())
如此一来,前台实现传递过滤字段以及过滤内容、页码以及每页条数,便可以完成通过sql来在后台实现过滤以及分页
附一下前台传递的参数,一个自定义类
public class TableBaseRequest
{
/**
* 表格分页信息,当前是第几页
*/
@Min(1)
@Max(Integer.MAX_VALUE)
private int curPage;
/**
* 表格分页信息,每页展示多少条数据
*/
@IntPattern(regexp = ValidatorConstants.TABLE_PAGESIZE_REGEXP)
private int pageSize;
/**
* 表格分页信息,查询数据库的偏移量
*/
private int offset;
/**
* 过滤参数 filter:{ "text":"XXX", "select":["0", "1"], "time":{"startTime":"2018-02-01 00:00:00", "endTime":
* "2018-02-02 23:59:59"} }
*/
private JSONObject filter;
/**
* 排序列,如不为空即需要对此字段进行排序
*/
@Length(max = 100)
private String sortName;
/**
* 排序类型,默认desc,枚举包括:增序asc或降序desc
*/
@Pattern(regexp = ValidatorConstants.TABLE_SORT_REGEXP)
private String sortValue;
}