摘要:本篇文章主要讲解的何使用Spring boot AOP
+自定义注解+PageHelper
来实现无侵入式的分页。传统的分页方式需要我们手动在每个接口中使用重复性的分页代码,这显然是不够明智的选择。相关AOP
的内容可参考之前的文章,本文仅介绍使用自定义注解与Spring boot AOP
完成分页处理的具体步骤。
常用分页问题
使用PageHelper
分页工具的一般步骤如下:
- 编写一个查询
sql
,一般定义到mapper
中; - 编写一个分页查询方法,设置PageHelper的当前页和页大小;
- 执行查询语句;
- 查询完成后把
PageInfo
的数据填充到自定义的PageBean
中。
示例代码如下:
public PageBean<ReportTemplate> selectPage(PageBean<User> page) {
// 通过PageHelper设置当前页和页大小
PageHelper.startPage(page.getPageNo(), page.getPageSize());
PageHelper.orderBy(page.getSortedField());
List<User> users= userMapper.selectList(page.getKeyWords());
PageInfo<User> pageInfo = new PageInfo<>(users);
page.setCount(pageInfo.getTotal());
page.setList(pageInfo.getList());
return page;
}
分析以上步骤我们可以发现,除了第一步我们需要手动编写SQL
查询语句,其他都是重复步骤。如果能将其封装成一个注解来使用,就会非常简单和优雅,因此需要结合Spring boot AOP
来实现。
AOP 分页处理
实现步骤总结如下:
- 引入相关依赖
pagehelper-spring-boot-starter
和spring-boot-starter-aop
。 - 定义
@Page
注解; - 定义
PageVo
分页参数; - 定义
PageAspect
分页切面。
引入相关依赖pagehelper-spring-boot-starter
和spring-boot-starter-aop
:
<!--MyBatis分页插件starter-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-starter.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义@Page
注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Page {
/**
* 用于绑定的请求参数名字
*/
String value() default "";
}
定义PageVo
分页参数:
/**
* 分页参数
**/
public class PageVo implements Serializable{
private static final long serialVersionUID = -1305720016123712695L;
// 当前页
private String pageNum;
// 每页显示条数
private String pageSize;
// 查询参数
private Map<String, Object> parameters = new HashMap<>(10);
// 排序参数
private Map<String, Object> sort = new HashMap<>(10);
public String getPageNum() {
return pageNum;
}
public void setPageNum(String pageNum) {
this.pageNum = pageNum;
}
public String getPageSize() {
return pageSize;
}
public void setPageSize(String pageSize) {
this.pageSize = pageSize;
}
public Map<String, Object> getParameters() {
return parameters;
}
public void setParameters(Map<String, Object> parameters) {
this.parameters = parameters;
}
public Map<String, Object> getSort() {
return sort;
}
public void setSort(Map<String, Object> sort) {
this.sort = sort;
}
}
定义PageAspect
分页切面:
/**
* 分页处理切面
**/
@Aspect
@Component
@Order(1)
public class PageAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Pointcut("@annotation(com.xxx.annotation.Page)")
public void page() {
}
@Around("page()")
public Object processPage(ProceedingJoinPoint jp) throws java.lang.Throwable {
// 获取目标方法原始的调用参数
Object[] args = jp.getArgs();
PageVo pageVo = new PageVo();
if (args != null && args.length > 0 && args[0] instanceof PageVo) {
// 修改目标方法的第一个参数
pageVo = (PageVo) args[0];
logger.info("当前页为:{},每页{}条数据", pageVo.getPageNum(), pageVo.getPageSize());
logger.info("查询条件为:{}", pageVo.getParameters());
}
logger.info("执行查询===");
// 以改变后的参数去执行目标方法,并保存目标方法执行后的返回值
Object result = null;
try {
PageHelper.clearPage();
if (pageVo != null && pageVo.getPageNum() != null) {
PageHelper.startPage(Integer.parseInt(pageVo.getPageNum()), Integer.parseInt(pageVo.getPageSize())).setReasonable(false);
}
result = jp.proceed(args);
logger.info("查询结束===");
// 如果result的类型是list,并且参数类型为pageVo,将result初始化到分页中
if (result != null && result instanceof List && args[0] instanceof PageVo) {
ArrayList resultList = (ArrayList) result;
logger.info("返回查询结果size={}", resultList.size());
PageInfo<Object> pageInfo = new PageInfo<Object>(resultList);
logger.info("pageInfo={},pageDataSize={}", pageInfo.getList(), pageInfo.getPageSize());
// 将pageInfo中多余的参数去除掉
ReturnInfo info = new ReturnInfo();
info.setStatus(ReturnState.SUCCESS);
info.setMessage("");
Map<String, Object> page = Maps.newHashMap();
page.put("totalCount", pageInfo.getTotal());
page.put("pageSize", pageInfo.getPageSize());
page.put("currentPage", pageInfo.getPageNum());
page.put("totalPage", pageInfo.getPages());
info.setReturnData(pageInfo.getList());
info.setPageInfo(page);
return info;
}
return result;
} finally {
logger.info("清除PageInfo的分页查询");
PageHelper.clearPage();
}
}
}
使用示例:
public Object listTransferMarket(PageVo pageVo) {
logger.info("listTransferMarket para:{}", JSON.toJSONString(pageVo));
return this.newProductTransferRecordManager.getTransferMarketListManager(pageVo);
}
@Page
public Object getTransferMarketListManager(PageVo pageVo) {
List<Map<String, Object>> list = this.newProductTransferRecordMapper.getTransferMarketList(pageVo);
return list;
}
List<Map<String,Object>> getTransferMarketList(@Param("pageVo") PageVo pageVo);