# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
#	yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java
#	yudao-module-bpm/yudao-module-bpm-server/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java
#	yudao-module-bpm/yudao-module-bpm-server/src/main/resources/application-local.yaml
#	yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java
#	yudao-module-infra/yudao-module-infra-server/src/main/resources/application-local.yaml
#	yudao-module-mall/yudao-module-product-server/src/main/resources/application-local.yaml
#	yudao-module-mall/yudao-module-promotion-server/src/main/resources/application-local.yaml
#	yudao-module-mall/yudao-module-statistics-server/src/main/resources/application-local.yaml
#	yudao-module-mall/yudao-module-trade-server/src/main/resources/application-local.yaml
#	yudao-module-member/yudao-module-member-server/src/main/resources/application-local.yaml
#	yudao-module-mp/yudao-module-mp-server/src/main/resources/application-local.yaml
#	yudao-module-pay/yudao-module-pay-server/src/main/resources/application-local.yaml
#	yudao-module-report/yudao-module-report-server/src/main/resources/application-local.yaml
#	yudao-module-system/yudao-module-system-server/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java
#	yudao-module-system/yudao-module-system-server/src/main/resources/application-local.yaml
pull/150/MERGE
YunaiV 2025-07-26 19:26:49 +08:00
commit 7b6c81beaa
170 changed files with 1234 additions and 1284 deletions

View File

