This commit is contained in:
jack ning
2025-10-22 15:50:31 +08:00
parent 6bbeb621c8
commit 8674e9e7fb
3 changed files with 115 additions and 14 deletions

View File

@@ -93,20 +93,26 @@ public class FreeSwitchDataSourceConfig {
@Bean(name = "freeswitchEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean freeswitchEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("freeswitchDataSource") DataSource dataSource) {
@Qualifier("freeswitchDataSource") DataSource dataSource,
org.springframework.core.env.Environment env) {
log.info("Creating FreeSWITCH EntityManagerFactory");
// 允许通过属性覆盖,默认在启用时对 bytedesk_freeswitch 执行表结构创建/更新
// 支持值none|validate|update|create|create-drop
String ddlAuto = env.getProperty("bytedesk.datasource.freeswitch.ddl-auto", "update");
log.info("FreeSWITCH JPA ddl-auto={}", ddlAuto);
java.util.Map<String, Object> jpaProps = new java.util.HashMap<>();
jpaProps.put("hibernate.hbm2ddl.auto", ddlAuto);
jpaProps.put("hibernate.show_sql", "false");
jpaProps.put("hibernate.format_sql", "false");
jpaProps.put("hibernate.jdbc.time_zone", "Asia/Shanghai");
return builder
.dataSource(dataSource)
.packages("com.bytedesk.call.freeswitch") // FreeSWITCH 实体类所在包
.packages("com.bytedesk.call.freeswitch") // 仅扫描 freeswitch 实体
.persistenceUnit("freeswitch")
.properties(java.util.Map.of(
// 只读取,不创建/更新表结构
"hibernate.hbm2ddl.auto", "none",
"hibernate.show_sql", "false",
"hibernate.format_sql", "false",
// 设置 Hibernate 时区
"hibernate.jdbc.time_zone", "Asia/Shanghai"
))
.properties(jpaProps)
.build();
}

View File

@@ -0,0 +1,93 @@
/*
* 目的:当 bytedesk.datasource.freeswitch.enabled 未开启时,将 com.bytedesk.call.freeswitch
* 从主库 entityManagerFactory 的 packagesToScan 中剔除,避免主库对 freeswitch 实体建表/写入。
* 位置freeswitch 模块内部;不修改全局 starter 配置,完全满足“在 freeswitch 文件夹里面配置”。
*/
package com.bytedesk.call.freeswitch;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@Configuration
@ConditionalOnProperty(
prefix = "bytedesk.datasource.freeswitch",
name = "enabled",
havingValue = "false",
matchIfMissing = true
)
public class FreeSwitchEntityScanCustomizer {
private static final String PRIMARY_EMF_BEAN_NAME = "entityManagerFactory";
private static final String PACKAGES_TO_SCAN_PROP = "packagesToScan";
private static final String FREESWITCH_PACKAGE = "com.bytedesk.call.freeswitch";
@Bean
public static BeanFactoryPostProcessor freeSwitchEntityExclusionPostProcessor() {
return new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (!beanFactory.containsBeanDefinition(PRIMARY_EMF_BEAN_NAME)) {
return;
}
BeanDefinition bd = beanFactory.getBeanDefinition(PRIMARY_EMF_BEAN_NAME);
PropertyValue pv = bd.getPropertyValues().getPropertyValue(PACKAGES_TO_SCAN_PROP);
if (pv == null) {
// 主库未显式设置 packagesToScanSpring Boot 通常会回退为应用主包;
// 此处尽量安全处理:不做任何变更,避免误伤。
return;
}
Object value = pv.getValue();
List<String> packages = new ArrayList<>();
if (value instanceof String[]) {
for (String s : (String[]) value) {
if (StringUtils.hasText(s)) packages.add(s);
}
} else if (value instanceof List<?>) {
for (Object o : (List<?>) value) {
if (o instanceof String && StringUtils.hasText((String) o)) {
packages.add((String) o);
} else if (o instanceof TypedStringValue) {
String s = ((TypedStringValue) o).getValue();
if (StringUtils.hasText(s)) packages.add(s);
}
}
} else if (value instanceof TypedStringValue) {
String s = ((TypedStringValue) value).getValue();
if (StringUtils.hasText(s)) packages.add(s);
}
if (packages.isEmpty()) {
return;
}
// 过滤掉 freeswitch 包及其子包
List<String> filtered = packages.stream()
.filter(p -> !isSameOrChildPackage(p, FREESWITCH_PACKAGE))
.toList();
if (!filtered.equals(packages)) {
bd.getPropertyValues().add(PACKAGES_TO_SCAN_PROP, filtered.toArray(String[]::new));
}
}
private boolean isSameOrChildPackage(String pkg, String target) {
if (!StringUtils.hasText(pkg) || !StringUtils.hasText(target)) return false;
if (Objects.equals(pkg, target)) return true;
return pkg.startsWith(target + ".");
}
};
}
}

View File

@@ -239,13 +239,15 @@ services:
volumes:
# 配置文件目录 - 使用本地配置文件覆盖容器内的配置(经验证实际使用 /usr/local/freeswitch/etc/freeswitch
- ../../../../deploy/freeswitch/conf:/usr/local/freeswitch/etc/freeswitch
# 语音文件目录
# 数据持久化目录
- freeswitch_data:/usr/local/freeswitch/db
# - freeswitch_data:/usr/local/freeswitch/db
- ../../../../deploy/freeswitch/db:/usr/local/freeswitch/db
# 日志目录
- freeswitch_logs:/usr/local/freeswitch/log
# - freeswitch_logs:/usr/local/freeswitch/log
- ../../../../deploy/freeswitch/log:/usr/local/freeswitch/log
# 录音目录
- freeswitch_recordings:/usr/local/freeswitch/recordings
# - freeswitch_recordings:/usr/local/freeswitch/recordings
- ../../../../deploy/freeswitch/recordings:/usr/local/freeswitch/recordings
depends_on:
- bytedesk-mysql
networks: