1. 新增分页接口聚合查询注解支持

2. 优化 databus api 日志记录的字段缺失问题
3. 新增 eplat sso 页面登录校验
4. 用户、部门编辑新增 seata 事务支持
5. 新增 iwork 流程发起接口
6. 新增 eban 同步用户时的岗位处理逻辑
7. 新增无 skywalking 时的 traceId 支持
This commit is contained in:
chenbowen
2025-11-18 10:03:34 +08:00
committed by chenbowen
parent 8b3d93dc17
commit 633e430f46
72 changed files with 4997 additions and 92 deletions

View File

@@ -1,9 +1,9 @@
package com.zt.plat.framework.mybatis.config;
import cn.hutool.core.util.StrUtil;
import com.zt.plat.framework.mybatis.core.handler.DefaultDBFieldHandler;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.extension.incrementer.*;
@@ -11,6 +11,8 @@ import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.zt.plat.framework.mybatis.core.handler.DefaultDBFieldHandler;
import com.zt.plat.framework.mybatis.core.sum.PageSumTableFieldAnnotationHandler;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@@ -25,29 +27,40 @@ import java.util.concurrent.TimeUnit;
*
* @author ZT
*/
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) // 目的:先于 MyBatis Plus 自动配置,避免 @MapperScan 可能扫描不到 Mapper 打印 warn 日志
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) // 先于官方自动配置,避免 Mapper 未扫描完成
@MapperScan(value = "${zt.info.base-package}", annotationClass = Mapper.class,
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅单测需要
public class ZtMybatisAutoConfiguration {
static {
// 动态 SQL 智能优化支持本地缓存加速解析,更完善的租户复杂 XML 动态 SQL 支持,静态注入缓存
// 使用本地缓存加速 JsqlParser 解析,复杂动态 SQL 性能更稳定
JsqlParserGlobal.setJsqlParseCache(new JdkSerialCaffeineJsqlParseCache(
(cache) -> cache.maximumSize(1024)
.expireAfterWrite(5, TimeUnit.SECONDS))
);
cache -> cache.maximumSize(1024).expireAfterWrite(5, TimeUnit.SECONDS)));
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
return mybatisPlusInterceptor;
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
return interceptor;
}
@Bean
public MetaObjectHandler defaultMetaObjectHandler() {
return new DefaultDBFieldHandler(); // 自动填充参数类
return new DefaultDBFieldHandler(); // 统一的公共字段填充
}
@Bean
public MybatisPlusPropertiesCustomizer pageSumAnnotationCustomizer() {
// 通过官方扩展点为 @PageSum 字段自动注入 exist = false 的 TableField 注解
return properties -> {
var globalConfig = properties.getGlobalConfig();
if (globalConfig == null) {
return;
}
globalConfig.setAnnotationHandler(
new PageSumTableFieldAnnotationHandler(globalConfig.getAnnotationHandler()));
};
}
@Bean

View File

@@ -1,6 +1,13 @@
package com.zt.plat.framework.mybatis.core.mapper;
import cn.hutool.core.collection.CollUtil;
import com.zt.plat.framework.common.pojo.PageParam;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.pojo.SortablePageParam;
import com.zt.plat.framework.common.pojo.SortingField;
import com.zt.plat.framework.mybatis.core.sum.PageSumSupport;
import com.zt.plat.framework.mybatis.core.util.JdbcUtils;
import com.zt.plat.framework.mybatis.core.util.MyBatisUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -43,14 +50,18 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
// 特殊:不分页,直接查询全部
if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
List<T> list = selectList(queryWrapper);
return new PageResult<>(list, (long) list.size());
PageResult<T> pageResult = new PageResult<>(list, (long) list.size());
PageSumSupport.tryAttachSummary(this, queryWrapper, pageResult);
return pageResult;
}
// MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
selectPage(mpPage, queryWrapper);
// 转换返回
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
PageResult<T> pageResult = new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
PageSumSupport.tryAttachSummary(this, queryWrapper, pageResult);
return pageResult;
}
default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {

View File

@@ -0,0 +1,76 @@
package com.zt.plat.framework.mybatis.core.sum;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* Metadata describing a field participating in page-level SUM aggregation.
*/
final class PageSumFieldMeta {
private final String propertyName;
private final String columnExpression;
private final String selectAlias;
private final Class<?> fieldType;
PageSumFieldMeta(String propertyName, String columnExpression, String selectAlias, Class<?> fieldType) {
this.propertyName = propertyName;
this.columnExpression = columnExpression;
this.selectAlias = selectAlias;
this.fieldType = fieldType;
}
static PageSumFieldMeta of(Field field, String columnExpression) {
String property = field.getName();
return new PageSumFieldMeta(property, columnExpression, property, field.getType());
}
String getPropertyName() {
return propertyName;
}
String getColumnExpression() {
return columnExpression;
}
String getSelectAlias() {
return selectAlias;
}
Class<?> getFieldType() {
return fieldType;
}
String buildSelectSegment() {
return "SUM(" + columnExpression + ") AS " + selectAlias;
}
@Override
public int hashCode() {
return Objects.hash(propertyName, columnExpression, selectAlias, fieldType);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PageSumFieldMeta other)) {
return false;
}
return Objects.equals(propertyName, other.propertyName)
&& Objects.equals(columnExpression, other.columnExpression)
&& Objects.equals(selectAlias, other.selectAlias)
&& Objects.equals(fieldType, other.fieldType);
}
@Override
public String toString() {
return "PageSumFieldMeta{" +
"propertyName='" + propertyName + '\'' +
", columnExpression='" + columnExpression + '\'' +
", selectAlias='" + selectAlias + '\'' +
", fieldType=" + fieldType +
'}';
}
}

