本来只是研究一下Total的值,后面越陷越深!
数据查询到html发现没有总数!!!一开始想着Total应该是查的数据总数,但是测试几遍发现,返回的是当前分页的总条数,这显然不是我想要的,然后发现了PageInfo的继承类PageSerializable下的初始化方法:

很显然,如果我们传实例不是属于Page,那么就会把list.size()复制给total;
Page page = PageHelper.startPage(page,pageSize);
//数据查询语句。。。 返回的List
//数据包装类等等....
PageInfo pageInfo = new PageInfo<>(你自己的list);
//需要赋值下
pageInfo.setTotal(sqlpage.getTotal());
这个分页插件前后执行的都是一样的代码,很显然这个分页方法应该提取出来。然后我写了一个A方法,查询出List,调用A方法。呃呃,居然没有分页,而是查询了所有数据。一开始对分页理解不够,查询语句必须要再中间执行。
既然前后代码一样的就可用动态代理来写。
主要代码
JDK 代理方式:
public class PageProxy implements InvocationHandler {
private Object object;
public PageProxy(Object object) {
this.object = object;
}
public Object getinfoimpl() {
//初始值
ClassLoader classLoader = this.object.getClass().getClassLoader();
Class<?>[] cs = this.object.getClass().getInterfaces();
return Proxy.newProxyInstance(this.object.getClass().getClassLoader(), cs, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//用来获取总数,如果说数据不进行传输类转换 可以直接返回 page
Page sqlpage = PageHelper.startPage((int)args[0],(int)args[1]);
//执行方法返回的list
List objlist= (List) method.invoke(object, args);
PageInfo pageInfo = new PageInfo<>(objlist);
//设置总页
pageInfo.setTotal(sqlpage.getTotal());
return pageInfo;
}
}
AOP 注解方式:
@Component
@Aspect
public class PagingAop {
@Pointcut("execution(* com.lemon.sell.service.impl.*.select*(..))")
public void pointCut() {
}
@Around("pointCut()")
public Object doAround(ProceedingJoinPoint pj) {
//获取参数 page sieze 分页
Object[] args = pj.getArgs();
Page sqlpage = PageHelper.startPage((int) args[0], (int) args[1]);
Object ret = null;
try {
//这里应该返回 传输类的list集合
ret = pj.proceed(args);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
//强转为List 实际返回值为PageInfo的实例对象
PageInfo pageInfo = new PageInfo<>((List)ret);
//设置总页
pageInfo.setTotal(sqlpage.getTotal());
return pageInfo;
}
}
其他动态代理方式,自行研究。
最终我选择AOP注解方式的动态代理(代码少)。发现被代理的方法返回值必须是Object(需要修改返回值,返回List给代理类处理,返回Pageinfo给Controller层)。
那么我Controller层返回是Object类型,需要强转,每次在Controller层强转一个Object类型很难看啊。
我想着直接在Service层进行强转,例如:
//这是被代理的方法
public Object B(int page,int size){
//查询数据库返回 list数据
List list = .....;
return list;
}
//这是Controller层调用的方法
public PageInfo C(int page,int size){
//调用被代理的方法
PageInfo pageInfo = (PageInfo)B(page,size);
return pageInfo;
}
我兴致勃勃的去测试,丫的!AOP根本没有拦截。然后以为自己的execution路径配置有问题(建议拦截某个接口方法)。检查了几遍,发现类的内部调用自个方法,根本不会被拦截。详细查看:AOP 不拦截内部方法原因 (另外几种方法,自行了解)
直接通过上下文获取bean来调用方法,而不直接从方法内部调用。
//启动类
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(App.class, args);
SpringContextUtil.setApplicationContext(applicationContext);
}
}
public class SpringContextUtil {
private static ApplicationContext applicationContext;
//获取上下文
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//设置上下文
public static void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
//通过名字获取上下文中的bean
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
//通过类型获取上下文中的bean
public static Object getBean(Class<?> requiredType) {
return applicationContext.getBean(requiredType);
}
}
修改后这样就可以正常拦截了
//因为内部调用 其他方法 是不会被Aop拦截的 所以内部要通过获取bean来调用
private XXXServiceImpl getService() {
return (XXXServiceImpl) SpringContextUtil.getBean(this.getClass());
}
//这是被代理的方法
public Object B(int page,int size){
//查询数据库返回 list数据
List list = .....;
return list;
}
//这是Controller层调用的方法
public PageInfo C(int page,int size){
//调用被代理的方法
PageInfo pageInfo = (PageInfo)getService.B(page,size);
return pageInfo;
}
血案到此结束!