diff --git a/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
index 4da6e212f4ad75d61816054abd04127e195268f5..57f87fcfe298b77dc99f8258f87282fc1fc2c8c6 100644
--- a/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
+++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -16,5 +16,9 @@ PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
-
+
+
+
+
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
index 2650fb7b2739be941f8c142d3fbdd37997bc404f..36b5489ee387d2f9a81aff5093b734ca4a422096 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
@@ -5,7 +5,7 @@ import com.ruoyi.common.utils.StringUtils;
/**
* sql操作工具类
- *
+ *
* @author ruoyi
*/
public class SqlUtil
diff --git a/ruoyi-middleware/pom.xml b/ruoyi-middleware/pom.xml
index 20f21403c8f57123f658cab69af8cdc12257821e..c6895ebe23ca6689af32cf1ebdce0e93a3ac2cd2 100644
--- a/ruoyi-middleware/pom.xml
+++ b/ruoyi-middleware/pom.xml
@@ -44,6 +44,7 @@
ruoyi-middleware-starter
${ruoyi.version}
+
@@ -52,6 +53,7 @@
ruoyi-middleware-minio
ruoyi-middleware-redis
ruoyi-middleware-starter
+
pom
-
\ No newline at end of file
+
diff --git a/ruoyi-middleware/ruoyi-middleware-starter/pom.xml b/ruoyi-middleware/ruoyi-middleware-starter/pom.xml
index 870ca1ecf23a33ec3f355423fedf55c6cf6e8c82..bb7eca4fa1ac4242cc262e4b071beec58fab7902 100644
--- a/ruoyi-middleware/ruoyi-middleware-starter/pom.xml
+++ b/ruoyi-middleware/ruoyi-middleware-starter/pom.xml
@@ -32,6 +32,7 @@
ruoyi-middleware-redis
+
diff --git a/ruoyi-plugins/pom.xml b/ruoyi-plugins/pom.xml
index 837a95a0b28640a969af2119c55f6375a1fb0a0f..f956740e6e8f214b7315c61c44e2b405ab40bdcd 100644
--- a/ruoyi-plugins/pom.xml
+++ b/ruoyi-plugins/pom.xml
@@ -80,6 +80,12 @@
ruoyi-plugins-starter
${ruoyi.version}
+
+ com.ruoyi
+ ruoyi-mybatis-interceptor
+ ${ruoyi.version}
+
+
@@ -90,6 +96,7 @@
ruoyi-mybatis-plus
ruoyi-websocket
ruoyi-plugins-starter
+ ruoyi-mybatis-interceptor
pom
-
\ No newline at end of file
+
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/pom.xml b/ruoyi-plugins/ruoyi-mybatis-interceptor/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d1386233fa727e73da96b5d19baa9e12bad9d8a
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/pom.xml
@@ -0,0 +1,31 @@
+
+
+
+ ruoyi-plugins
+ com.ruoyi
+ 3.8.8.3.1
+
+ 4.0.0
+
+ ruoyi-mybatis-interceptor
+
+
+ 19
+ 19
+ UTF-8
+
+
+
+ com.ruoyi
+ ruoyi-common
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/DataSecurity.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/DataSecurity.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae9f8e3f1e1a3e5fc7dfebc5fd5dd3b31b2e8d4b
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/DataSecurity.java
@@ -0,0 +1,16 @@
+package com.ruoyi.mybatisinterceptor.annotation;
+
+import com.ruoyi.mybatisinterceptor.enums.DataSecurityStrategy;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataSecurity {
+ public DataSecurityStrategy strategy() default DataSecurityStrategy.CREEATE_BY;
+
+ public String table() default "";
+
+ public String joinTableAlise() default "";
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/MybatisHandlerOrder.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/MybatisHandlerOrder.java
new file mode 100644
index 0000000000000000000000000000000000000000..e897354004559113a020562b7253ce824677bc54
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/annotation/MybatisHandlerOrder.java
@@ -0,0 +1,10 @@
+package com.ruoyi.mybatisinterceptor.annotation;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface MybatisHandlerOrder {
+ public int value() default 0;
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/aspectj/DataSecurityAspect.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/aspectj/DataSecurityAspect.java
new file mode 100644
index 0000000000000000000000000000000000000000..166b87fc862e52cd155bcf8a41120d91f860fd5f
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/aspectj/DataSecurityAspect.java
@@ -0,0 +1,82 @@
+package com.ruoyi.mybatisinterceptor.aspectj;
+
+import com.ruoyi.mybatisinterceptor.annotation.DataSecurity;
+import com.ruoyi.mybatisinterceptor.model.JoinTableModel;
+import com.ruoyi.mybatisinterceptor.model.WhereModel;
+import com.ruoyi.mybatisinterceptor.context.dataSecurity.SqlContextHolder;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+
+
+
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+
+@Aspect
+@Component
+public class DataSecurityAspect {
+
+ @Before(value = "@annotation(dataSecurity)")
+ public void doBefore(final JoinPoint point, DataSecurity dataSecurity) throws Throwable {
+ SqlContextHolder.startDataSecurity();
+ switch (dataSecurity.strategy()) {
+ case CREEATE_BY:
+ WhereModel createByModel = new WhereModel();
+ createByModel.setTable(dataSecurity.table());
+ createByModel.setValue("\"" + SecurityUtils.getUsername() + "\"");
+ createByModel.setWhereColumn("create_by");
+ createByModel.setMethod(WhereModel.METHOD_EQUAS);
+ createByModel.setConnectType(WhereModel.CONNECT_AND);
+ SqlContextHolder.addWhereParam(createByModel);
+ break;
+ case USER_ID:
+ WhereModel userIdModel = new WhereModel();
+ userIdModel.setTable(dataSecurity.table());
+ userIdModel.setTable("user_id");
+ userIdModel.setValue(SecurityUtils.getUserId());
+ userIdModel.setConnectType(WhereModel.CONNECT_AND);
+ userIdModel.setMethod(WhereModel.METHOD_EQUAS);
+ SqlContextHolder.addWhereParam(userIdModel);
+ break;
+ case JOINTABLE_CREATE_BY:
+ JoinTableModel createByTableModel = new JoinTableModel();
+ createByTableModel.setFromTable(dataSecurity.table());
+ createByTableModel.setFromTableAlise(dataSecurity.table());
+ createByTableModel.setJoinTable("sys_user");
+ if (!StringUtils.isEmpty(dataSecurity.joinTableAlise())) {
+ createByTableModel.setJoinTableAlise(dataSecurity.joinTableAlise());
+ }
+
+ createByTableModel.setFromTableColumn("create_by");
+ createByTableModel.setJoinTableColumn("user_name");
+ SqlContextHolder.addJoinTable(createByTableModel);
+ break;
+ case JOINTABLE_USER_ID:
+ JoinTableModel userIdTableModel = new JoinTableModel();
+ userIdTableModel.setFromTable(dataSecurity.table());
+ userIdTableModel.setFromTableAlise(dataSecurity.table());
+ userIdTableModel.setJoinTable("sys_user");
+ if (!StringUtils.isEmpty(dataSecurity.joinTableAlise())) {
+ userIdTableModel.setJoinTableAlise(dataSecurity.joinTableAlise());
+ }
+
+ userIdTableModel.setFromTableColumn("user_id");
+ userIdTableModel.setJoinTableColumn("user_id");
+ SqlContextHolder.addJoinTable(userIdTableModel);
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ @After(value = " @annotation(dataSecurity)")
+ public void doAfter(final JoinPoint point, DataSecurity dataSecurity) {
+ SqlContextHolder.clearCache();
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/dataSecurity/SqlContextHolder.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/dataSecurity/SqlContextHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..54407a68984526e28be6c5cb2660cf9643223afa
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/dataSecurity/SqlContextHolder.java
@@ -0,0 +1,45 @@
+package com.ruoyi.mybatisinterceptor.context.dataSecurity;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.mybatisinterceptor.enums.SqlType;
+import com.ruoyi.mybatisinterceptor.model.JoinTableModel;
+import com.ruoyi.mybatisinterceptor.model.WhereModel;
+
+public class SqlContextHolder {
+ private static final ThreadLocal SQL_CONTEXT_HOLDER = new ThreadLocal<>();
+
+ public static void startDataSecurity() {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("isSecurity", Boolean.TRUE);
+ jsonObject.put(SqlType.WHERE.getSqlType(), new JSONArray());
+ jsonObject.put(SqlType.JOIN.getSqlType(), new JSONArray());
+ SQL_CONTEXT_HOLDER.set(jsonObject);
+ }
+
+ public static void addWhereParam(WhereModel whereModel) {
+ SQL_CONTEXT_HOLDER.get().getJSONArray(SqlType.WHERE.getSqlType()).add(whereModel);
+ }
+
+ public static void clearCache() {
+ SQL_CONTEXT_HOLDER.remove();
+ }
+
+ public static boolean isSecurity() {
+
+ return SQL_CONTEXT_HOLDER.get() != null
+ && SQL_CONTEXT_HOLDER.get().getBooleanValue("isSecurity");
+ }
+
+ public static JSONArray getWhere() {
+ return SQL_CONTEXT_HOLDER.get().getJSONArray(SqlType.WHERE.getSqlType());
+ }
+
+ public static void addJoinTable(JoinTableModel joinTableModel) {
+ SQL_CONTEXT_HOLDER.get().getJSONArray(SqlType.JOIN.getSqlType()).add(joinTableModel);
+ }
+
+ public static JSONArray getJoinTables() {
+ return SQL_CONTEXT_HOLDER.get().getJSONArray(SqlType.JOIN.getSqlType());
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/PageContextHolder.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/PageContextHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..4eef6861ff5bb0a2886547730422ede060f4db16
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/PageContextHolder.java
@@ -0,0 +1,44 @@
+package com.ruoyi.mybatisinterceptor.context.page;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.mybatisinterceptor.context.page.model.PageInfo;
+
+public class PageContextHolder {
+ private static final ThreadLocal PAGE_CONTEXT_HOLDER = new ThreadLocal<>();
+
+ private static final String PAGE_FLAG = "isPage";
+
+ private static final String PAGE_INFO = "pageInfo";
+
+ private static final String TOTAL = "total";
+
+ public static void startPage() {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put(PAGE_FLAG, Boolean.TRUE);
+ PAGE_CONTEXT_HOLDER.set(jsonObject);
+ }
+
+ public static void setPageInfo() {
+ PAGE_CONTEXT_HOLDER.get().put(PAGE_INFO, PageInfo.defaultPageInfo());
+ }
+
+ public static PageInfo getPageInfo() {
+ return (PageInfo) PAGE_CONTEXT_HOLDER.get().get(PAGE_INFO);
+ }
+
+ public static void clear() {
+ PAGE_CONTEXT_HOLDER.remove();
+ }
+
+ public static boolean isPage() {
+ return PAGE_CONTEXT_HOLDER.get() != null && PAGE_CONTEXT_HOLDER.get().getBooleanValue(PAGE_FLAG);
+ }
+
+ public static void setTotal(Long total) {
+ PAGE_CONTEXT_HOLDER.get().put(TOTAL, total);
+ }
+
+ public static Long getTotal() {
+ return PAGE_CONTEXT_HOLDER.get().getLong(TOTAL);
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/PageInfo.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/PageInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0cd7a04763a3e9562720fa62232a86997846b45
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/PageInfo.java
@@ -0,0 +1,63 @@
+package com.ruoyi.mybatisinterceptor.context.page.model;
+
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ServletUtils;
+
+public class PageInfo {
+
+ private Long pageNumber;
+
+ private Long pageSize;
+
+ /**
+ * 当前记录起始索引
+ */
+ public static final String PAGE_NUM = "pageNum";
+
+ /**
+ * 每页显示记录数
+ */
+ public static final String PAGE_SIZE = "pageSize";
+
+ /**
+ * 排序列
+ */
+ public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+ /**
+ * 排序的方向 "desc" 或者 "asc".
+ */
+ public static final String IS_ASC = "isAsc";
+
+ /**
+ * 分页参数合理化
+ */
+ public static final String REASONABLE = "reasonable";
+
+ public Long getPageNumber() {
+ return pageNumber;
+ }
+
+ public void setPageNumber(Long pageNumber) {
+ this.pageNumber = pageNumber;
+ }
+
+ public Long getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(Long pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public static PageInfo defaultPageInfo() {
+ PageInfo pageInfo = new PageInfo();
+ pageInfo.setPageNumber(Long.valueOf(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1)));
+ pageInfo.setPageSize(Long.valueOf(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10)));
+ return pageInfo;
+ }
+
+ public Long getOffeset() {
+ return (pageNumber.longValue() - 1L) * pageSize;
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/RuoyiTableData.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/RuoyiTableData.java
new file mode 100644
index 0000000000000000000000000000000000000000..925c1fe5a33355c90e9ee1361230461f9ca992e7
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/RuoyiTableData.java
@@ -0,0 +1,25 @@
+package com.ruoyi.mybatisinterceptor.context.page.model;
+
+import java.util.List;
+
+public class RuoyiTableData {
+ private Long total;
+ private List> data;
+
+ public Long getTotal() {
+ return total;
+ }
+
+ public void setTotal(Long total) {
+ this.total = total;
+ }
+
+ public List> getData() {
+ return data;
+ }
+
+ public void setData(List> data) {
+ this.data = data;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/TableInfo.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/TableInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..b055a58f92b0d35017e6d903e0aeeefa715a3f63
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/context/page/model/TableInfo.java
@@ -0,0 +1,22 @@
+package com.ruoyi.mybatisinterceptor.context.page.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TableInfo extends ArrayList {
+
+ private Long total;
+
+ public TableInfo(List extends E> list) {
+ super(list);
+ }
+
+ public Long getTotal() {
+ return total;
+ }
+
+ public void setTotal(Long total) {
+ this.total = total;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/DataSecurityStrategy.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/DataSecurityStrategy.java
new file mode 100644
index 0000000000000000000000000000000000000000..16358c19ad143e7a9a817be81f53b305168d23be
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/DataSecurityStrategy.java
@@ -0,0 +1,8 @@
+package com.ruoyi.mybatisinterceptor.enums;
+
+public enum DataSecurityStrategy {
+ JOINTABLE_CREATE_BY,
+ JOINTABLE_USER_ID,
+ CREEATE_BY,
+ USER_ID;
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/SqlType.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/SqlType.java
new file mode 100644
index 0000000000000000000000000000000000000000..52af7d4c5a1c83821a629196268aa19502176143
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/enums/SqlType.java
@@ -0,0 +1,18 @@
+package com.ruoyi.mybatisinterceptor.enums;
+
+public enum SqlType {
+ WHERE("where"),
+ JOIN("join"),
+ SELECT("select"),
+ LIMIT("limit");
+
+ private String sqlType;
+
+ public String getSqlType() {
+ return sqlType;
+ }
+
+ private SqlType(String sqlType) {
+ this.sqlType = sqlType;
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/interceptor/mybatis/MybatisInterceptor.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/interceptor/mybatis/MybatisInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..179e1508846f80d6c75908e1fc13149d282ac1cf
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/interceptor/mybatis/MybatisInterceptor.java
@@ -0,0 +1,129 @@
+package com.ruoyi.mybatisinterceptor.interceptor.mybatis;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.ruoyi.mybatisinterceptor.annotation.MybatisHandlerOrder;
+import com.ruoyi.mybatisinterceptor.sql.MybatisAfterHandler;
+import com.ruoyi.mybatisinterceptor.sql.MybatisPreHandler;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.plugin.Intercepts;
+import org.apache.ibatis.plugin.Invocation;
+import org.apache.ibatis.plugin.Signature;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+
+import jakarta.annotation.PostConstruct;
+
+@Component
+@Intercepts({
+ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
+ RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class }),
+ @Signature(type = Executor.class, method = "query", args = {
+ MappedStatement.class, Object.class, RowBounds.class,
+ ResultHandler.class })
+
+})
+public class MybatisInterceptor implements Interceptor {
+
+ @Autowired
+ private List preHandlerBeans;
+
+ @Autowired
+ private List afterHandlerBeans;
+
+ private static List preHandlersChain;
+
+ private static List afterHandlersChain;
+
+ @PostConstruct
+ public void init() {
+ List sortedPreHandlers = preHandlerBeans.stream().sorted((item1, item2) -> {
+ int a;
+ int b;
+ MybatisHandlerOrder ann1 = item1.getClass().getAnnotation(MybatisHandlerOrder.class);
+ MybatisHandlerOrder ann2 = item2.getClass().getAnnotation(MybatisHandlerOrder.class);
+ if (ann1 == null) {
+ a = 0;
+ } else {
+ a = ann1.value();
+ }
+ if (ann2 == null) {
+ b = 0;
+ } else {
+ b = ann2.value();
+ }
+ return a - b;
+ }).collect(Collectors.toList());
+ preHandlersChain = sortedPreHandlers;
+
+ List sortedAfterHandlers = afterHandlerBeans.stream().sorted((item1, item2) -> {
+ int a;
+ int b;
+ MybatisHandlerOrder ann1 = item1.getClass().getAnnotation(MybatisHandlerOrder.class);
+ MybatisHandlerOrder ann2 = item2.getClass().getAnnotation(MybatisHandlerOrder.class);
+ if (ann1 == null) {
+ a = 0;
+ } else {
+ a = ann1.value();
+ }
+ if (ann2 == null) {
+ b = 0;
+ } else {
+ b = ann2.value();
+ }
+ return a - b;
+ }).collect(Collectors.toList());
+ afterHandlersChain = sortedAfterHandlers;
+ }
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ Executor targetExecutor = (Executor) invocation.getTarget();
+ Object[] args = invocation.getArgs();
+ if (args.length < 6) {
+ if (preHandlersChain != null && preHandlersChain.size() > 0) {
+ MappedStatement ms = (MappedStatement) args[0];
+ Object parameterObject = args[1];
+ RowBounds rowBounds = (RowBounds) args[2];
+ Executor executor = (Executor) invocation.getTarget();
+ BoundSql boundSql = ms.getBoundSql(parameterObject);
+ // 可以对参数做各种处理
+ CacheKey cacheKey = executor.createCacheKey(ms, parameterObject, rowBounds, boundSql);
+ for (MybatisPreHandler item : preHandlersChain) {
+ item.preHandle(targetExecutor, ms, args[1], (RowBounds) args[2],
+ (ResultHandler) args[3], cacheKey, boundSql);
+ }
+ }
+ Object result = invocation.proceed();
+ if (afterHandlersChain != null && afterHandlersChain.size() > 0) {
+ for (MybatisAfterHandler item : afterHandlersChain) {
+ item.handleObject(result);
+ }
+ }
+ return result;
+ }
+ if (preHandlersChain != null && preHandlersChain.size() > 0) {
+ for (MybatisPreHandler item : preHandlersChain) {
+ item.preHandle(targetExecutor, (MappedStatement) args[0], args[1], (RowBounds) args[2],
+ (ResultHandler) args[3], (CacheKey) args[4], (BoundSql) args[5]);
+ }
+ }
+ Object result = invocation.proceed();
+ if (afterHandlersChain != null && afterHandlersChain.size() > 0) {
+ for (MybatisAfterHandler item : afterHandlersChain) {
+ result = item.handleObject(result);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/JoinTableModel.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/JoinTableModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..50bd25d1d3ac6a10135745b387e7e6b64d2884ab
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/JoinTableModel.java
@@ -0,0 +1,85 @@
+package com.ruoyi.mybatisinterceptor.model;
+
+import com.ruoyi.common.utils.StringUtils;
+
+public class JoinTableModel {
+ private String joinTable;
+
+ private String joinTableAlise;
+
+ private String fromTable;
+
+ private String fromTableAlise;
+
+ private String joinTableColumn;
+
+ private String fromTableColumn;
+
+ public String getJoinTable() {
+ return joinTable;
+ }
+
+ public void setJoinTable(String joinTable) {
+ this.joinTable = joinTable;
+ }
+
+ public String getJoinTableAlise() {
+ if (StringUtils.isEmpty(this.joinTableAlise)) {
+ return this.joinTable;
+ }
+ return joinTableAlise;
+ }
+
+ public void setJoinTableAlise(String joinTableAlise) {
+
+ this.joinTableAlise = joinTableAlise;
+ }
+
+ public String getFromTable() {
+ return fromTable;
+ }
+
+ public void setFromTable(String fromTable) {
+ this.fromTable = fromTable;
+ }
+
+ public String getFromTableAlise() {
+ if (StringUtils.isEmpty(this.fromTableAlise)) {
+ return this.fromTable;
+ }
+ return fromTableAlise;
+ }
+
+ public void setFromTableAlise(String fromTableAlise) {
+ this.fromTableAlise = fromTableAlise;
+ }
+
+ public String getJoinTableColumn() {
+
+ return joinTableColumn;
+ }
+
+ public void setJoinTableColumn(String joinTableColumn) {
+ this.joinTableColumn = joinTableColumn;
+ }
+
+ public String getFromTableColumn() {
+ return fromTableColumn;
+ }
+
+ public void setFromTableColumn(String fromTableColumn) {
+ this.fromTableColumn = fromTableColumn;
+ }
+
+ public String getJoinTableColumnString() {
+ return this.getJoinTableAlise() + "." + this.joinTableColumn;
+ }
+
+ public String getFromTableColumnString() {
+ if (StringUtils.isEmpty(this.getFromTableAlise())) {
+ return this.fromTableColumn;
+ }
+ return this.getFromTableAlise() + "." + this.fromTableColumn;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/WhereModel.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/WhereModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..6456fb59b430be578f698219849a3ac9a73c46a8
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/model/WhereModel.java
@@ -0,0 +1,67 @@
+package com.ruoyi.mybatisinterceptor.model;
+
+import com.ruoyi.common.utils.StringUtils;
+
+public class WhereModel {
+ private String whereColumn;
+ private String table;
+ private Object value;
+ private String connectType;
+ private String method;
+
+ public static final String METHOD_EQUAS = "=";
+ public static final String METHOD_LIKE = "like";
+ public static final String CONNECT_AND = "AND";
+ public static final String CONNECT_OR = "OR";
+
+ public String getWhereColumn() {
+ return whereColumn;
+ }
+
+ public void setWhereColumn(String whereColumn) {
+ this.whereColumn = whereColumn;
+ }
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public String getFullTableColumn() {
+ if (StringUtils.isEmpty(this.table)) {
+ return this.whereColumn;
+ }
+ return this.table + "." + this.whereColumn;
+ }
+
+ public String getConnectType() {
+ return connectType;
+ }
+
+ public void setConnectType(String connectType) {
+ this.connectType = connectType;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String getSqlString() {
+ return String.format(" %s %s %s %s ", this.getConnectType(), this.getFullTableColumn(), this.method, this.value);
+ }
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/mybatis/MybatisInterceptor.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/mybatis/MybatisInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae7d0a3767640f3c0e2c3917bc2a2a0eb8596d8b
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/mybatis/MybatisInterceptor.java
@@ -0,0 +1,129 @@
+package com.ruoyi.mybatisinterceptor.mybatis;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.ruoyi.mybatisinterceptor.annotation.MybatisHandlerOrder;
+import com.ruoyi.mybatisinterceptor.sql.MybatisAfterHandler;
+import com.ruoyi.mybatisinterceptor.sql.MybatisPreHandler;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.plugin.Intercepts;
+import org.apache.ibatis.plugin.Invocation;
+import org.apache.ibatis.plugin.Signature;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+
+
+import jakarta.annotation.PostConstruct;
+
+@Component
+@Intercepts({
+ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
+ RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class }),
+ @Signature(type = Executor.class, method = "query", args = {
+ MappedStatement.class, Object.class, RowBounds.class,
+ ResultHandler.class })
+
+})
+public class MybatisInterceptor implements Interceptor {
+
+ @Autowired
+ private List preHandlerBeans;
+
+ @Autowired
+ private List afterHandlerBeans;
+
+ private static List preHandlersChain;
+
+ private static List afterHandlersChain;
+
+ @PostConstruct
+ public void init() {
+ List sortedPreHandlers = preHandlerBeans.stream().sorted((item1, item2) -> {
+ int a;
+ int b;
+ MybatisHandlerOrder ann1 = item1.getClass().getAnnotation(MybatisHandlerOrder.class);
+ MybatisHandlerOrder ann2 = item2.getClass().getAnnotation(MybatisHandlerOrder.class);
+ if (ann1 == null) {
+ a = 0;
+ } else {
+ a = ann1.value();
+ }
+ if (ann2 == null) {
+ b = 0;
+ } else {
+ b = ann2.value();
+ }
+ return a - b;
+ }).collect(Collectors.toList());
+ preHandlersChain = sortedPreHandlers;
+
+ List sortedAfterHandlers = afterHandlerBeans.stream().sorted((item1, item2) -> {
+ int a;
+ int b;
+ MybatisHandlerOrder ann1 = item1.getClass().getAnnotation(MybatisHandlerOrder.class);
+ MybatisHandlerOrder ann2 = item2.getClass().getAnnotation(MybatisHandlerOrder.class);
+ if (ann1 == null) {
+ a = 0;
+ } else {
+ a = ann1.value();
+ }
+ if (ann2 == null) {
+ b = 0;
+ } else {
+ b = ann2.value();
+ }
+ return a - b;
+ }).collect(Collectors.toList());
+ afterHandlersChain = sortedAfterHandlers;
+ }
+
+ @Override
+ public Object intercept(Invocation invocation) throws Throwable {
+ Executor targetExecutor = (Executor) invocation.getTarget();
+ Object[] args = invocation.getArgs();
+ if (args.length < 6) {
+ if (preHandlersChain != null && preHandlersChain.size() > 0) {
+ MappedStatement ms = (MappedStatement) args[0];
+ Object parameterObject = args[1];
+ RowBounds rowBounds = (RowBounds) args[2];
+ Executor executor = (Executor) invocation.getTarget();
+ BoundSql boundSql = ms.getBoundSql(parameterObject);
+ // 可以对参数做各种处理
+ CacheKey cacheKey = executor.createCacheKey(ms, parameterObject, rowBounds, boundSql);
+ for (MybatisPreHandler item : preHandlersChain) {
+ item.preHandle(targetExecutor, ms, args[1], (RowBounds) args[2],
+ (ResultHandler) args[3], cacheKey, boundSql);
+ }
+ }
+ Object result = invocation.proceed();
+ if (afterHandlersChain != null && afterHandlersChain.size() > 0) {
+ for (MybatisAfterHandler item : afterHandlersChain) {
+ item.handleObject(result);
+ }
+ }
+ return result;
+ }
+ if (preHandlersChain != null && preHandlersChain.size() > 0) {
+ for (MybatisPreHandler item : preHandlersChain) {
+ item.preHandle(targetExecutor, (MappedStatement) args[0], args[1], (RowBounds) args[2],
+ (ResultHandler) args[3], (CacheKey) args[4], (BoundSql) args[5]);
+ }
+ }
+ Object result = invocation.proceed();
+ if (afterHandlersChain != null && afterHandlersChain.size() > 0) {
+ for (MybatisAfterHandler item : afterHandlersChain) {
+ result = item.handleObject(result);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisAfterHandler.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisAfterHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..133f1116f80b5a5371836b6a56a31ec897712b6a
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisAfterHandler.java
@@ -0,0 +1,7 @@
+package com.ruoyi.mybatisinterceptor.sql;
+
+public interface MybatisAfterHandler {
+
+ Object handleObject(Object object) throws Throwable;
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisPreHandler.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisPreHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e9e2ebb7f360269feba8f1aae7affade046e4f1
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/MybatisPreHandler.java
@@ -0,0 +1,15 @@
+package com.ruoyi.mybatisinterceptor.sql;
+
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
+public interface MybatisPreHandler {
+
+ void preHandle(Executor executor, MappedStatement mappedStatement, Object params,
+ RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql)
+ throws Throwable;
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/dataSecurity/DataSecurityPreHandler.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/dataSecurity/DataSecurityPreHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..01a57667ea8f50e036e90cb3268b76dfb31a7548
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/dataSecurity/DataSecurityPreHandler.java
@@ -0,0 +1,98 @@
+package com.ruoyi.mybatisinterceptor.sql.dataSecurity;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import com.ruoyi.mybatisinterceptor.annotation.MybatisHandlerOrder;
+import com.ruoyi.mybatisinterceptor.context.dataSecurity.SqlContextHolder;
+import com.ruoyi.mybatisinterceptor.model.JoinTableModel;
+import com.ruoyi.mybatisinterceptor.model.WhereModel;
+import com.ruoyi.mybatisinterceptor.sql.MybatisPreHandler;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ReflectionUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import net.sf.jsqlparser.JSQLParserException;
+import net.sf.jsqlparser.expression.Alias;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
+import net.sf.jsqlparser.schema.Column;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.select.Join;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+
+@MybatisHandlerOrder(1)
+@Component
+public class DataSecurityPreHandler implements MybatisPreHandler {
+
+ private static final Field sqlFiled = ReflectionUtils.findField(BoundSql.class, "sql");
+ static {
+ sqlFiled.setAccessible(true);
+ }
+
+ @Override
+ public void preHandle(Executor executor, MappedStatement mappedStatement, Object params, RowBounds rowBounds,
+ ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws Throwable {
+ if (SqlContextHolder.isSecurity()) {
+ Statement sql = parseSql(SqlUtil.parseSql(boundSql.getSql()));
+ sqlFiled.set(boundSql, sql.toString());
+ }
+ }
+
+ private static Statement parseSql(Statement statement) throws JSQLParserException {
+ if (statement instanceof Select) {
+ Select select = (Select) statement;
+ // plain.setWhere(CCJSqlParserUtil.parseCondExpression(handleWhere(expWhere)));
+ handleWhere(select);
+ handleJoin(select);
+ return select;
+ } else {
+ return statement;
+ }
+ }
+
+ private static void handleWhere(Select select) throws JSQLParserException {
+ PlainSelect plain = select.getPlainSelect();
+ Expression expWhere = plain.getWhere();
+ StringBuilder whereParam = new StringBuilder(" ");
+ String where = expWhere != null ? expWhere.toString() : null;
+ if (SqlContextHolder.getWhere() == null || SqlContextHolder.getWhere().size() <= 0) {
+ return;
+ }
+ SqlContextHolder.getWhere().forEach(item -> {
+ whereParam.append(((WhereModel) item).getSqlString());
+ });
+ where = StringUtils.isEmpty(where) ? whereParam.toString().substring(5, whereParam.length())
+ : where + " " + whereParam.toString();
+ plain.setWhere(CCJSqlParserUtil.parseCondExpression(where));
+ }
+
+ private static void handleJoin(Select select) {
+ PlainSelect selectBody = select.getPlainSelect();
+ if (SqlContextHolder.getJoinTables() == null || SqlContextHolder.getJoinTables().size() <= 0) {
+ return;
+ }
+ SqlContextHolder.getJoinTables().forEach(item -> {
+ JoinTableModel tableModel = (JoinTableModel) item;
+ Table table = new Table(tableModel.getJoinTable());
+ table.setAlias(new Alias(tableModel.getJoinTableAlise()));
+ Join join = new Join();
+ join.setRightItem(table);
+ join.setInner(true);
+ Expression onExpression = new EqualsTo(new Column(tableModel.getFromTableColumnString()),
+ new Column(tableModel.getJoinTableColumnString()));
+ join.setOnExpressions(List.of(onExpression));
+ selectBody.addJoins(join);
+ });
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PageAfterHandler.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PageAfterHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..76d0776c263eb546e4be3f5f5c8424ba1b93fc11
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PageAfterHandler.java
@@ -0,0 +1,31 @@
+package com.ruoyi.mybatisinterceptor.sql.page;
+
+import java.util.List;
+
+import com.ruoyi.mybatisinterceptor.annotation.MybatisHandlerOrder;
+import com.ruoyi.mybatisinterceptor.context.page.PageContextHolder;
+import com.ruoyi.mybatisinterceptor.context.page.model.TableInfo;
+import com.ruoyi.mybatisinterceptor.sql.MybatisAfterHandler;
+import org.springframework.stereotype.Component;
+
+
+
+@MybatisHandlerOrder(1)
+@Component
+public class PageAfterHandler implements MybatisAfterHandler {
+
+ @Override
+ public Object handleObject(Object object) throws Throwable {
+ if (PageContextHolder.isPage()) {
+ if (object instanceof List) {
+ TableInfo tableInfo = new TableInfo<>((List) object);
+ tableInfo.setTotal(PageContextHolder.getTotal());
+ PageContextHolder.clear();
+ return tableInfo;
+ }
+ return object;
+ }
+ return object;
+ }
+
+}
diff --git a/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PagePreHandler.java b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PagePreHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7f771a44076bc535dee25e069adcdf26204a4b5
--- /dev/null
+++ b/ruoyi-plugins/ruoyi-mybatis-interceptor/src/main/java/com/ruoyi/mybatisinterceptor/sql/page/PagePreHandler.java
@@ -0,0 +1,142 @@
+package com.ruoyi.mybatisinterceptor.sql.page;
+
+import java.lang.reflect.Field;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.ruoyi.mybatisinterceptor.annotation.MybatisHandlerOrder;
+import com.ruoyi.mybatisinterceptor.context.page.PageContextHolder;
+import com.ruoyi.mybatisinterceptor.context.page.model.PageInfo;
+import com.ruoyi.mybatisinterceptor.sql.MybatisPreHandler;
+import org.apache.ibatis.cache.CacheKey;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ResultMap;
+import org.apache.ibatis.mapping.ResultMapping;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ReflectionUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import net.sf.jsqlparser.schema.Column;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.select.Limit;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectItem;
+
+@Component
+@MybatisHandlerOrder(2)
+public class PagePreHandler implements MybatisPreHandler {
+
+ private static final List EMPTY_RESULTMAPPING = new ArrayList(0);
+
+ private static final String SELECT_COUNT_SUFIX = "_SELECT_COUNT";
+ private static final Field sqlFiled = ReflectionUtils.findField(BoundSql.class, "sql");
+ static {
+ sqlFiled.setAccessible(true);
+ }
+
+ @Override
+ public void preHandle(Executor executor, MappedStatement mappedStatement, Object params, RowBounds rowBounds,
+ ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws Throwable {
+ if (PageContextHolder.isPage()) {
+ String originSql = boundSql.getSql();
+ Statement sql = SqlUtil.parseSql(originSql);
+ if (sql instanceof Select) {
+ PageInfo pageInfo = PageContextHolder.getPageInfo();
+ Statement handleLimit = handleLimit((Select) sql, pageInfo);
+ Statement countSql = getCountSql((Select) sql);
+ Long count = getCount(executor, mappedStatement, params, boundSql, rowBounds, resultHandler,
+ countSql.toString());
+ PageContextHolder.setTotal(count);
+ sqlFiled.set(boundSql, handleLimit.toString());
+ cacheKey = executor.createCacheKey(mappedStatement, params, rowBounds, boundSql);
+ }
+ }
+
+ }
+
+ private static MappedStatement createCountMappedStatement(MappedStatement ms, String newMsId) {
+ MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), newMsId,
+ ms.getSqlSource(),
+ ms.getSqlCommandType());
+ builder.resource(ms.getResource());
+ builder.fetchSize(ms.getFetchSize());
+ builder.statementType(ms.getStatementType());
+ builder.keyGenerator(ms.getKeyGenerator());
+ if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
+ StringBuilder keyProperties = new StringBuilder();
+ for (String keyProperty : ms.getKeyProperties()) {
+ keyProperties.append(keyProperty).append(",");
+ }
+ keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
+ builder.keyProperty(keyProperties.toString());
+ }
+ builder.timeout(ms.getTimeout());
+ builder.parameterMap(ms.getParameterMap());
+ // count查询返回值int
+ List resultMaps = new ArrayList();
+ ResultMap resultMap = new ResultMap.Builder(ms.getConfiguration(), ms.getId(), Long.class,
+ EMPTY_RESULTMAPPING)
+ .build();
+ resultMaps.add(resultMap);
+ builder.resultMaps(resultMaps);
+ builder.resultSetType(ms.getResultSetType());
+ builder.cache(ms.getCache());
+ builder.flushCacheRequired(ms.isFlushCacheRequired());
+ builder.useCache(ms.isUseCache());
+ return builder.build();
+ }
+
+ public static Long getCount(Executor executor, MappedStatement mappedStatement, Object parameter,
+ BoundSql boundSql, RowBounds rowBounds, ResultHandler resultHandler, String countSql)
+ throws SQLException {
+
+ Map additionalParameters = boundSql.getAdditionalParameters();
+
+ BoundSql countBoundSql = new BoundSql(mappedStatement.getConfiguration(), countSql,
+ boundSql.getParameterMappings(), parameter);
+ for (String key : additionalParameters.keySet()) {
+ countBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
+ }
+ CacheKey countKey = executor.createCacheKey(mappedStatement, parameter, RowBounds.DEFAULT, countBoundSql);
+
+ List