Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/bpm

# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
This commit is contained in:
YunaiV
2024-10-03 11:28:22 +08:00
320 changed files with 10940 additions and 5311 deletions

View File

@ -290,7 +290,15 @@ public class CollectionUtils {
return valueFunc.apply(t);
}
public static <T, V extends Comparable<? super V>> V getSumValue(List<T> from, Function<T, V> valueFunc,
public static <T, V extends Comparable<? super V>> T getMinObject(List<T> from, Function<T, V> valueFunc) {
if (CollUtil.isEmpty(from)) {
return null;
}
assert from.size() > 0; // 断言,避免告警
return from.stream().min(Comparator.comparing(valueFunc)).get();
}
public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
BinaryOperator<V> accumulator) {
return getSumValue(from, valueFunc, accumulator, null);
}

View File

@ -21,6 +21,7 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import java.util.HashMap;
import java.util.HashSet;
@ -141,7 +142,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
return deptExpression;
}
// 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即WHERE (dept_id IN ? OR user_id = ?)
return new Parenthesis(new OrExpression(deptExpression, userExpression));
return new ParenthesedExpressionList(new OrExpression(deptExpression, userExpression));
}
private Expression buildDeptExpression(String tableName, Alias tableAlias, Set<Long> deptIds) {
@ -157,7 +158,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
// 拼接条件
return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
// Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号
new Parenthesis(new ExpressionList<LongValue>(CollectionUtils.convertList(deptIds, LongValue::new))));
new ParenthesedExpressionList(new ExpressionList<LongValue>(CollectionUtils.convertList(deptIds, LongValue::new))));
}
private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) {

View File

@ -8,10 +8,10 @@ import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionIntercepto
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.schema.Column;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -81,7 +81,7 @@ public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest {
Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN);
ExpressionList<LongValue> values = new ExpressionList<>(new LongValue(10L),
new LongValue(20L));
return new InExpression(column, new Parenthesis((values)));
return new InExpression(column, new ParenthesedExpressionList((values)));
}
};

View File