View File

@@ -0,0 +1,79 @@
package com.zt.plat.framework.mybatis.core.sum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
import com.zt.plat.framework.common.annotation.PageSum;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
/**
* 让 {@link PageSum#exist()} 能够自动生成 {@link TableField#exist()} = false 的能力,
* 这样 DO 层无需重复编写 {@code @TableField(exist = false)}。
*/
public class PageSumTableFieldAnnotationHandler implements AnnotationHandler {
private static final AnnotationHandler DEFAULT_HANDLER = new AnnotationHandler() { };
/** 预构建 @TableField(exist = false) 的属性集合,避免重复创建 Map 对象 */
private static final Map<String, Object> TABLE_FIELD_EXIST_FALSE_ATTRIBUTES =
Collections.singletonMap("exist", Boolean.FALSE);
private final AnnotationHandler delegate;
public PageSumTableFieldAnnotationHandler(AnnotationHandler delegate) {
this.delegate = delegate != null ? delegate : DEFAULT_HANDLER;
}
@Override
public <T extends Annotation> T getAnnotation(Class<?> target, Class<T> annotationClass) {
return delegate.getAnnotation(target, annotationClass);
}
@Override
public <T extends Annotation> boolean isAnnotationPresent(Class<?> target, Class<T> annotationClass) {
return delegate.isAnnotationPresent(target, annotationClass);
}
@Override
public <T extends Annotation> T getAnnotation(java.lang.reflect.Method method, Class<T> annotationClass) {
return delegate.getAnnotation(method, annotationClass);
}
@Override
public <T extends Annotation> boolean isAnnotationPresent(java.lang.reflect.Method method, Class<T> annotationClass) {
return delegate.isAnnotationPresent(method, annotationClass);
}
@Override
public <T extends Annotation> T getAnnotation(Field field, Class<T> annotationClass) {
T annotation = delegate.getAnnotation(field, annotationClass);
if (annotation != null || annotationClass != TableField.class) {
return annotation;
}
PageSum pageSum = delegate.getAnnotation(field, PageSum.class);
if (pageSum != null && !pageSum.exist()) {
// 当字段只用于分页汇总时,动态合成一个 exist = false 的 TableField 注解
return annotationClass.cast(synthesizeTableField(field));
}
return null;
}
@Override
public <T extends Annotation> boolean isAnnotationPresent(Field field, Class<T> annotationClass) {
if (delegate.isAnnotationPresent(field, annotationClass)) {
return true;
}
if (annotationClass != TableField.class) {
return false;
}
PageSum pageSum = delegate.getAnnotation(field, PageSum.class);
return pageSum != null && !pageSum.exist();
}
private static TableField synthesizeTableField(Field field) {
return AnnotationUtils.synthesizeAnnotation(TABLE_FIELD_EXIST_FALSE_ATTRIBUTES, TableField.class, field);
}
}

View File

@@ -0,0 +1,68 @@
package com.zt.plat.framework.mybatis.core.sum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zt.plat.framework.common.annotation.PageSum;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
import org.junit.jupiter.api.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
class PageSumSupportTest {
@Test
void shouldAttachSummaryWhenAnnotationPresent() {
TestMapper mapper = createMapperProxy();
PageResult<TestEntity> pageResult = new PageResult<>(Collections.emptyList(), 0L);
QueryWrapper<TestEntity> wrapper = new QueryWrapper<>();
PageSumSupport.tryAttachSummary(mapper, wrapper, pageResult);
assertFalse(pageResult.getSummary().isEmpty());
assertEquals(new BigDecimal("123.45"), pageResult.getSummary().get("amount"));
assertEquals(new BigDecimal("50"), pageResult.getSummary().get("virtualAmount"));
}
private TestMapper createMapperProxy() {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if ("selectMaps".equals(method.getName())) {
Map<String, Object> row = new HashMap<>();
row.put("amount", new BigDecimal("123.45"));
row.put("virtualAmount", new BigDecimal("50"));
return List.of(row);
}
return Collections.emptyList();
}
};
return (TestMapper) Proxy.newProxyInstance(
TestMapper.class.getClassLoader(),
new Class[]{TestMapper.class},
handler);
}
interface TestMapper extends BaseMapperX<TestEntity> {
}
static class TestEntity {
@PageSum(column = "amount")
private BigDecimal amount;
@PageSum(column = "virtual_column", exist = false)
private BigDecimal virtualAmount;
}
}