Java版本: jdk1.8
运行环境: Mac OS
IDE: IDEA
一 知识储备
1. PageHelper
PageHelper是Mybatis的一款分页插件,利用ThreadLocal实现分页功能。PageHelper先是根据你即将发出的SQL命令获取count值(也就是数据总量),然后获取当前线程上的线程变量进行分页操作。
2. AOP
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待…。
一 AOP的基本概念
- Aspect(切面):通常是一个类,里面可以定义切入点和通知
- JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
- Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
二 代码思路
- 为什么要使用AOP技术来进行PageHelper分页,先来看一个普通的PageHelper分页方法
/**
* @param page 当前页
* @param pageSize 每页数量
* @return
*/
public PageInfo<User> findUserListWithPage(int page,int pageSize){
//pageHelper帮助生成分页语句
//底层实现 采用改写语句
PageHelper.startPage(page,pageSize);
List<User> userList = userMapper.findUserList();
PageInfo<User> userListPageInfo = new PageInfo<>(users);
return userListPageInfo;
}
不难发现 PageHelper常用的分页方法逻辑代码就是
1. 用PageHelper设置 从第n页开始查,每页x条数据
2. 执行Dao(Mapper)层方法
3. 将查询结果用PageInfo类包装返回
当方法较少的时候不会有太多的感觉,但如果要写好几百个方法分页查询的方法,每个方法的代码都按照这个逻辑来来写,就会显得代码冗余。
在这个执行逻辑中可以看出 只要给了page
和pageSize
参数,第1步和第3步是不变的,会变的只是第2步。于是乎就有了使用AOP技术来将第1步和第3步抽出来,减少代码量。
三 技术实现
已知model层
public class User {
private Integer id;
private String name;
private Integer age;
}
Dao(Mapper)层
public interface UserMapper {
@Select("select * from user")
List<User> findUserList();
}
Service层的写法是关键,根据是否使用AOP技术有不同的实现.
Controller层
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findUserList")
public Object findUserList(int page, int pageSize){
return userService.findUserList();
}
}
–
在不使用aop时进行pageHelper分页操作时,Service层代码如下
–
@Service
public class UserService {
@Autowired
UserMapper userMapper;
/**
* @param page 当前页
* @param pageSize 每页数量
* @return
*/
public PageInfo<User> findUserListWithPage(int page,int pageSize){
//pageHelper帮助生成分页语句
//底层实现 采用改写语句
PageHelper.startPage(page,pageSize);
List<User> userList = userMapper.findUserList();
PageInfo<User> userListPageInfo = new PageInfo<>(users);
return userListPageInfo;
}
}
–
使用aop技术进行pageHelper分页操作时,Service层代码如下
–
@Service
@Slf4j
public class UserService {
@Autowired
UserMapper userMapper;
/**
*
* @param page 当前页
* @param pageSize 每页数量
* @return
*/
public Object findUserListWithPage(int page ,int pageSize){
List<User> userList = userMapper.findUserList();
return userList;
}
}
–
AOP层 PageHelperAspect代码
–
/**
* @author hyl
* @date 18/12/18 下午10:38
*/
@Aspect
@Component
@Slf4j
public class PageHelperAspect {
@Pointcut("execution(public * com.bootbase.service.*.*WithPage(..))")
public void serviceFindFunction(){}
/**
* 使用around方法 在执行查询方法前执行PageHelper.startWith
* 在执行查询方法后 将结果封装到PageInfo中
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("serviceFindFunction()")
public Object serviceImplAop(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
log.info("进入PageHelper AOP");
//获取连接点方法运行时的入参列表
Object[] args = proceedingJoinPoint.getArgs();
//获取连接点的方法签名对象
Signature signature = proceedingJoinPoint.getSignature();
//获取连接点所在的类的对象(实例)
Object target = proceedingJoinPoint.getTarget();
PageHelper.startPage(Integer.parseInt(args[0].toString()),Integer.parseInt(args[1].toString()));
log.info("方法[{}]开始执行...",signature.getName());
Object object = proceedingJoinPoint.proceed();
log.info("方法[{}]执行结束.",signature.getName());
if(object instanceof List) {
List objList = (List) object;
PageInfo pageInfo = new PageInfo<>(objList);
return pageInfo;
}
return object;
}
}
四 结语
以上就是使用AOP进行PageHelper分页的全部内容.其内容本身与springboot2.0无充分必要关系,只不过在springboot2.0中 可以省略AOP配置文件的编写 (说白了就是懒