@ -58,6 +58,11 @@
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId> <!-- 解决 https://github.com/alibaba/easyexcel/issues/3954 问题 -->
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.framework.mybatis.config;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
@ -42,9 +41,6 @@ public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor
// TODO 芋艿:暂时没有找到特别合适的地方,先放在这里
setJobStoreDriverIfPresent(environment, dbType);
// 初始化 SQL 静态变量
SqlConstants.init(dbType);
// 如果非 NONE则不进行处理
IdType idType = getIdType(environment);
if (idType != IdType.NONE) {
@ -55,7 +51,7 @@ public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor
setIdType(environment, IdType.INPUT);
return;
}
// 情况二,自增 ID适合 MySQL 等直接自增的数据库
// 情况二,自增 ID适合 MySQL、DM 达梦等直接自增的数据库
setIdType(environment, IdType.AUTO);
}
@ -86,6 +82,10 @@ public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor
case SQL_SERVER2005:
driverClass = "org.quartz.impl.jdbcjobstore.MSSQLDelegate";
break;
case DM:
case KINGBASE_ES:
driverClass = "org.quartz.impl.jdbcjobstore.StdJDBCDelegate";
break;
}
// 设置 driverClass 变量
if (StrUtil.isNotEmpty(driverClass)) {

View File

@ -18,10 +18,17 @@ import java.util.stream.Collectors;
@AllArgsConstructor
public enum DbTypeEnum {
/**
* H2
*
* 注意H2 不支持 find_in_set 函数
*/
H2(DbType.H2, "H2", ""),
/**
* MySQL
*/
MY_SQL( DbType.MYSQL, "MySQL", "FIND_IN_SET('#{value}', #{column}) <> 0"),
MY_SQL(DbType.MYSQL, "MySQL", "FIND_IN_SET('#{value}', #{column}) <> 0"),
/**
* Oracle
@ -39,6 +46,10 @@ public enum DbTypeEnum {
* SQL Server
*/
SQL_SERVER(DbType.SQL_SERVER, "Microsoft SQL Server", "CHARINDEX(',' + #{value} + ',', ',' + #{column} + ',') <> 0"),
/**
* SQL Server 2005
*/
SQL_SERVER2005(DbType.SQL_SERVER2005, "Microsoft SQL Server 2005", "CHARINDEX(',' + #{value} + ',', ',' + #{column} + ',') <> 0"),
/**
* 达梦

View File

@ -1,21 +0,0 @@
package cn.iocoder.yudao.framework.mybatis.core.enums;
import com.baomidou.mybatisplus.annotation.DbType;
/**
* SQL相关常量类
*
* @author 芋道源码
*/
public class SqlConstants {
/**
* 数据库的类型
*/
public static DbType DB_TYPE;
public static void init(DbType dbType) {
DB_TYPE = dbType;
}
}

View File

@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
import cn.iocoder.yudao.framework.common.pojo.SortingField;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
@ -22,7 +22,6 @@ import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
/**
* 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
@ -135,11 +134,6 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return selectList(new LambdaQueryWrapper<T>().in(field, values));
}
@Deprecated
default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
}
default List<T> selectList(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
return selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
}
@ -151,7 +145,8 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
*/
default Boolean insertBatch(Collection<T> entities) {
// 特殊SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
if (Objects.equals(SqlConstants.DB_TYPE, DbType.SQL_SERVER)) {
DbType dbType = JdbcUtils.getDbType();
if (JdbcUtils.isSQLServer(dbType)) {
entities.forEach(this::insert);
return CollUtil.isNotEmpty(entities);
}
@ -166,7 +161,8 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
*/
default Boolean insertBatch(Collection<T> entities, int size) {
// 特殊SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
if (Objects.equals(SqlConstants.DB_TYPE, DbType.SQL_SERVER)) {
DbType dbType = JdbcUtils.getDbType();
if (JdbcUtils.isSQLServer(dbType)) {
entities.forEach(this::insert);
return CollUtil.isNotEmpty(entities);
}
@ -185,10 +181,6 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return Db.updateBatchById(entities, size);
}
default Boolean insertOrUpdateBatch(Collection<T> collection) {
return Db.saveOrUpdateBatch(collection);
}
default int delete(String field, String value) {
return delete(new QueryWrapper<T>().eq(field, value));
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.mybatis.core.query;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@ -147,8 +147,8 @@ public class QueryWrapperX<T> extends QueryWrapper<T> {
* @return this
*/
public QueryWrapperX<T> limitN(int n) {
Assert.notNull(SqlConstants.DB_TYPE, "获取不到数据库的类型");
switch (SqlConstants.DB_TYPE) {
DbType dbType = JdbcUtils.getDbType();
switch (dbType) {
case ORACLE:
case ORACLE_12C:
super.le("ROWNUM", n);
@ -157,7 +157,7 @@ public class QueryWrapperX<T> extends QueryWrapper<T> {
case SQL_SERVER2005:
super.select("TOP " + n + " *"); // 由于 SQL Server 是通过 SELECT TOP 1 实现限制一条,所以只好使用 * 查询剩余字段
break;
default:
default: // MySQL、PostgreSQL、DM 达梦、KingbaseES 大金都是采用 LIMIT 实现
super.last("LIMIT " + n);
}
return this;

View File

@ -1,9 +1,11 @@
package cn.iocoder.yudao.framework.mybatis.core.util;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.mybatisplus.annotation.DbType;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import javax.sql.DataSource;
import java.sql.Connection;
@ -49,8 +51,13 @@ public class JdbcUtils {
* @return DB 类型
*/
public static DbType getDbType() {
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class);
DataSource dataSource = dynamicRoutingDataSource.determineDataSource();
DataSource dataSource;
try {
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class);
dataSource = dynamicRoutingDataSource.determineDataSource();
} catch (NoSuchBeanDefinitionException e) {
dataSource = SpringUtils.getBean(DataSource.class);
}
try (Connection conn = dataSource.getConnection()) {
return DbTypeEnum.find(conn.getMetaData().getDatabaseProductName());
} catch (SQLException e) {
@ -58,4 +65,25 @@ public class JdbcUtils {
}
}
/**
* 判断 JDBC 连接是否为 SQLServer 数据库
*
* @param url JDBC 连接
* @return 是否为 SQLServer 数据库
*/
public static boolean isSQLServer(String url) {
DbType dbType = getDbType(url);
return isSQLServer(dbType);
}
/**
* 判断 JDBC 连接是否为 SQLServer 数据库
*
* @param dbType DB 类型
* @return 是否为 SQLServer 数据库
*/
public static boolean isSQLServer(DbType dbType) {
return ObjectUtils.equalsAny(dbType, DbType.SQL_SERVER, DbType.SQL_SERVER2005);
}
}

View File

@ -96,7 +96,6 @@ public class MyBatisUtils {
* @return sql
*/
public static String findInSet(String column, Object value) {
// 这里不用SqlConstants.DB_TYPE因为它是使用 primary 数据源的 url 推断出来的类型
DbType dbType = JdbcUtils.getDbType();
return DbTypeEnum.getFindInSetTemplate(dbType)
.replace("#{column}", column)

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.security.config;
import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
@ -38,14 +37,6 @@ public class YudaoSecurityAutoConfiguration {
@Resource
private SecurityProperties securityProperties;
/**
* 处理用户未登录拦截的切面的 Bean
*/
@Bean
public PreAuthenticatedAspect preAuthenticatedAspect() {
return new PreAuthenticatedAspect();
}
/**
* 认证失败处理类 Bean
*/

View File

@ -129,17 +129,15 @@ public class YudaoWebSecurityConfigurerAdapter {
.authorizeHttpRequests(c -> c
// 1.1 静态资源,可匿名访问
.requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()
// 1.1 设置 @PermitAll 无需认证
// 1.2 设置 @PermitAll 无需认证
.requestMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.HEAD, permitAllUrls.get(HttpMethod.HEAD).toArray(new String[0])).permitAll()
.requestMatchers(HttpMethod.PATCH, permitAllUrls.get(HttpMethod.PATCH).toArray(new String[0])).permitAll()
// 1.2 基于 yudao.security.permit-all-urls 无需认证
// 1.3 基于 yudao.security.permit-all-urls 无需认证
.requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
// 1.3 设置 App API 无需认证
.requestMatchers(buildAppApi("/**")).permitAll()
)
// ②:每个项目的自定义规则
.authorizeHttpRequests(c -> authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(c)))

View File

@ -1,17 +0,0 @@
package cn.iocoder.yudao.framework.security.core.annotations;
import java.lang.annotation.*;
/**
* 声明用户需要登录
*
* 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登录
*
* @author 芋道源码
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface PreAuthenticated {
}

View File

@ -1,25 +0,0 @@
package cn.iocoder.yudao.framework.security.core.aop;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@Aspect
@Slf4j
public class PreAuthenticatedAspect {
@Around("@annotation(preAuthenticated)")
public Object around(ProceedingJoinPoint joinPoint, PreAuthenticated preAuthenticated) throws Throwable {
if (SecurityFrameworkUtils.getLoginUser() == null) {
throw exception(UNAUTHORIZED);
}
return joinPoint.proceed();
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.test.core.ut;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
@ -44,6 +45,9 @@ public class BaseDbAndRedisUnitTest {
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedisAutoConfiguration.class, // Spring Redis 自动配置类
RedissonAutoConfiguration.class, // Redisson 自动配置类
// 其它配置类
SpringUtil.class
})
public static class Application {
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.test.core.ut;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
@ -36,6 +37,9 @@ public class BaseDbUnitTest {
YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
MybatisPlusJoinAutoConfiguration.class, // MyBatis 的Join配置类
// 其它配置类
SpringUtil.class
})
public static class Application {
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.test.core.ut;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration;
import org.redisson.spring.starter.RedissonAutoConfiguration;
@ -25,6 +26,9 @@ public class BaseRedisUnitTest {
RedisAutoConfiguration.class, // Spring Redis 自动配置类
YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类
RedissonAutoConfiguration.class, // Redisson 自动配置类
// 其它配置类
SpringUtil.class
})
public static class Application {
}

View File

@ -134,6 +134,11 @@ public class RandomUtils {
@SafeVarargs
public static <T> List<T> randomPojoList(Class<T> clazz, Consumer<T>... consumers) {
int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH);
return randomPojoList(clazz, size, consumers);
}
@SafeVarargs
public static <T> List<T> randomPojoList(Class<T> clazz, int size, Consumer<T>... consumers) {
return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers))
.collect(Collectors.toList());
}

View File

@ -62,6 +62,10 @@ public class BannerApplicationRunner implements ApplicationRunner {
if (isNotPresent("cn.iocoder.yudao.module.ai.framework.web.config.AiWebConfiguration")) {
System.out.println("[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
}
// IOT 物联网
if (isNotPresent("cn.iocoder.yudao.module.iot.framework.web.config.IotWebConfiguration")) {
System.out.println("[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
}
});
}

View File

@ -378,6 +378,12 @@ public class GlobalExceptionHandler {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
}
// 9. IOT 物联网
if (message.contains("iot_")) {
log.error("[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
}
return null;
}

View File

@ -85,7 +85,7 @@ public class YudaoWebSocketAutoConfiguration {
// ==================== Sender 相关 ====================
@Configuration
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true)
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local")
public class LocalWebSocketMessageSenderConfiguration {
@Bean
@ -96,7 +96,7 @@ public class YudaoWebSocketAutoConfiguration {
}
@Configuration
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true)
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis")
public class RedisWebSocketMessageSenderConfiguration {
@Bean
@ -114,7 +114,7 @@ public class YudaoWebSocketAutoConfiguration {
}
@Configuration
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true)
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq")
public class RocketMQWebSocketMessageSenderConfiguration {
@Bean
@ -133,7 +133,7 @@ public class YudaoWebSocketAutoConfiguration {
}
@Configuration
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true)
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq")
public class RabbitMQWebSocketMessageSenderConfiguration {
@Bean
@ -162,7 +162,7 @@ public class YudaoWebSocketAutoConfiguration {
}
@Configuration
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true)
@ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka")
public class KafkaWebSocketMessageSenderConfiguration {
@Bean