1. 原理: 无非就是基于mybaits插件机制,拦截执行过程中某个阶段(Executor, StatementHandler, ParamterStatementHander,ResultSetHandler), 获取到待执行SQL, 利用反射对SQL重新赋值 (拼接上分页参数); 

2. SQL触发执行是在 StatementHandler阶段,故这里对StatementHandler拦截 (具体原因,自行看源码  从 Executor #query()方法debug)

2. 上代码

 1 /**
 2  * @author yangxj
 3  * @date 2021/6/4-23:21
 4  */
 5 @Slf4j
 6 @Component
 7 @Intercepts({@Signature(type = StatementHandler.class, method = "prepare",args = {Connection.class, Integer.class})})
 8 public class PageHelper implements Interceptor {
 9 
10     private static final ThreadLocal<Page> localCache = new ThreadLocal<>();
11 
12     @Override
13     public Object intercept(Invocation invocation) throws Throwable {
14         StatementHandler stm = (StatementHandler) invocation.getTarget();
15 
16         BoundSql boundSql = stm.getBoundSql();
17 
18         Page page = getPage(); // 取到分页参数
19 
20         if (page != null) {
21             Field SQLField = BoundSql.class.getDeclaredField("sql");   // 利用反射对SQL重新赋值
22             SQLField.setAccessible(true);
23             SQLField.set(boundSql, page.getPageSQL(boundSql.getSql()));
24             clearPage(); // 用完清空分页参数
25         }
26 
27         log.info("待执行SQL: " + boundSql.getSql().replaceAll("\\n", "").replaceAll("\\t", ""));
28 
29         return invocation.proceed();
30     }
31 
32     @Override
33     public Object plugin(Object o) {
34         return o instanceof StatementHandler ? Plugin.wrap(o, this) : o;
35     }
36 
37     @Override
38     public void setProperties(Properties properties) {
39 
40     }
41 
42 
43     public  static void startPage(Long pageNum, Long pageSize) {
44         localCache.set(new Page(pageNum, pageSize));
45     }
46 
47     private Page getPage() {
48         return localCache.get();
49     }
50 
51     private void clearPage() {
52         localCache.remove();
53     }
54 
55     private static class Page {
56         private Long pageNum;
57         private Long pageSize;
58 
59         private Page(Long pageNum, Long pageSize) {
60             this.pageNum = pageNum;
61             this.pageSize = pageSize;
62         }
63 
64         private String getPageSQL(String SQL) {
65             if (pageNum != null && pageSize != null) {
66                 return SQL + " limit " + (pageNum - 1) * pageSize + " ," + pageSize;
67             }
68             return SQL;
69         }
70     }
71 }

 

posted on 2021-06-05 10:37  yang希军  阅读(294)  评论(0)    收藏  举报