@ -39,7 +39,7 @@
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version> <opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
<taos.version>3.3.3</taos.version> <taos.version>3.3.3</taos.version>
<!-- 消息队列 --> <!-- 消息队列 -->
<rocketmq-spring.version>2.3.1</rocketmq-spring.version> <rocketmq-spring.version>2.3.2</rocketmq-spring.version>
<!-- RPC 相关 --> <!-- RPC 相关 -->
<!-- Config 配置中心相关 --> <!-- Config 配置中心相关 -->
<!-- Job 定时任务相关 --> <!-- Job 定时任务相关 -->
@ -62,7 +62,7 @@
<lombok.version>1.18.36</lombok.version> <lombok.version>1.18.36</lombok.version>
<mapstruct.version>1.6.3</mapstruct.version> <mapstruct.version>1.6.3</mapstruct.version>
<hutool.version>5.8.35</hutool.version> <hutool.version>5.8.35</hutool.version>
<easyexcel.version>4.0.3</easyexcel.version> <fastexcel.version>1.2.0</fastexcel.version>
<velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! --> <velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! -->
<fastjson.version>1.2.83</fastjson.version> <fastjson.version>1.2.83</fastjson.version>
<guava.version>33.4.8-jre</guava.version> <guava.version>33.4.8-jre</guava.version>
@ -78,8 +78,6 @@
<pf4j-spring.version>0.9.0</pf4j-spring.version> <pf4j-spring.version>0.9.0</pf4j-spring.version>
<vertx.version>4.5.13</vertx.version> <vertx.version>4.5.13</vertx.version>
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<commons-io.version>2.17.0</commons-io.version>
<commons-compress.version>1.27.1</commons-compress.version>
<awssdk.version>2.30.14</awssdk.version> <awssdk.version>2.30.14</awssdk.version>
<justauth.version>1.16.7</justauth.version> <justauth.version>1.16.7</justauth.version>
<justauth-starter.version>1.4.0</justauth-starter.version> <justauth-starter.version>1.4.0</justauth-starter.version>
@ -551,20 +549,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
<version>${easyexcel.version}</version> <version>${fastexcel.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -74,30 +74,30 @@ public class DateUtils {
* *
* *
* @param year * @param year
* @param mouth * @param month
* @param day * @param day
* @return * @return
*/ */
public static Date buildTime(int year, int mouth, int day) { public static Date buildTime(int year, int month, int day) {
return buildTime(year, mouth, day, 0, 0, 0); return buildTime(year, month, day, 0, 0, 0);
} }
/** /**
* *
* *
* @param year * @param year
* @param mouth * @param month
* @param day * @param day
* @param hour * @param hour
* @param minute * @param minute
* @param second * @param second
* @return * @return
*/ */
public static Date buildTime(int year, int mouth, int day, public static Date buildTime(int year, int month, int day,
int hour, int minute, int second) { int hour, int minute, int second) {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year); calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, mouth - 1); calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.MINUTE, minute);

View File

@ -49,8 +49,8 @@
<!-- 工具类相关 --> <!-- 工具类相关 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>easyexcel</artifactId> <artifactId>fastexcel</artifactId>
</dependency> </dependency>
<dependency> <dependency>
@ -58,11 +58,6 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId> <!-- 解决 https://github.com/alibaba/easyexcel/issues/3954 问题 -->
</dependency>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId> <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>

View File

@ -76,4 +76,9 @@ public class DictFrameworkUtils {
return dictData!= null ? dictData.getValue(): null; return dictData!= null ? dictData.getValue(): null;
} }
@SneakyThrows
public static List<String> getDictDataValueList(String dictType) {
List<DictDataRespDTO> dictDatas = GET_DICT_DATA_CACHE.get(dictType);
return convertList(dictDatas, DictDataRespDTO::getValue);
}
} }

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.framework.dict.validation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Target({
ElementType.METHOD,
ElementType.FIELD,
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.PARAMETER,
ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {InDictValidator.class, InDictCollectionValidator.class}
)
public @interface InDict {
/**
* type
*/
String type();
String message() default "必须在指定范围 {value}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.framework.dict.validation;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Collection;
import java.util.List;
public class InDictCollectionValidator implements ConstraintValidator<InDict, Collection<?>> {
private String dictType;
@Override
public void initialize(InDict annotation) {
this.dictType = annotation.type();
}
@Override
public boolean isValid(Collection<?> list, ConstraintValidatorContext context) {
// 为空时,默认不校验,即认为通过
if (CollUtil.isEmpty(list)) {
return true;
}
// 校验全部通过
List<String> dbValues = DictFrameworkUtils.getDictDataValueList(dictType);
boolean match = list.stream().allMatch(v -> dbValues.stream()
.anyMatch(dbValue -> dbValue.equalsIgnoreCase(v.toString())));
if (match) {
return true;
}
// 校验不通过,自定义提示语句
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
context.buildConstraintViolationWithTemplate(
context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}", dbValues.toString())
).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.framework.dict.validation;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.List;
public class InDictValidator implements ConstraintValidator<InDict, Object> {
private String dictType;
@Override
public void initialize(InDict annotation) {
this.dictType = annotation.type();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
// 为空时,默认不校验,即认为通过
if (value == null) {
return true;
}
// 校验通过
final List<String> values = DictFrameworkUtils.getDictDataValueList(dictType);
boolean match = values.stream().anyMatch(v -> StrUtil.equalsIgnoreCase(v, value.toString()));
if (match) {
return true;
}
// 校验不通过,自定义提示语句
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
context.buildConstraintViolationWithTemplate(
context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}", values.toString())
).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}

View File

@ -3,11 +3,11 @@ package cn.iocoder.yudao.framework.excel.core.convert;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.Area;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import com.alibaba.excel.converters.Converter; import cn.idev.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import cn.idev.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration; import cn.idev.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData; import cn.idev.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import cn.idev.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**

View File

@ -3,12 +3,12 @@ package cn.iocoder.yudao.framework.excel.core.convert;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import com.alibaba.excel.converters.Converter; import cn.idev.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import cn.idev.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration; import cn.idev.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData; import cn.idev.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData; import cn.idev.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import cn.idev.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.framework.excel.core.convert; package cn.iocoder.yudao.framework.excel.core.convert;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import com.alibaba.excel.converters.Converter; import cn.idev.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import cn.idev.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration; import cn.idev.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData; import cn.idev.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import cn.idev.excel.metadata.property.ExcelContentProperty;
/** /**
* Excel Json * Excel Json

View File

@ -1,10 +1,10 @@
package cn.iocoder.yudao.framework.excel.core.convert; package cn.iocoder.yudao.framework.excel.core.convert;
import com.alibaba.excel.converters.Converter; import cn.idev.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum; import cn.idev.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration; import cn.idev.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.WriteCellData; import cn.idev.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty; import cn.idev.excel.metadata.property.ExcelContentProperty;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;

View File

@ -11,12 +11,12 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction; import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction;
import com.alibaba.excel.annotation.ExcelIgnore; import cn.idev.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler; import cn.idev.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
@ -87,7 +87,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
/** /**
* transient * transient
* EasyExcel static final transient * FastExcel static final transient
* *
* @param field * @param field
* @return transient * @return transient

View File

@ -1,13 +1,13 @@
package cn.iocoder.yudao.framework.excel.core.util; package cn.iocoder.yudao.framework.excel.core.util;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.converters.longconverter.LongStringConverter;
import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
import com.alibaba.excel.EasyExcel; import jakarta.servlet.http.HttpServletResponse;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -32,7 +32,7 @@ public class ExcelUtils {
public static <T> void write(HttpServletResponse response, String filename, String sheetName, public static <T> void write(HttpServletResponse response, String filename, String sheetName,
Class<T> head, List<T> data) throws IOException { Class<T> head, List<T> data) throws IOException {
// 输出 Excel // 输出 Excel
EasyExcel.write(response.getOutputStream(), head) FastExcelFactory.write(response.getOutputStream(), head)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
.registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
@ -44,7 +44,7 @@ public class ExcelUtils {
} }
public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException { public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
return EasyExcel.read(file.getInputStream(), head, null) return FastExcelFactory.read(file.getInputStream(), head, null)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.doReadAllSync(); .doReadAllSync();
} }

View File

@ -1,4 +1,4 @@
/** /**
* EasyExcel Excel * FastExcel Excel
*/ */
package cn.iocoder.yudao.framework.excel; package cn.iocoder.yudao.framework.excel;

View File

@ -44,29 +44,35 @@
<dependency> <dependency>
<groupId>io.opentracing</groupId> <groupId>io.opentracing</groupId>
<artifactId>opentracing-util</artifactId> <artifactId>opentracing-util</artifactId>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.skywalking</groupId> <groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId> <artifactId>apm-toolkit-trace</artifactId>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.skywalking</groupId> <groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId> <artifactId>apm-toolkit-logback-1.x</artifactId>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.skywalking</groupId> <groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-opentracing</artifactId> <artifactId>apm-toolkit-opentracing</artifactId>
<optional>true</optional>
</dependency> </dependency>
<!-- Micrometer 对 Prometheus 的支持 --> <!-- Micrometer 对 Prometheus 的支持 -->
<dependency> <dependency>
<groupId>io.micrometer</groupId> <groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId> <artifactId>micrometer-registry-prometheus</artifactId>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>de.codecentric</groupId> <groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 --> <artifactId>spring-boot-admin-starter-client</artifactId> <!-- 实现 Spring Boot Admin Client 客户端 -->
<optional>true</optional>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -3,6 +3,9 @@ package cn.iocoder.yudao.framework.tracer.config;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect; import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect;
import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter; import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -16,30 +19,32 @@ import org.springframework.context.annotation.Bean;
* @author mashu * @author mashu
*/ */
@AutoConfiguration @AutoConfiguration
@ConditionalOnClass({BizTraceAspect.class}) @ConditionalOnClass(name = {
"org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer",
"io.opentracing.Tracer"
})
@EnableConfigurationProperties(TracerProperties.class) @EnableConfigurationProperties(TracerProperties.class)
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
public class YudaoTracerAutoConfiguration { public class YudaoTracerAutoConfiguration {
// TODO @芋艿:重要。目前 opentracing 版本存在冲突,要么保证 skywalking要么保证阿里云短信 sdk @Bean
// @Bean public TracerProperties bizTracerProperties() {
// public TracerProperties bizTracerProperties() { return new TracerProperties();
// return new TracerProperties(); }
// }
// @Bean
// @Bean public BizTraceAspect bizTracingAop() {
// public BizTraceAspect bizTracingAop() { return new BizTraceAspect(tracer());
// return new BizTraceAspect(tracer()); }
// }
// @Bean
// @Bean public Tracer tracer() {
// public Tracer tracer() { // 创建 SkywalkingTracer 对象
// // 创建 SkywalkingTracer 对象 SkywalkingTracer tracer = new SkywalkingTracer();
// SkywalkingTracer tracer = new SkywalkingTracer(); // 设置为 GlobalTracer 的追踪器
// // 设置为 GlobalTracer 的追踪器 GlobalTracer.registerIfAbsent(tracer);
// GlobalTracer.register(tracer); return tracer;
// return tracer; }
// }
/** /**
* TraceFilter header traceId * TraceFilter header traceId

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.web.core.filter; package cn.iocoder.yudao.framework.web.core.filter;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
@ -16,6 +17,14 @@ import java.io.IOException;
*/ */
public class CacheRequestBodyFilter extends OncePerRequestFilter { public class CacheRequestBodyFilter extends OncePerRequestFilter {
/**
* URI
*
* 1. Spring Boot Admin
* <a href="https://github.com/YunaiV/ruoyi-vue-pro/issues/795">795 ISSUE</a>
*/
private static final String[] IGNORE_URIS = {"/admin/", "/actuator/"};
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException { throws IOException, ServletException {
@ -24,7 +33,13 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter {
@Override @Override
protected boolean shouldNotFilter(HttpServletRequest request) { protected boolean shouldNotFilter(HttpServletRequest request) {
// 只处理 json 请求内容 // 1. 校验是否为排除的 URL
String requestURI = request.getRequestURI();
if (StrUtil.startWithAny(requestURI, IGNORE_URIS)) {
return true;
}
// 2. 只处理 json 请求内容
return !ServletUtils.isJsonRequest(request); return !ServletUtils.isJsonRequest(request);
} }

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -46,14 +46,16 @@ spring:
initial-size: 5 # 初始连接数 initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量 min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -20,7 +20,6 @@ spring:
# 数据源配置项 # 数据源配置项
autoconfigure: autoconfigure:
exclude: exclude:
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant手动创建 - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant手动创建
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus手动创建 - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus手动创建
datasource: datasource:
@ -47,14 +46,16 @@ spring:
initial-size: 1 # 初始连接数 initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量 min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -74,6 +74,7 @@ public interface ErrorCodeConstants {
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_009_012_000, "流程分类不存在"); ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_009_012_000, "流程分类不存在");
ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(1_009_012_001, "流程分类名字【{}】重复"); ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(1_009_012_001, "流程分类名字【{}】重复");
ErrorCode CATEGORY_CODE_DUPLICATE = new ErrorCode(1_009_012_002, "流程分类编码【{}】重复"); ErrorCode CATEGORY_CODE_DUPLICATE = new ErrorCode(1_009_012_002, "流程分类编码【{}】重复");
ErrorCode CATEGORY_DELETE_FAIL_MODEL_USED = new ErrorCode(1_009_012_003, "删除失败,流程分类【{}】已被流程模型使用,请先删除对应的流程模型");
// ========== BPM 流程监听器 1-009-013-000 ========== // ========== BPM 流程监听器 1-009-013-000 ==========
ErrorCode PROCESS_LISTENER_NOT_EXISTS = new ErrorCode(1_009_013_000, "流程监听器不存在"); ErrorCode PROCESS_LISTENER_NOT_EXISTS = new ErrorCode(1_009_013_000, "流程监听器不存在");

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression; package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -73,7 +73,7 @@ public class BpmApprovalDetailRespVO {
private List<UserSimpleBaseVO> candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 private List<UserSimpleBaseVO> candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表
@Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf") @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf")
private String processInstanceId; // 当且仅当该节点是子流程节点时才会有值CallActivity 的 processInstanceId 字段) private String processInstanceId; // 当且仅当该节点是子流程节点时才会有值CallActivity 的 calledProcessInstanceId 字段)
} }

View File

@ -18,10 +18,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.CallActivity;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
@ -132,7 +129,7 @@ public class BpmTaskCandidateInvoker {
Long startUserId, String processDefinitionId, Map<String, Object> processVariables) { Long startUserId, String processDefinitionId, Map<String, Object> processVariables) {
// 如果是 CallActivity 子流程,不进行计算候选人 // 如果是 CallActivity 子流程,不进行计算候选人
FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, activityId); FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, activityId);
if (flowElement instanceof CallActivity) { if (flowElement instanceof CallActivity || flowElement instanceof SubProcess) {
return new HashSet<>(); return new HashSet<>();
} }
// 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过 // 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过

View File

@ -11,7 +11,7 @@ import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import javax.annotation.Resource; import jakarta.annotation.Resource;
import java.util.Set; import java.util.Set;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
@ -24,6 +24,7 @@ import static java.util.Collections.emptySet;
* @author * @author
*/ */
@Component @Component
@Deprecated // 仅仅是表达式的示例,建议使用 BpmTaskCandidateStartUserDeptLeaderStrategy 替代
public class BpmTaskAssignLeaderExpression { public class BpmTaskAssignLeaderExpression {
@Resource @Resource

View File

@ -16,6 +16,7 @@ import java.util.Set;
* @author * @author
*/ */
@Component @Component
@Deprecated // 仅仅是表达式的示例,建议使用 BpmTaskCandidateStartUserStrategy 替代
public class BpmTaskAssignStartUserExpression { public class BpmTaskAssignStartUserExpression {
@Resource @Resource

View File

@ -8,6 +8,7 @@ import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.api.FlowableException; import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.javax.el.PropertyNotFoundException;
import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -48,10 +49,12 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat
Object result = FlowableUtils.getExpressionValue(variables, param); Object result = FlowableUtils.getExpressionValue(variables, param);
return CollectionUtils.toLinkedHashSet(Long.class, result); return CollectionUtils.toLinkedHashSet(Long.class, result);
} catch (FlowableException ex) { } catch (FlowableException ex) {
// 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常, // 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常,此时忽略该异常!相当于说,不做流程预测!!!
log.warn("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex); if (ex.getCause() != null && ex.getCause() instanceof PropertyNotFoundException) {
// 不能预测候选人,返回空列表, 避免流程无法进行 return Sets.newHashSet();
return Sets.newHashSet(); }
log.error("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex);
throw ex;
} }
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent
@Override @Override
protected void processCreated(FlowableEngineEntityEvent event) { protected void processCreated(FlowableEngineEntityEvent event) {
processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity()); ProcessInstance processInstance = (ProcessInstance) event.getEntity();
FlowableUtils.execute(processInstance.getTenantId(),
() -> processInstanceService.processProcessInstanceCreated(processInstance));
} }
@Override @Override
protected void processCompleted(FlowableEngineEntityEvent event) { protected void processCompleted(FlowableEngineEntityEvent event) {
processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity()); ProcessInstance processInstance = (ProcessInstance) event.getEntity();
FlowableUtils.execute(processInstance.getTenantId(),
() -> processInstanceService.processProcessInstanceCompleted(processInstance));
} }
@Override // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法 @Override
protected void processCancelled(FlowableCancelledEvent event) { protected void processCancelled(FlowableCancelledEvent event) {
// 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法
ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId()); ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
processInstanceService.processProcessInstanceCompleted(processInstance); if (processInstance != null) {
FlowableUtils.execute(processInstance.getTenantId(),
() -> processInstanceService.processProcessInstanceCompleted(processInstance));
}
} }
} }

View File

@ -3,10 +3,12 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventTypeEnum; import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventTypeEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -58,17 +60,20 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
@Override @Override
protected void taskCreated(FlowableEngineEntityEvent event) { protected void taskCreated(FlowableEngineEntityEvent event) {
taskService.processTaskCreated((Task) event.getEntity()); Task entity = (Task) event.getEntity();
FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskCreated(entity));
} }
@Override @Override
protected void taskAssigned(FlowableEngineEntityEvent event) { protected void taskAssigned(FlowableEngineEntityEvent event) {
taskService.processTaskAssigned((Task) event.getEntity()); Task entity = (Task) event.getEntity();
FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskAssigned(entity));
} }
@Override @Override
protected void taskCompleted(FlowableEngineEntityEvent event) { protected void taskCompleted(FlowableEngineEntityEvent event) {
taskService.processTaskCompleted((Task) event.getEntity()); Task entity = (Task) event.getEntity();
FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskCompleted(entity));
} }
@Override @Override
@ -94,6 +99,23 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
String processDefinitionId = event.getProcessDefinitionId(); String processDefinitionId = event.getProcessDefinitionId();
BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processDefinitionId); BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processDefinitionId);
Job entity = (Job) event.getEntity(); Job entity = (Job) event.getEntity();
// 特殊 from https://t.zsxq.com/h6oWr :当 elementId 为空时,尝试从 JobHandlerConfiguration 中解析 JSON 获取
String elementId = entity.getElementId();
if (elementId == null && entity.getJobHandlerConfiguration() != null) {
try {
String handlerConfig = entity.getJobHandlerConfiguration();
if (handlerConfig.startsWith("{") && handlerConfig.contains("activityId")) {
elementId = new JSONObject(handlerConfig).getStr("activityId");
}
} catch (Exception e) {
log.error("[timerFired][解析 entity({}) 失败]", entity, e);
return;
}
}
if (elementId == null) {
log.error("[timerFired][解析 entity({}) elementId 为空,跳过处理]", entity);
return;
}
FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, entity.getElementId()); FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, entity.getElementId());
if (!(element instanceof BoundaryEvent)) { if (!(element instanceof BoundaryEvent)) {
return; return;

View File

@ -108,7 +108,9 @@ public class BpmHttpRequestUtils {
Map<String, Object> processVariables = processInstance.getProcessVariables(); Map<String, Object> processVariables = processInstance.getProcessVariables();
MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
addHttpRequestParam(body, bodySettings, processVariables); addHttpRequestParam(body, bodySettings, processVariables);
body.add("processInstanceId", processInstance.getId()); if (!body.containsKey("processInstanceId")) { // 避免重复添加
body.add("processInstanceId", processInstance.getId());
}
return body; return body;
} }

View File

@ -478,7 +478,11 @@ public class BpmnModelUtils {
*/ */
public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) { public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
Process process = model.getMainProcess(); Process process = model.getMainProcess();
return process.getFlowElement(flowElementId); FlowElement flowElement = process.getFlowElement(flowElementId);
if (flowElement != null) {
return flowElement;
}
return model.getFlowElement(flowElementId);
} }
/** /**

View File

@ -34,6 +34,9 @@ public class BpmCategoryServiceImpl implements BpmCategoryService {
@Resource @Resource
private BpmCategoryMapper bpmCategoryMapper; private BpmCategoryMapper bpmCategoryMapper;
@Resource
private BpmModelService modelService;
@Override @Override
public Long createCategory(BpmCategorySaveReqVO createReqVO) { public Long createCategory(BpmCategorySaveReqVO createReqVO) {
// 校验唯一 // 校验唯一
@ -77,15 +80,22 @@ public class BpmCategoryServiceImpl implements BpmCategoryService {
@Override @Override
public void deleteCategory(Long id) { public void deleteCategory(Long id) {
// 校验存在 // 校验存在
validateCategoryExists(id); BpmCategoryDO category = validateCategoryExists(id);
// 校验是否被流程模型使用
Long count = modelService.getModelCountByCategory(category.getCode());
if (count > 0) {
throw exception(CATEGORY_DELETE_FAIL_MODEL_USED, category.getName());
}
// 删除 // 删除
bpmCategoryMapper.deleteById(id); bpmCategoryMapper.deleteById(id);
} }
private void validateCategoryExists(Long id) { private BpmCategoryDO validateCategoryExists(Long id) {
if (bpmCategoryMapper.selectById(id) == null) { BpmCategoryDO category = bpmCategoryMapper.selectById(id);
if (category == null) {
throw exception(CATEGORY_NOT_EXISTS); throw exception(CATEGORY_NOT_EXISTS);
} }
return category;
} }
@Override @Override

View File

@ -24,6 +24,14 @@ public interface BpmModelService {
*/ */
List<Model> getModelList(String name); List<Model> getModelList(String name);
/**
*
*
* @param category
* @return
*/
Long getModelCountByCategory(String category);
/** /**
* *
* *

View File

@ -88,6 +88,14 @@ public class BpmModelServiceImpl implements BpmModelService {
return modelQuery.list(); return modelQuery.list();
} }
@Override
public Long getModelCountByCategory(String category) {
return repositoryService.createModelQuery()
.modelCategory(category)
.modelTenantId(FlowableUtils.getTenantId())
.count();
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public String createModel(@Valid BpmModelSaveReqVO createReqVO) { public String createModel(@Valid BpmModelSaveReqVO createReqVO) {

View File

@ -4,11 +4,9 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.*;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
@ -59,6 +57,8 @@ import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -67,6 +67,7 @@ import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID;
@ -264,7 +265,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
// 3. 获取下一个将要执行的节点集合 // 3. 获取下一个将要执行的节点集合
FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); List<FlowNode> nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables);
List<ActivityNode> nextActivityNodes = convertList(nextFlowNodes, node -> new ActivityNode().setId(node.getId()) // 仅仅获取 UserTask 节点 TODO add from jason如果网关节点和网关节点相连获取下个 UserTask. 貌似有点不准。
List<FlowNode> nextUserTaskList = CollectionUtils.filterList(nextFlowNodes, node -> node instanceof UserTask);
List<ActivityNode> nextActivityNodes = convertList(nextUserTaskList, node -> new ActivityNode().setId(node.getId())
.setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())
.setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) .setStatus(BpmTaskStatusEnum.RUNNING.getStatus())
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node)) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node))
@ -449,7 +452,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
.setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus)
.setStartTime(DateUtils.of(activity.getStartTime())) .setStartTime(DateUtils.of(activity.getStartTime()))
.setEndTime(DateUtils.of(activity.getEndTime())) .setEndTime(DateUtils.of(activity.getEndTime()))
.setProcessInstanceId(activity.getProcessInstanceId()); .setProcessInstanceId(activity.getCalledProcessInstanceId());
approvalNodes.add(callActivity); approvalNodes.add(callActivity);
} }
}); });
@ -521,7 +524,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size()));
} }
if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) {
activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId());
} }
return activityNode; return activityNode;
}); });
@ -771,17 +774,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule)); processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule));
} }
// 3.2 流程名称 // 3.2 流程名称
BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting(); processInstanceBuilder.name(generateProcessInstanceName(userId, definition, processDefinitionInfo, variables));
if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) {
AdminUserRespDTO user = adminUserApi.getUser(userId).getCheckedData();
Map<String, Object> cloneVariables = new HashMap<>(variables);
cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables));
} else {
processInstanceBuilder.name(definition.getName().trim());
}
// 3.3 发起流程实例 // 3.3 发起流程实例
ProcessInstance instance = processInstanceBuilder.start(); ProcessInstance instance = processInstanceBuilder.start();
return instance.getId(); return instance.getId();
@ -817,6 +810,25 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
}); });
} }
private String generateProcessInstanceName(Long userId,
ProcessDefinition definition,
BpmProcessDefinitionInfoDO definitionInfo,
Map<String, Object> variables) {
if (definition == null || definitionInfo == null) {
return null;
}
BpmModelMetaInfoVO.TitleSetting titleSetting = definitionInfo.getTitleSetting();
if (titleSetting == null || !BooleanUtil.isTrue(titleSetting.getEnable())) {
return definition.getName();
}
AdminUserRespDTO user = adminUserApi.getUser(userId).getCheckedData();
Map<String, Object> cloneVariables = new HashMap<>(variables);
cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname());
cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now());
cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim());
return StrUtil.format(definitionInfo.getTitleSetting().getTitle(), cloneVariables);
}
@Override @Override
public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) {
// 1.1 校验流程实例存在 // 1.1 校验流程实例存在
@ -833,7 +845,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
.getProcessDefinitionInfo(instance.getProcessDefinitionId()); .getProcessDefinitionInfo(instance.getProcessDefinitionId());
Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo);
if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消
&& Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { && BooleanUtil.isFalse(processDefinitionInfo.getAllowCancelRunningProcess())) {
throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW);
} }
// 1.4 子流程不允许取消 // 1.4 子流程不允许取消
@ -900,64 +912,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
@Override @Override
public void processProcessInstanceCompleted(ProcessInstance instance) { public void processProcessInstanceCompleted(ProcessInstance instance) {
// 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 // 1.1 获取当前状态
FlowableUtils.execute(instance.getTenantId(), () -> { Integer status = (Integer) instance.getProcessVariables()
// 1.1 获取当前状态 .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS);
Integer status = (Integer) instance.getProcessVariables() String reason = (String) instance.getProcessVariables()
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON);
String reason = (String) instance.getProcessVariables() // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态
.get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了
// 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) {
// 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 status = BpmProcessInstanceStatusEnum.APPROVE.getStatus();
if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS,
status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); status);
runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, }
status);
// 2. 发送对应的消息通知
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
messageService.sendMessageWhenProcessInstanceApprove(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
messageService.sendMessageWhenProcessInstanceReject(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
}
// 3. 发送流程实例的状态事件
processInstanceEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
// 4. 流程后置通知
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
getProcessDefinitionInfo(instance.getProcessDefinitionId());
if (ObjUtil.isNotNull(processDefinitionInfo) &&
ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
} }
}
// 2. 发送对应的消息通知
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
messageService.sendMessageWhenProcessInstanceApprove(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance));
} else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) {
messageService.sendMessageWhenProcessInstanceReject(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason));
}
// 3. 发送流程实例的状态事件
processInstanceEventPublisher.sendProcessInstanceResultEvent(
BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status));
// 4. 流程后置通知
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
getProcessDefinitionInfo(instance.getProcessDefinitionId());
if (ObjUtil.isNotNull(processDefinitionInfo) &&
ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) {
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting();
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
}
}
});
} }
@Override @Override
public void processProcessInstanceCreated(ProcessInstance instance) { public void processProcessInstanceCreated(ProcessInstance instance) {
// 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService.
FlowableUtils.execute(instance.getTenantId(), () -> { getProcessDefinitionInfo(instance.getProcessDefinitionId());
// 流程前置通知 ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(instance.getProcessDefinitionId());
BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. if (processDefinition == null || processDefinitionInfo == null) {
getProcessDefinitionInfo(instance.getProcessDefinitionId()); return;
if (ObjUtil.isNull(processDefinitionInfo) || }
ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
return; // 自定义标题。目的:主要处理子流程的标题无法处理
// 注意:必须使用 TransactionSynchronizationManager 事务提交后,否则不生效!!!
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
String name = generateProcessInstanceName(Long.valueOf(instance.getStartUserId()),
processDefinition, processDefinitionInfo, instance.getProcessVariables());
if (ObjUtil.notEqual(instance.getName(), name)) {
runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name);
}
} }
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
}); });
// 流程前置通知
if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
return;
}
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
} }
} }

View File

@ -230,10 +230,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
if (StrUtil.isNotBlank(pageVO.getName())) { if (StrUtil.isNotBlank(pageVO.getName())) {
taskQuery.taskNameLike("%" + pageVO.getName() + "%"); taskQuery.taskNameLike("%" + pageVO.getName() + "%");
} }
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { // if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); // taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); // taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
} // }
// 执行查询 // 执行查询
long count = taskQuery.count(); long count = taskQuery.count();
if (count == 0) { if (count == 0) {
@ -244,6 +244,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 特殊:强制移除自动完成的“发起人”节点 // 特殊:强制移除自动完成的“发起人”节点
// 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤 // 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤
tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID)); tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID));
// TODO @芋艿https://t.zsxq.com/MNzqp 【flowable bug】taskCreatedAfter、taskCreatedBefore 拼接的是 OR
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
tasks.removeIf(task -> task.getCreateTime() == null
|| task.getCreateTime().before(DateUtils.of(pageVO.getCreateTime()[0]))
|| task.getCreateTime().after(DateUtils.of(pageVO.getCreateTime()[1])));
}
return new PageResult<>(tasks, count); return new PageResult<>(tasks, count);
} }
@ -259,16 +265,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
if (StrUtil.isNotEmpty(pageVO.getCategory())) { if (StrUtil.isNotEmpty(pageVO.getCategory())) {
taskQuery.taskCategory(pageVO.getCategory()); taskQuery.taskCategory(pageVO.getCategory());
} }
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { // if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); // taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); // taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
} // }
// 执行查询 // 执行查询
long count = taskQuery.count(); long count = taskQuery.count();
if (count == 0) { if (count == 0) {
return PageResult.empty(); return PageResult.empty();
} }
List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); List<HistoricTaskInstance> tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
// TODO @芋艿https://t.zsxq.com/MNzqp 【flowable bug】taskCreatedAfter、taskCreatedBefore 拼接的是 OR
if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) {
tasks.removeIf(task -> task.getCreateTime() == null
|| task.getCreateTime().before(DateUtils.of(pageVO.getCreateTime()[0]))
|| task.getCreateTime().after(DateUtils.of(pageVO.getCreateTime()[1])));
}
return new PageResult<>(tasks, count); return new PageResult<>(tasks, count);
} }
@ -886,7 +898,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) { if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
return; return;
} }
runExecutionIds.add(task.getExecutionId()); if (task.getExecutionId() != null) {
runExecutionIds.add(task.getExecutionId());
}
// 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务 // 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务
if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记 if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记
@ -1367,7 +1381,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));
if (userTaskElement.getId().equals(START_USER_NODE_ID) if (userTaskElement.getId().equals(START_USER_NODE_ID)
&& (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核
|| Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核
&& ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
.setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));

View File

@ -85,10 +85,15 @@ public class BpmCallActivityListener implements ExecutionListener {
// 2.2 使用表单值,并兜底字符串转 Long 失败时使用主流程发起人 // 2.2 使用表单值,并兜底字符串转 Long 失败时使用主流程发起人
try { try {
FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue));
} catch (Exception e) { } catch (NumberFormatException ex) {
log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", try {
DELEGATE_EXPRESSION, formFieldValue); List<Long> formFieldValues = JsonUtils.parseArray(formFieldValue, Long.class);
FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); FlowableUtils.setAuthenticatedUserId(formFieldValues.get(0));
} catch (Exception e) {
log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]",
DELEGATE_EXPRESSION, formFieldValue);
FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId()));
}
} }
} }
} }

View File

@ -45,14 +45,16 @@ spring:
initial-size: 5 # 初始连接数 initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量 min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -21,7 +21,6 @@ spring:
autoconfigure: autoconfigure:
exclude: exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
datasource: datasource:
druid: # Druid 【监控】相关的全局配置 druid: # Druid 【监控】相关的全局配置
web-stat-filter: web-stat-filter:
@ -46,14 +45,16 @@ spring:
initial-size: 1 # 初始连接数 initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量 min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒1 分钟)
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;

View File

@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction; import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.followup.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category; package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -4,9 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fhs.core.trans.anno.Trans; import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO; import com.fhs.core.trans.vo.VO;
@ -59,7 +58,7 @@ public class CrmProductRespVO implements VO {
private String description; private String description;
@Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31926") @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31926")
@Trans(type = TransType.AUTO_TRANS, key = AdminUserApi.PREFIX, @Trans(type = TransType.SIMPLE, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
fields = "nickname", ref = "ownerUserName") fields = "nickname", ref = "ownerUserName")
private Long ownerUserId; private Long ownerUserId;
@Schema(description = "负责人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @Schema(description = "负责人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@ -67,7 +66,7 @@ public class CrmProductRespVO implements VO {
private String ownerUserName; private String ownerUserName;
@Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@Trans(type = TransType.AUTO_TRANS, key = AdminUserApi.PREFIX, @Trans(type = TransType.SIMPLE, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
fields = "nickname", ref = "creatorName") fields = "nickname", ref = "creatorName")
private String creator; private String creator;
@Schema(description = "创建人名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @Schema(description = "创建人名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan;
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO;
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -44,14 +44,16 @@ spring:
initial-size: 5 # 初始连接数 initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量 min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -20,7 +20,6 @@ spring:
# 数据源配置项 # 数据源配置项
autoconfigure: autoconfigure:
exclude: exclude:
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
datasource: datasource:
druid: # Druid 【监控】相关的全局配置 druid: # Druid 【监控】相关的全局配置
web-stat-filter: web-stat-filter:
@ -45,14 +44,16 @@ spring:
initial-size: 1 # 初始连接数 initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量 min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; import cn.iocoder.yudao.module.erp.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -44,14 +44,16 @@ spring:
initial-size: 5 # 初始连接数 initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量 min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -20,7 +20,6 @@ spring:
# 数据源配置项 # 数据源配置项
autoconfigure: autoconfigure:
exclude: exclude:
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
datasource: datasource:
druid: # Druid 【监控】相关的全局配置 druid: # Druid 【监控】相关的全局配置
web-stat-filter: web-stat-filter:
@ -45,14 +44,16 @@ spring:
initial-size: 1 # 初始连接数 initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量 min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -121,6 +121,7 @@
<dependency> <dependency>
<groupId>de.codecentric</groupId> <groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 --> <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
<optional>true</optional>
</dependency> </dependency>
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.config.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.erp.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;

View File

@ -6,11 +6,10 @@ import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender;
import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
import cn.iocoder.yudao.module.infra.websocket.message.DemoReceiveMessage; import cn.iocoder.yudao.module.infra.websocket.message.DemoReceiveMessage;
import cn.iocoder.yudao.module.infra.websocket.message.DemoSendMessage; import cn.iocoder.yudao.module.infra.websocket.message.DemoSendMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import javax.annotation.Resource;
/** /**
* WebSocket * WebSocket
* *
@ -19,7 +18,8 @@ import javax.annotation.Resource;
@Component @Component
public class DemoWebSocketMessageListener implements WebSocketMessageListener<DemoSendMessage> { public class DemoWebSocketMessageListener implements WebSocketMessageListener<DemoSendMessage> {
@Resource @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@Autowired(required = false) // 由于 yudao.websocket.enable 配置项,可以关闭 WebSocket 的功能,所以这里只能不强制注入
private WebSocketMessageSender webSocketMessageSender; private WebSocketMessageSender webSocketMessageSender;
@Override @Override

View File

@ -45,14 +45,16 @@ spring:
initial-size: 5 # 初始连接数 initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量 min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒1 分钟)
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -22,10 +22,6 @@ spring:
autoconfigure: autoconfigure:
exclude: exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
- de.codecentric.boot.admin.server.cloud.config.AdminServerDiscoveryAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
datasource: datasource:
druid: # Druid 【监控】相关的全局配置 druid: # Druid 【监控】相关的全局配置
web-stat-filter: web-stat-filter:
@ -50,14 +46,16 @@ spring:
initial-size: 1 # 初始连接数 initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量 min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量 max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒1 分钟)
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒10 分钟)
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true test-while-idle: true
test-on-borrow: false test-on-borrow: false
test-on-return: false test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master primary: master
datasource: datasource:
master: master:

View File

@ -19,7 +19,7 @@ import java.time.LocalDateTime;
#end #end
#end #end
## 处理 Excel 导出 ## 处理 Excel 导出
import com.alibaba.excel.annotation.*; import cn.idev.excel.annotation.*;
#foreach ($column in $columns) #foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典 #if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName}; import ${DictFormatClassName};
@ -50,4 +50,4 @@ public class ${sceneEnum.prefixClass}${table.className}RespVO {
#end #end
#end #end
} }

View File

@ -15,7 +15,7 @@ import ${BaseDOClassName};
## 处理 Excel 导出 + Schema 注解(仅 DO 模式) ## 处理 Excel 导出 + Schema 注解(仅 DO 模式)
#if ($voType == 20) #if ($voType == 20)
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.excel.annotation.*; import cn.idev.excel.annotation.*;
#foreach ($column in $columns) #foreach ($column in $columns)
#if ("$!column.dictType" != "")## 有设置数据字典 #if ("$!column.dictType" != "")## 有设置数据字典
import ${DictFormatClassName}; import ${DictFormatClassName};
@ -100,4 +100,4 @@ public class ${table.className}DO extends BaseDO {
#end #end
#end #end
} }

View File

@ -138,6 +138,7 @@ watch(
() => props.${subJoinColumn.javaField}, () => props.${subJoinColumn.javaField},
(val: number) => { (val: number) => {
if (!val) { if (!val) {
list.value = [] // 清空列表
return return
} }
queryParams.${subJoinColumn.javaField} = val queryParams.${subJoinColumn.javaField} = val

View File

@ -353,6 +353,7 @@ const handleDelete = async (id: number) => {
// 发起删除 // 发起删除
await ${simpleClassName}Api.delete${simpleClassName}(id) await ${simpleClassName}Api.delete${simpleClassName}(id)
message.success(t('common.delSuccess')) message.success(t('common.delSuccess'))
currentRow.value = {}
// 刷新列表 // 刷新列表
await getList() await getList()
} catch {} } catch {}

View File

@ -1,76 +1,56 @@
<configuration> <configuration>
<!-- 引用 Spring Boot 的 logback 基础配置 --> <!-- 参考 org/springframework/boot/logging/logback/defaults.xml 配置,优化 CONSOLE_LOG_PATTERN、FILE_LOG_PATTERN -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" /> <!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 -->
<!-- 变量 yudao.info.base-package基础业务包 --> <!-- CONSOLE_LOG_PATTERN 相比 FILE_LOG_PATTERN 多了 highlight、cyan 等高亮 -->
<springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/> <property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n"/>
<!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level级别从左显示 5 个字符宽度,%msg日志消息%n是换行符 --> <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n"/>
<property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} | %highlight(${LOG_LEVEL_PATTERN:-%5p} ${PID:- }) | %boldYellow(%thread [%tid]) %boldGreen(%-40.40logger{39}) | %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- 控制台 Appender --> <!-- 控制台 Appender -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">      <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${CONSOLE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
</appender> </appender>
<!-- 文件 Appender --> <!-- 文件 Appender -->
<!-- 参考 Spring Boot 的 file-appender.xml 编写 --> <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <pattern>${FILE_LOG_PATTERN}</pattern>
<pattern>${PATTERN_DEFAULT}</pattern>
</layout>
</encoder> </encoder>
<!-- 日志文件名 --> <!-- 日志文件名 -->
<file>${LOG_FILE}</file> <file>${LOG_FILE}</file>
<!-- 滚动策略:基于【每天 + 大小】创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后的日志文件名 --> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern> <!-- 日志文件输出的文件名 -->
<fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern> <maxHistory>30</maxHistory> <!-- 日志文件的保留天数 -->
<!-- 启动服务时,是否清理历史日志,一般不建议清理 --> <maxFileSize>10MB</maxFileSize> <!-- 日志文件,到达多少容量,进行滚动 -->
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
<!-- 日志文件,到达多少容量,进行滚动 -->
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
<!-- 日志文件的总大小0 表示不限制 -->
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
<!-- 日志文件的保留天数 -->
<maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
</rollingPolicy> </rollingPolicy>
</appender> </appender>
<!-- 异步写入日志,提升性能 --> <!-- 异步写入日志,提升性能 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --> <discardingThreshold>0</discardingThreshold> <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
<discardingThreshold>0</discardingThreshold> <queueSize>512</queueSize> <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
<queueSize>256</queueSize>
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</appender> </appender>
<!-- SkyWalking GRPC 日志收集实现日志中心。注意SkyWalking 8.4.0 版本开始支持 --> <!-- SkyWalking AppenderGRPC 日志收集,实现日志中心 -->
<appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"> <!--
<appender name="SKYWALKING" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout"> <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${PATTERN_DEFAULT}</pattern> <pattern>[%tid] ${FILE_LOG_PATTERN}</pattern>
</layout> </layout>
</encoder> </encoder>
</appender> </appender>
-->
<!-- 本地环境 --> <root level="INFO">
<springProfile name="local"> <appender-ref ref="STDOUT"/>
<root level="INFO"> <!-- 本地环境下如果不想【FILE】打印日志可以注释掉本行 -->
<appender-ref ref="STDOUT"/> <appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 --> <!-- 如果想接入【SkyWalking 日志服务】,可以取消注释掉本行 -->
<appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 --> <!-- <appender-ref ref="SKYWALKING"/> -->
</root> </root>
</springProfile>
<!-- 其它环境 -->
<springProfile name="dev,test,stage,prod,default">
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ASYNC"/>
<appender-ref ref="GRPC"/>
</root>
</springProfile>
</configuration> </configuration>

View File

@ -6,7 +6,7 @@ import java.util.*;
import java.util.*; import java.util.*;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*; import cn.idev.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@ -57,4 +57,4 @@ public class InfraStudentRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@ -6,7 +6,7 @@ import java.util.*;
import java.util.*; import java.util.*;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*; import cn.idev.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@ -57,4 +57,4 @@ public class InfraStudentRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@ -6,7 +6,7 @@ import java.util.*;
import java.util.*; import java.util.*;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*; import cn.idev.excel.annotation.*;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
@ -57,4 +57,4 @@ public class InfraStudentRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

Some files were not shown because too many files have changed in this diff Show More