diff --git a/pom.xml b/pom.xml
index 286e85be..7b77c4ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,12 +40,24 @@
2.10.0
3.2.2
2.12.2
+ 4.1.0
-
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+ test
+
+
+ org.mockito
+ mockito-inline
+ ${mockito.version}
+ test
+
org.springframework.cloud
diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml
index 3bc14f45..b1c96b12 100644
--- a/ruoyi-common/ruoyi-common-core/pom.xml
+++ b/ruoyi-common/ruoyi-common-core/pom.xml
@@ -1,130 +1,144 @@
-
-
-
- com.ruoyi
- ruoyi-common
- 3.2.0
-
- 4.0.0
-
- ruoyi-common-core
-
-
- ruoyi-common-core核心模块
-
-
-
-
-
-
- org.springframework.cloud
- spring-cloud-starter-openfeign
-
-
-
-
- org.springframework.cloud
- spring-cloud-starter-loadbalancer
-
-
-
-
- org.springframework
- spring-context-support
-
-
-
-
- org.springframework
- spring-web
-
-
-
-
- com.alibaba
- transmittable-thread-local
-
-
-
-
- org.apache.commons
- commons-pool2
-
-
-
-
- com.github.pagehelper
- pagehelper-spring-boot-starter
-
-
-
-
- org.springframework.boot
- spring-boot-starter-validation
-
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
-
-
- com.alibaba
- fastjson
-
-
-
-
- io.jsonwebtoken
- jjwt
-
-
-
-
- javax.xml.bind
- jaxb-api
-
-
-
-
- org.apache.commons
- commons-lang3
-
-
-
-
- commons-io
- commons-io
-
-
-
-
- commons-fileupload
- commons-fileupload
-
-
-
-
- org.apache.poi
- poi-ooxml
-
-
-
-
- javax.servlet
- javax.servlet-api
-
-
-
-
- io.swagger
- swagger-annotations
-
-
-
-
-
+
+
+
+ com.ruoyi
+ ruoyi-common
+ 3.2.0
+
+ 4.0.0
+
+ ruoyi-common-core
+
+
+ ruoyi-common-core核心模块
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+
+ org.springframework
+ spring-context-support
+
+
+
+
+ org.springframework
+ spring-web
+
+
+
+
+ com.alibaba
+ transmittable-thread-local
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+
+
+ com.github.pagehelper
+ pagehelper-spring-boot-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ com.alibaba
+ fastjson
+
+
+
+
+ io.jsonwebtoken
+ jjwt
+
+
+
+
+ javax.xml.bind
+ jaxb-api
+
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+
+ commons-io
+ commons-io
+
+
+
+
+ commons-fileupload
+ commons-fileupload
+
+
+
+
+ org.apache.poi
+ poi-ooxml
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+
+
+ io.swagger
+ swagger-annotations
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
+
+ org.mockito
+ mockito-inline
+ test
+
+
+
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrder.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrder.java
new file mode 100644
index 00000000..069bf068
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrder.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.core.annotation.order;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义排序
+ * 如何使用:
+ * @DefaultOrder(column="createTime", orderType="desc", tableName="user")
+ * class UserVO {
+ * ...
+ * }
+ * startPage(UserVO.class)
+ * @author ruoyi
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(CustomOrders.class)
+public @interface CustomOrder {
+ // 列名 驼峰最终会转换为下划线命名法作为最终排序列名。
+ String column() default "";
+
+ // 列对应的表名
+ String tableName() default "";
+}
\ No newline at end of file
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrders.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrders.java
new file mode 100644
index 00000000..05667372
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/CustomOrders.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.core.annotation.order;
+
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义排序组合注解
+ * @author ruoyi
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Component
+public @interface CustomOrders {
+ CustomOrder[] value();
+}
\ No newline at end of file
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/DefaultOrder.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/DefaultOrder.java
new file mode 100644
index 00000000..67f7a840
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/DefaultOrder.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.core.annotation.order;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 默认排序
+ * 如何使用:
+ * @DefaultOrder(column="createTime", orderType="desc", tableName="user")
+ * class UserVO {
+ * ...
+ * }
+ * startPage(UserVO.class)
+ * @author ruoyi
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DefaultOrder {
+ // 默认排序列 驼峰最终会转换为下划线命名法作为最终排序列名。
+ String column() default "";
+ // 排序类型, desc/asc
+ String orderType() default "asc";
+ // 表名, 可不指定
+ String tableName() default "";
+}
\ No newline at end of file
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/TableAlias.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/TableAlias.java
new file mode 100644
index 00000000..edcec32b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/order/TableAlias.java
@@ -0,0 +1,25 @@
+package com.ruoyi.common.core.annotation.order;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 字段表别名
+ * 如何使用:
+ * class UserVO {
+ * ...
+ * @TableAlias("dept")
+ * private String deptName;
+ * ...
+ * }
+ * startPage(UserVO.class)
+ * 查询多表关联时, 指定表别名, 即可简单实现完成对应的字段排序。
+ * @author ruoyi
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TableAlias {
+ String value() default "";
+}
\ No newline at end of file
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
index 64169511..3c687cc6 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
@@ -1,8 +1,14 @@
package com.ruoyi.common.core.web.controller;
import java.beans.PropertyEditorSupport;
+import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
+import java.util.Objects;
+
+import com.ruoyi.common.core.annotation.order.CustomOrder;
+import com.ruoyi.common.core.annotation.order.DefaultOrder;
+import com.ruoyi.common.core.annotation.order.TableAlias;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
@@ -20,7 +26,7 @@ import com.ruoyi.common.core.web.page.TableSupport;
/**
* web层通用数据处理
- *
+ *
* @author ruoyi
*/
public class BaseController
@@ -60,12 +66,162 @@ public class BaseController
}
}
+ /**
+ * 设置请求分页数据
+ * 并根据class的注解设置排序列
+ * 列对应表名优先级
+ * TableAlias > CustomOrder > DefaultOrder
+ * @param clazz
+ */
+ protected void startPage(Class> clazz) {
+ // 正常分页的情况
+ if (clazz == null) {
+ startPage();
+ return;
+ }
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ Integer pageNum = pageDomain.getPageNum();
+ Integer pageSize = pageDomain.getPageSize();
+ if (pageNum != null && pageSize != null) {
+ PageHelper.startPage(pageNum, pageSize);
+ }
+
+ // 处理orderBy的情况。
+ String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+ String column = SqlUtil.escapeOrderBySql(pageDomain.getOrderByColumn());
+ // 获取默认排序
+ if (StringUtils.isEmpty(orderBy)) {
+ orderBy = getDefaultOrderByAnnotation(clazz);
+ }
+
+ if (StringUtils.isEmpty(orderBy)) {
+ return;
+ }
+ // 根据列获取表名
+ String tableName = getTableNameByColumn(clazz, column);
+ if (StringUtils.isNotEmpty(tableName)) {
+ orderBy = tableName + "." + orderBy;
+ }
+ PageHelper.orderBy(orderBy);
+ }
+
+ /**
+ * 尝试从field的TableAlias获取表别名
+ * @param clazz
+ * @param column
+ * @return
+ */
+ private static String getFieldTableName(Class> clazz, String column) {
+ // 获取对象中所有的成员变量
+ Field[] declaredFields = clazz.getDeclaredFields();
+ for (Field field : declaredFields) {
+ String fieldName = field.getName();
+ if (Objects.equals(column, fieldName)) {
+ if (field.isAnnotationPresent(TableAlias.class)) {
+ TableAlias orderTableAlias = field.getAnnotation(TableAlias.class);
+ return orderTableAlias.value();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 尝试从CustomOrder获取表别名
+ * @param clazz
+ * @param column
+ * @return
+ */
+ private static String getCustomOrderTableName(Class> clazz, String column) {
+ // 获取对象中所有的成员变量
+ if (clazz.isAnnotationPresent(CustomOrder.class)) {
+ CustomOrder[] customOrders = clazz.getAnnotationsByType(CustomOrder.class);
+ for (CustomOrder customOrder : customOrders) {
+ String realColumn = column;
+ if (column.contains("_")) {
+ realColumn = StringUtils.toCamelCase(customOrder.column());
+ }
+ if (Objects.equals(column, realColumn)) {
+ return customOrder.tableName();
+ }
+ }
+ }
+ return null;
+ }
+ /**
+ * 获取默认排序
+ * @param clazz
+ * @return
+ */
+ private static String getDefaultTableName(Class> clazz) {
+ // 最后,查找类上的tableName
+ if (clazz.isAnnotationPresent(DefaultOrder.class)) {
+ DefaultOrder defaultOrder = clazz.getAnnotation(DefaultOrder.class);
+ if (StringUtils.isNotEmpty(defaultOrder.tableName())) {
+ return defaultOrder.tableName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 通过过滤列获取对应的table
+ * @param clazz
+ * @param column
+ * @return
+ */
+ private static String getTableNameByColumn(Class> clazz, String column) {
+ if (clazz == null) {
+ return null;
+ }
+ String tableName = null;
+ // 未指定排序 则尝试设置默认排序的Table
+ if (StringUtils.isEmpty(column)) {
+ tableName = getDefaultTableName(clazz);
+ return tableName;
+ }
+
+
+ // 优先获取字段的tableName
+ tableName = getFieldTableName(clazz, column);
+ if (StringUtils.isNotEmpty(tableName)) {
+ return tableName;
+ }
+
+ // 其次查找CustomOrder定义的column对应的TableName
+ tableName = getCustomOrderTableName(clazz, column);
+ if (StringUtils.isNotEmpty(tableName)) {
+ return tableName;
+ }
+
+ // 获取默认排序
+ tableName = getDefaultTableName(clazz);
+
+ return tableName;
+ }
+
+ /**
+ * 获取类注解获取默认过滤列
+ * @param clazz
+ * @return
+ */
+ private String getDefaultOrderByAnnotation(Class> clazz) {
+ if (!clazz.isAnnotationPresent(DefaultOrder.class)) {
+ return null;
+ }
+ DefaultOrder defaultOrder = clazz.getAnnotation(DefaultOrder.class);
+ String orderBy = null;
+ if (StringUtils.isNotEmpty(defaultOrder.column())) {
+ orderBy = StringUtils.toUnderScoreCase(defaultOrder.column()) + " " + defaultOrder.orderType();
+ }
+ return orderBy;
+ }
+
/**
* 响应请求分页数据
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
- protected TableDataInfo getDataTable(List> list)
- {
+ protected TableDataInfo getDataTable(List> list) {
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(HttpStatus.SUCCESS);
rspData.setRows(list);
@@ -76,7 +232,7 @@ public class BaseController
/**
* 响应返回结果
- *
+ *
* @param rows 影响行数
* @return 操作结果
*/
@@ -87,7 +243,7 @@ public class BaseController
/**
* 响应返回结果
- *
+ *
* @param result 结果
* @return 操作结果
*/
diff --git a/ruoyi-common/ruoyi-common-core/src/test/com/ruoyi/common/core/web/controller/BaseControllerTest.java b/ruoyi-common/ruoyi-common-core/src/test/com/ruoyi/common/core/web/controller/BaseControllerTest.java
new file mode 100644
index 00000000..84d47465
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/test/com/ruoyi/common/core/web/controller/BaseControllerTest.java
@@ -0,0 +1,125 @@
+package com.ruoyi.common.core.web.controller;
+
+import com.github.pagehelper.Page;
+import com.github.pagehelper.PageHelper;
+import com.ruoyi.common.core.annotation.order.CustomOrder;
+import com.ruoyi.common.core.annotation.order.DefaultOrder;
+import com.ruoyi.common.core.annotation.order.TableAlias;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.core.web.page.PageDomain;
+import com.ruoyi.common.core.web.page.TableSupport;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class BaseControllerTest {
+
+ @Test
+ void testStartPageByDefaultOrder()
+ {
+ @DefaultOrder(tableName = "user", column = "userName")
+ class UserVO {
+ private String userName;
+ }
+ PageDomain pageDomain = new PageDomain();
+ pageDomain.setPageNum(10);
+ pageDomain.setPageSize(20);
+
+ MockedStatic mocked = Mockito.mockStatic(TableSupport.class);
+ mocked.when(TableSupport::buildPageRequest).thenReturn(
+ pageDomain
+ );
+ new BaseController().startPage(UserVO.class);
+ Page