最近再写一个后台管理项目的时候,对于某个字段的模糊查询加上借助pagehelper插件的分页功能时,产生了网页持续刷新的情况,此时客户端向服务端不断地发送大量请求,对于服务器安全有较大的威胁。
一、问题起源在使用MyBatis进行数据库操作时,为了图方便使用了Example类,其中有一段涉及到分页的查询代码如下:
@Override public PageInfogetCourseListByPage(SearchVo searchVo) { CourseExample example = new CourseExample(); CourseExample.Criteria criteria = example.createCriteria(); if (null != searchVo.getKeyword() && "" != searchVo.getKeyword()) criteria.andCourseNameLike("%" + searchVo.getKeyword() + "%"); PageHelper.startPage(searchVo.getPageNum(), searchVo.getPageSize()); List courses = courseMapper.selectByExample(example); PageInfo info = new PageInfo<>(courses); return info; }
在SearchVo中只有三个属性,当前页pageNum、每页大小pageSize以及模糊查询时使用的关键字keyword,模糊查询的关键字通过搜索框输入并提交。
如上图,当输入的模糊查询字段不存在匹配的对象时,查询出的集合理所当然是一个空集合,这个时候如果用pagehelper分页,前端页面便会不断地刷新,不断地请求服务端,而服务端也不停地进行数据库访问操作。
1.URL书写错误导致循环请求
一开始对于该问题我以为是前端页面与Controller层的请求循环转发的原因,于是不断的查找每一个URL,经过多次比对后,算是确定URL并没有出现问题。
2.Example类使用不当
由于Example类平时开发时使用较少,所以存在不确定因子,于是怀疑可能是Example类的问题。于是修改了Service层代码,采用自己手写Mapper来进行模糊查询。
Mapper:
Service:
@Override public PageInfogetCourseListByPage(SearchVo searchVo) { PageHelper.startPage(searchVo.getPageNum(), searchVo.getPageSize()); List courses = courseMapper.findAllCourse(searchVo); PageInfo info = new PageInfo<>(courses); return info; }
再次进行查询,结果和之前一样,当提交的keyword无法匹配到任何一条记录时,pagehelper执行的SQL语句返回的集合为空时,网页依旧频繁的不断刷新,不断向服务器发起请求。
三、结论综合上述测试,个人认为该问题是Pagehelper的一个缺陷,在使用pagehelper插件时,如果在PageHelper.startPage()函数后面紧跟的SQL语句查询的结果集为空集时,浏览器会不断的循环发起请求。
四、解决方案对于该问题,目前我个人在网上搜索和官网查询都没有发现有相似的问题分享以及解决方案。对于这个问题的解决,最希望的是在pagehelper插件的源码中加上对查询结果集为空时的处理方案,这样是最好的。
但对于只是临时需要组织该问题造成的对服务器进行大量请求的行为,那么可以对SQL查询的结果集进行一次判断,让其绕过PageInfo例如通过全局异常处理来反馈错误信息。简单示例代码如下:
@Override public PageInfogetCourseListByPage(SearchVo searchVo) throws Exception { PageHelper.startPage(searchVo.getPageNum(), searchVo.getPageSize()); List courses = courseMapper.findAllCourse(searchVo); if (courses.size() > 0) { PageInfo info = new PageInfo<>(courses); return info; } else { throw new Exception("查无此结果!"); } }
如果有不对的地方欢迎指正,插件本身如果有原生的解决方案望各位指导!



