动态代理使用分页插件PageHelper

版权声明:柠檬乐园:200145783 https://blog.csdn.net/u014431237/article/details/82532662

本来只是研究一下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;
}

血案到此结束!

猜你喜欢

转载自blog.csdn.net/u014431237/article/details/82532662