手动实现SSM分页逻辑

第一种方法:查询出所有数据再分页

分析:

  1. 分页时,需要获得前台传来的两个参数,分别为pageNo(第几页数据),pageSize(每页的条数);
  2. 根据这两个参数来计算出前端需要的数据是查出数据list中的开始索引和结束索引;
  3. 利用List 的subList方法来分割查询出来的所有数据并返回;

实现过程

1. 获取参数

这里返回的是json数据接口,实现方法在service层

1
2
3
4
5
6
7
@ResponseBody
@GetMapping("/allPage")
public String findAllPage(
@RequestParam(required = true,defaultValue = "1") Integer pageNo,
@RequestParam(required = false,defaultValue = "5") Integer pageSize) {
return customerService.findAllPage(pageNo,pageSize);
}

2. 截取数据

CustomerServiceImpl.java

  • 里面的pageUtil类,iterCustomer()方法,JsonUtil类在下面有所介绍,抽离这些类或者方法的目的是提高代码的复用性,减少代码冗余;
1
2
3
4
5
6
7
8
9
10
@Override
public String findAllPage(Integer pageNo, Integer pageSize) {
List<Customer> customers = customerDao.findAll();
List<Map<String, String>> resultList = new ArrayList<>();
PageUtil<Customer> pageUtil = new PageUtil<>();
for (Customer customer : pageUtil.pageList(customers, pageNo, pageSize){
resultList.add(iterCustomer(customer));
}
return JsonUtil.toJSON(resultList);
}

==PageUtil.java==

  • 这个类是我抽取出来的一个截取List的工具类,创建对象时需要传一个泛型,类型为处理列表List中的类型;

  • 该类对象调用pageList方法即可返回一个截取好长度的List 数组;

  • pageList方法有三个参数,

    • 第一个参数为保存所有数据的List数组;
    • 第二个参数为页码;
    • 第三个参数为每一页显示的数据条数;
1
2
3
4
5
6
7
8
9
10
11
12
13
public class PageUtil<T> {
private int beginIndex;//起始索引
private int endIndex;//终止索引

public List<T> pageList(List<T> list, int pageNo, int pageSize) {
int size = list.size();

beginIndex = (pageNo - 1) * pageSize;
endIndex = pageNo * pageSize > size ? size : pageNo * pageSize;
List<T> resultList = list.subList(beginIndex, endIndex);
return resultList;
}
}

iterCustomer()方法

  • 作用是得到一个map存储一个Customer实例的值,用键值对表示;
  • 参数为需要包装的类对象;
  • 返回值为一个Map对象,里面存储了参数类对象的一些信息;
1
2
3
4
5
6
7
8
public Map<String, String> iterCustomer(Customer customer) {
Map<String, String> resultMap = new HashMap<>();
resultMap.put("id", customer.getId().toString());
resultMap.put("name", customer.getName());
resultMap.put("phone", customer.getPhone());
resultMap.put("email", customer.getEmail());
return resultMap;
}

JsonUtil.java

  • 作用是封装Jackson,返回一个json字符串;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class JsonUtil {
//使用jackson 转换 json 数据的第一步
private static ObjectMapper MAPPER = new ObjectMapper();
static String jsonString=null;

public static String toJSON(Object object){
try {
//jackson转任意object对象 为json 字符串
jsonString = MAPPER.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonString;
}
}

第二种方法:用SQL分页,只查询当前页所需要的数据

分析:

  • 第一种方法在数据量比较小时可以使用,但当数据量非常大时,如果我们仅需要某一页的几条数据,而去查找所有数据,显得没有必要,或者说代价太大,所有我们现在采用第二种分页方式;

  • 第二种方法与第一种类似,获取前端传来的页码和每页显示的条数,通过自定义SQL语句查询数据库来得到需要的数据;

  • sql分页参考:

    Mysql复杂查询

    【MySQL】条件查询之排序聚合分组分页查询

实现过程

1. 获取参数

分析

  • 参数中,pageNo是前端传来的页码,即第几页;pageSize是每一页要显示的条数,默认为5;
  • 使用SQL分页时,查询语句中需要的参数为显示数据在数据库中的索引和每页显示的数据条目数;
    • 计算索引的公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数;
  • 在这里还要判断一下前端传来的页码数是否超出总数据最大的分页数,如果超出则显示最大页数;
    • 最大页数计算:int maxPage =(int) Math.ceil(count/pageSize.doubleValue());

CustomerController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Controller
public class CustomerController {
@Autowired
CustomerService customerService;

@ResponseBody
@GetMapping("/allSql")
public String findAllPageSql(
@RequestParam(required = true,defaultValue = "1") Integer pageNo,
@RequestParam(required = false,defaultValue = "5") Integer pageSize) {
/**
* pageSize 是每页显示的条数
* pageNo 是页码,sql分页传递的第一个参数是开始的索引;
* 计算公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
*/
//数据总数
int count = customerService.count();
//计算最大页码
int maxPage =(int) Math.ceil(count/pageSize.doubleValue());
//当前页码超出最大页码返回最大页码值:
pageNo = pageNo>maxPage?maxPage:pageNo;
//分页开始的索引值
int index = (pageNo - 1) * pageSize > count ? count : (pageNo - 1) * pageSize;
return customerService.findAllPageSql(index, pageSize);
}
}

2.分层调用方法

CustomerServiceImpl.java

1
2
3
4
5
6
7
8
9
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
CustomerDao customerDao;
@Override
public String findAllPageSql(Integer index, Integer pageSize) {
return JsonUtil.toJSON(customerDao.findAllPageSql(index, pageSize));
}
}

CustomerDao.java

1
2
3
public interface CustomerDao {   
List<Customer> findAllPageSql(Integer index,Integer pageSize);
}

3.定制sql

CustomerMapper.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vue.dao.CustomerDao">
<select id="findAllPageSql" parameterType="java.lang.Integer" resultType="com.vue.entity.Customer">
SELECT * FROM t_customer LIMIT #{param1},#{param2}
</select>
</mapper>

Mapper.xml映射文件获取多个参数参考:

Mybatis中的Mapper.xml映射文件sql查询接收多个参数

Mybatis中的Mapper.xml映射文件sql查询接收多个参数


以上

  • 以上就是SSM框架不用PageHelper插件实现分页的全过程,推荐使用第二种定制SQL查询,因为此种查询方法更加符合分页逻辑的实现,每次只查询需要的数据,而不是每次都要查询所有数据,故效率更高。
  • 有问题可以一起交流: