自定义注解,更优雅的使用MP分页功能
分页功能使用
MP的分页功能是通过MyBatis的插件实现的,使用起来也非常简单。下面先介绍下使用方式。
step1:配置分页插件
@Configuration
@EnableTransactionManagement
@MapperScan("com.csx.demo.spring.boot.dao")
public class MyBatisPlusConfig {
private static final Logger log = LoggerFactory.getLogger(MyBatisPlusConfig.class);
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 如果是单数据源的话,最好制定数据库类型,不然的话MP需要根据数据库连接来推断数据库类型
// 性能上略有损失
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
需要注意的是:MP提供了很多开箱即用的插件,这些插件的使用顺序有讲究。官方文档建议的配置顺序是:
目前已有的功能:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
注意:
使用多个功能需要注意顺序关系,建议使用如下顺序
多租户,动态表名
分页,乐观锁
sql性能规范,防止全表更新与删除
总结: 对sql进行单次改造的优先放入,不对sql进行改造的最后放入
step2:写分页代码
IPage<User> page = new Page<>(1,10);
((Page<User>) page).addOrder(OrderItem.desc("user_id"));
IPage<User> userIPage = userDAO.selectPage(page, null);
自定义注解,更优雅的使用MP分页功能
我们发现:虽然MP的分页插件使用起来非常简单,但是还是需要每次从参数中拿分页参数、排序参数等,代码看起来还是略微显得冗余。
这边定义了一个自定义注解,可以简化上面的这些操作。下面是实现的代码。
step1:定义自己的PageInfo
说明下:这边的PageInfo是可以不定义的,你可以直接使用MP的IPage实现。但是个人具有洁癖,有些信息不想返回前端,所以定义了一个精简的PageInfo.
/**
* 自定义的PageInfo
* 内容比MP中的IPage精简
* @param <T>
*/
public class PageInfo<T> {
private Integer pageNo;
private Integer pageSize;
private String sortColumn;
private Long total;
private List<T> rows;
public PageInfo(Integer pageNo, Integer pageSize, String sortColumn) {
this.pageNo = pageNo;
this.pageSize = pageSize;
this.sortColumn = sortColumn;
}
// 省略get和set方法
}
step2:定义分页注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Pagination {
// 可以自定义分页字段名称,当前页字段名称默认是pageNO
String pageNoField() default "pageNo";
// 可以自定义分页字段名称,每页数量名称默认是pageNO
String pageSizeField() default "pageSize";
// 可以自定义分页字段名称,排序字段名称默认是pageNO
String sortField() default "sort";
// 也可以通过注解指定排序字段
String sortItem() default "";
}
step3:注解处理类
@Aspect
@Component
public class PaginationHandler {
private static final Logger log = LoggerFactory.getLogger(PaginationHandler.class);
private static final int DEFAULT_PAGE_NO = 1;
private static final int DEFAULT_PAGE_SIZE = 10;
@Around("@annotation(pagination)&&args(pageParam)")
public Object handlePagination(ProceedingJoinPoint point,
Pagination pagination,
Object pageParam) throws Throwable {
int pageNo = DEFAULT_PAGE_NO;
int pageSize = DEFAULT_PAGE_SIZE;
String sortCols;
String pageNoField = pagination.pageNoField();
String pageSizeField = pagination.pageSizeField();
String sortField = pagination.sortField();
sortCols = pagination.sortItem();
if (pageParam == null) {
PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
PageUtil.setPageInfo(pageInfo);
} else {
if (pageParam instanceof Map) {
Map<String, Object> param = (Map<String, Object>) pageParam;
JSONObject json = new JSONObject(param);
if (json.getInteger(pageNoField) != null) {
pageNo = json.getIntValue(pageNoField);
}
if (json.getInteger(pageSizeField) != null) {
pageSize = json.getIntValue(pageSizeField);
}
if (json.getInteger(sortField) != null) {
sortCols = json.getString(sortField);
}
PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
PageUtil.setPageInfo(pageInfo);
} else {
// 暂时只支持Map类型的参数
// 如果需要支持其他类型的参数,可以在这边添加
PageInfo pageInfo = new PageInfo(pageNo, pageSize, sortCols);
PageUtil.setPageInfo(pageInfo);
}
}
try {
Object result = point.proceed();
if (result instanceof Response) {
Object data = ((Response) result).getData();
if(data instanceof IPage){
long total = ((IPage) data).getTotal();
List records = ((IPage) data).getRecords();
PageInfo pageInfo = PageUtil.getPageInfo();
pageInfo.setTotal(total);
pageInfo.setRows(records);
((Response) result).setData(pageInfo);
}
return result;
} else {
// Todo 暂时没想到好的处理方法
return result;
}
} finally {
PageUtil.removePageInfo();
}
}
}
step4:分页工具
public class PageUtil {
private static final String ASC = "asc";
private static final String DESC = "desc";
private static final Logger log = LoggerFactory.getLogger(PageUtil.class);
private static final ThreadLocal<PageInfo> pageInfoHolder = new ThreadLocal<>();
public static void setPageInfo(PageInfo pageInfo) {
pageInfoHolder.set(pageInfo);
}
public static void removePageInfo() {
pageInfoHolder.remove();
}
public static PageInfo getPageInfo() {
return pageInfoHolder.get();
}
public static <T> IPage<T> page() {
PageInfo pageInfo = getPageInfo();
Integer pageNo = pageInfo.getPageNo();
Integer pageSize = pageInfo.getPageSize();
//col1:aes,col2:des形式
String sortCols = pageInfo.getSortColumn();
IPage<T> iPage = new Page<>(pageNo, pageSize);
if (!StringUtils.isEmpty(sortCols)) {
String[] split = sortCols.split(",");
for (String s : split) {
try {
int index = s.lastIndexOf(':');
String col = s.substring(0, index);
String sortType = s.substring(index, s.length());
if(ASC.equalsIgnoreCase(sortCols)){
((Page<T>) iPage).addOrder(OrderItem.asc(col));
} else if (DESC.equalsIgnoreCase(sortType)){
((Page<T>) iPage).addOrder(OrderItem.desc(col));
} else {
log.warn("sort col {} is invalid, ignore it...",s);
continue;
}
} catch (Exception e) {
log.warn("sort col {} is invalid, ignore it...",s);
}
}
}
return iPage;
}
}
step5:使用
@PostMapping("/page")
@Pagination
public Object info(@RequestBody Map param) {
IPage<User> page = userService.page(PageUtil.page(), null);
Response response = new Response();
response.success().success().setData(page);
return response;
}
上面的代码比较简单,具体就不分析了。
自定义注解,更优雅的使用MP分页功能的更多相关文章
- 手写SpringBoot自动配置及自定义注解搭配Aop,实现升级版@Value()功能
背景 项目中为了统一管理项目的配置,比如接口地址,操作类别等信息,需要一个统一的配置管理中心,类似nacos. 我根据项目的需求写了一套分布式配置中心,测试无误后,改为单体应用并耦合到项目中.项目中使 ...
- ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存
基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...
- 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- 用大白话聊聊JavaSE -- 自定义注解入门
注解在JavaSE中算是比较高级的一种用法了,为什么要学习注解,我想大概有以下几个原因: 1. 可以更深层次地学习Java,理解Java的思想. 2. 有了注解的基础,能够方便阅读各种框架的源码,比如 ...
- java中自定义注解的应用
要想深刻的理解注解,我们必须能实现自己的注解,然后应用自己的注解去实现特定的业务,使用注解可以更优雅的做到某些事情. 有这样一个场景,在需要文件导出时,我们需要将一个model中的一些重要字段导出到c ...
- SpringBoot系列(十三)统一日志处理,logback+slf4j AOP+自定义注解,走起!
往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件详解 SpringBoot系列(四)we ...
- Spring中如何使用自定义注解搭配@Import引入内外部配置并完成某一功能的启用
文章背景 有一个封装 RocketMq 的 client 的需求,用来提供给各项目收.发消息,但是项目当中常常只使用收或者发消息的单一功能,而且不同的项目 group 等并不相同而且不会变化,可以在项 ...
- 如何通过自定义注解实现AOP切点定义
面向切面编程(Aspect Oriented Programming, AOP)是面向对象编程(Object Oriented Programming,OOP)的强大补充,通过横切面注入的方式引入其他 ...
- 使用 Promises 编写更优雅的 JavaScript 代码
你可能已经无意中听说过 Promises,很多人都在讨论它,使用它,但你不知道为什么它们如此特别.难道你不能使用回调么?有什么了特别的?在本文中,我们一起来看看 Promises 是什么以及如何使用它 ...
随机推荐
- 【Alpha冲刺阶段】Scrum Meeting Daily5
[Alpha冲刺阶段]Scrum Meeting Daily5 1.会议简述 会议开展时间 2020/5/27 8:30-9:00 PM 会议基本内容摘要 大家讲述了自己的任务完成情况以及遇到的问题 ...
- Java设计模式(一)——单例模式
简介 定义: 确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例. 单例类拥有一个私有构造函数,确保用户无法通过 new 来直接实例化它.类中包含一个静态私有成员变量与静态公有的工厂方法, ...
- linux文件实时同步
参考博客:https://www.cnblogs.com/MacoLee/p/5633650.html 一.文件同步很简单 服务端:被动的接收传输过来的数据 客户端:主动提供数据给服务端 安装思路:服 ...
- docker redis 设置和使用
1 开启docker 拉取redis镜像 1.1 桌面版docker 在镜像所在位置命令行执行 docker load -i redis.tar 1.2 开启redis docker run -p ...
- mysql 5.7升级8.0
升级前准备: [root@node01 ~]# mysql -V mysql Ver 14.14 Distrib 5.7.25, for linux-glibc2.12 (x86_64) using ...
- MobaXterm无法退格删除
MobaXterm退格删除出现^H,总是要取消输入重新敲语句,很麻烦 解决方法:打开MobaXterm-->settings-->Configuration,把"Backspac ...
- 在win7下安装texlive
首先到texlive官网下载texlive2017.iso 然后解压,找到install-tl-advanced.bat,用管理员权限双击,安装,关闭杀毒软件. 基本选择默认,前面路径可以按自己需求更 ...
- 记录一次mac访问Windows共享目录失败
一,起因 起因,有人联系我说他们的mac电脑连接不上Windows的共享目录,Windows的电脑连接正常,没有报错,连接框抖两下就没了 二,排查问题 1,我自己想mstsc登陆服务器看看,结果服务器 ...
- Shiro实现Basic认证
前言 今天跟小伙伴们分享一个实战内容,使用Spring Boot+Shiro实现一个简单的Http认证. 场景是这样的,我们平时的工作中可能会对外提供一些接口,如果这些接口不做一些安全认证,什么人都可 ...
- 线段树入门详解,洛谷P3372 【模板】线段树 1
关于线段树: 本随笔参考例题 P3372 [模板]线段树 1 所谓线段树就是把一串数组拆分成一个一个线段形成的一棵树. 比如说像这样的一个数组1,2,3,4,5: 1 ~ 5 / ...