rename com.imyeyu.server to com.imyeyu.api

This commit is contained in:
Timi
2025-07-22 15:26:14 +08:00
parent e816b885b2
commit 323e038e86
340 changed files with 1174 additions and 1175 deletions

View File

@@ -0,0 +1,35 @@
package com.imyeyu.api.config;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.Arrays;
/**
* 异步线程池配置
*
* @author 夜雨
* @since 2023-08-21 16:22
*/
@Slf4j
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public @NotNull AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (e, method, obj) -> {
log.info("Exception message - {}", e.getMessage());
log.info("Method name - {}", method.getName());
log.info("Parameter values - {}", Arrays.toString(obj));
if (e instanceof Exception exception) {
log.info("exception: {}", exception.getMessage());
}
log.error("async uncaught error", e);
};
}
}

View File

@@ -0,0 +1,16 @@
package com.imyeyu.api.config;
import com.google.gson.Gson;
import org.springframework.context.annotation.Configuration;
/**
* @author 夜雨
* @since 2025-05-16 18:53
*/
@Configuration
public class BeanConfig {
public Gson gson() {
return new Gson();
}
}

View File

@@ -0,0 +1,55 @@
package com.imyeyu.api.config;
import jakarta.servlet.Filter;
import lombok.Data;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
/**
* 跨域控制
*
* @author 夜雨
* @since 2021-05-14 09:21
*/
@Data
@Configuration
@EnableAutoConfiguration
@ConfigurationProperties(prefix = "cors")
public class CORSConfig {
/** 允许跨域的地址 */
private String[] allowOrigin;
/** 是否允许请求带有验证信息 */
private boolean allowCredentials;
/** 允许请求的方法 */
private String allowMethods;
/** 允许服务端访问的客户端请求头 */
private String allowHeaders;
@Bean
public FilterRegistrationBean<Filter> corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedHeader(allowHeaders);
config.addAllowedMethod(allowMethods);
config.setAllowCredentials(allowCredentials);
config.setAllowedOriginPatterns(Arrays.asList(allowOrigin));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}

View File

@@ -0,0 +1,24 @@
package com.imyeyu.api.config;
import com.mongodb.client.MongoClient;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 夜雨
* @since 2024-02-23 10:55
*/
@Configuration
public class MongoConfig {
@Value("${spring.data.mongodb.database}")
private String db;
@Bean
public GridFSBucket gridFSBucket(MongoClient mongoClient) {
return GridFSBuckets.create(mongoClient.getDatabase(db));
}
}

View File

@@ -0,0 +1,268 @@
package com.imyeyu.api.config;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.imyeyu.api.modules.blog.entity.ArticleRanking;
import com.imyeyu.api.modules.common.entity.Multilingual;
import com.imyeyu.spring.bean.RedisConfigParams;
import com.imyeyu.spring.config.AbstractRedisConfig;
import com.imyeyu.spring.util.Redis;
import com.imyeyu.spring.util.RedisSerializers;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.lang.Nullable;
import java.time.Duration;
/**
* Redis 配置
*
* @author 夜雨
* @since 2021-02-23 21:36
*/
@Data
@Configuration
@EqualsAndHashCode(callSuper = true)
@EnableAutoConfiguration
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfig extends AbstractRedisConfig {
// ---------- 连接配置 ----------
/** 地址 */
private String host;
/** 端口 */
private int port;
/** 密码 */
private String password;
/** 超时(毫秒) */
private int timeout;
/** 连接池 */
private Lettuce lettuce;
/** 数据库 */
private Database database;
/**
* 连接池
*
* @author 夜雨
* @since 2023-08-21 16:23
*/
@Data
public static class Lettuce {
/** 配置 */
private Pool pool;
/**
* 配置
*
* @author 夜雨
* @since 2023-08-21 16:23
*/
@Data
public static class Pool {
/** 最大活跃连接 */
private int maxActive;
/** 最小空闲连接 */
private int minIdle;
/** 最大空闲连接 */
private int maxIdle;
/** 最大等待时间(秒) */
private int maxWait;
}
}
/**
* 数据库
*
* @author 夜雨
* @since 2023-08-21 16:25
*/
@Data
public static class Database {
/** 分布式锁 */
private int locker;
/** 多语言环境 */
private int language;
/** 多语言键环境 */
private int languageMap;
/** 文章排位 */
private int articleRanking;
/** 文章阅读记录 */
private int articleRead;
/** 用户登录令牌 */
private int userToken;
/** 用户经验值标记 */
private int userExpFlag;
/** 用户邮箱验证 */
private int userEmailVerify;
/** 用户重置密码验证 */
private int userResetPWVerify;
/** 访问频率控制 */
private int rateLimit;
/** 系统配置 */
private int setting;
/** Minecraft 登录 */
private int fmcPlayerToken;
}
@Override
protected RedisConfigParams configParams() {
return new RedisConfigParams() {{
setHost(host);
setPort(port);
setPassword(password);
setTimeout(timeout);
setMaxActive(lettuce.pool.maxActive);
setMinIdle(lettuce.pool.minIdle);
setMaxIdle(lettuce.pool.maxIdle);
}};
}
/** @return 连接池配置 */
@Bean
@Override
public GenericObjectPoolConfig<?> getPoolConfig() {
GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(lettuce.pool.maxActive);
config.setMinIdle(lettuce.pool.minIdle);
config.setMaxIdle(lettuce.pool.maxIdle);
config.setMaxWait(Duration.ofMillis(lettuce.pool.maxWait));
return config;
}
/** @return key 生成策略 */
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
};
}
/** @return 分布式锁, ID: 尝试加锁次数 */
@Bean("redisLocker")
public Redis<String, Integer> getLockerRedisTemplate() {
return getRedis(database.locker, RedisSerializers.STRING, RedisSerializers.INTEGER);
}
/** @return 多语言环境ID: {@link Multilingual} */
@Bean("redisLanguage")
public Redis<Long, Multilingual> getLanguageRedisTemplate() {
return getRedis(database.language, RedisSerializers.LONG, new RedisSerializer<>() {
public Multilingual deserialize(@Nullable byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return null;
}
try {
return (Multilingual) new DeserializingConverter().convert(bytes);
} catch (Exception var3) {
throw new SerializationException("Cannot deserialize", var3);
}
}
public byte[] serialize(@Nullable Multilingual multilingual) {
if (multilingual == null) {
return new byte[0];
} else {
try {
return new SerializingConverter().convert(multilingual);
} catch (Exception var3) {
throw new SerializationException("Cannot serialize", var3);
}
}
}
});
}
/** @return 文章访问记录IP: [文章 ID] */
@Bean("redisLanguageMap")
public Redis<String, Long> getLanguageMapRedisTemplate() {
return getRedis(database.languageMap, RedisSerializers.STRING, RedisSerializers.LONG);
}
/** @return 文章访问统计,文章 ID: {@link ArticleRanking}(JSON) */
@Bean("redisArticleRanking")
public Redis<Long, ArticleRanking> getArticleRankingRedisTemplate() {
return getRedis(database.articleRanking, RedisSerializers.LONG, RedisSerializers.gsonSerializer(ArticleRanking.class));
}
/** @return 文章访问记录IP: [文章 ID] */
@Bean("redisArticleRead")
public Redis<String, Long> getArticleReadRedisTemplate() {
return getRedis(database.articleRead, RedisSerializers.STRING, RedisSerializers.LONG);
}
/** @return 用户登录经验标记UID: NULL暂时没有值数据死亡时间为次日零时 */
@Bean("redisUserExpFlag")
public Redis<Long, String> getUserExpFlagRedisTemplate() {
return getRedis(database.userExpFlag, RedisSerializers.LONG, RedisSerializers.STRING);
}
/** @return 用户邮箱验证密钥,密钥: UID */
@Bean("redisUserEmailVerify")
public Redis<String, Long> getUserEmailVerifyRedisTemplate() {
return getRedis(database.userEmailVerify, RedisSerializers.STRING, RedisSerializers.LONG);
}
/** @return 用户重置密码密钥,密钥: UID */
@Bean("redisUserResetPWVerify")
public Redis<String, Long> getUserResetPWVerifyRedisTemplate() {
return getRedis(database.userResetPWVerify, RedisSerializers.STRING, RedisSerializers.LONG);
}
/** @return 接口访问控制IP#方法: 生命周期内访问次数 */
@Bean("redisRateLimit")
public Redis<String, Integer> getRateLimitRedisTemplate() {
return getRedis(database.rateLimit, RedisSerializers.STRING, RedisSerializers.INTEGER);
}
/** @return 系统配置Key 枚举: String 配置值 */
@Bean("redisSetting")
public Redis<String, String> getSettingRedisTemplate() {
return getRedis(database.setting, RedisSerializers.STRING, RedisSerializers.STRING);
}
/** @return Minecraft 登录,令牌: 玩家 ID */
@Bean("redisMCPlayerToken")
public Redis<String, Long> getMCPlayerLoginRedisTemplate() {
return getRedis(database.fmcPlayerToken, RedisSerializers.STRING, RedisSerializers.LONG);
}
}

View File

@@ -0,0 +1,33 @@
package com.imyeyu.api.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
/**
*
*
* @author 夜雨
* @since 2024-12-19 23:04
*/
@Configuration
public class SchedulerConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(32);
scheduler.initialize();
return scheduler;
}
@Bean
public ScheduledTaskRegistrar scheduleCronTask(TaskScheduler taskScheduler) {
ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
registrar.setTaskScheduler(taskScheduler);
registrar.afterPropertiesSet();
return registrar;
}
}

View File

@@ -0,0 +1,57 @@
package com.imyeyu.api.config;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
*
* @author 夜雨
* @since 2023-08-21 16:31
*/
@Data
@Slf4j
@Configuration
@EnableAutoConfiguration
@ConfigurationProperties(prefix = "spring.async.thread-pool")
public class ThreadPoolConfig {
/** 核心数量 */
private int corePoolSize;
/** 最大数量 */
private int maxPoolSize;
/** 等待区容量 */
private int queueCapacity;
/** 最大保持活跃时间(秒) */
private int keepAliveSeconds;
/** 最大等待时间(秒) */
private int awaitTerminationSeconds;
/** 线程名称前缀 */
private String threadNamePrefix;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setAwaitTerminationSeconds(awaitTerminationSeconds);
executor.setThreadNamePrefix(threadNamePrefix);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}

View File

@@ -0,0 +1,94 @@
package com.imyeyu.api.config;
import com.google.gson.GsonBuilder;
import com.imyeyu.api.annotation.EnableSettingInterceptor;
import com.imyeyu.api.annotation.RequestRateLimitInterceptor;
import com.imyeyu.api.annotation.RequiredTokenInterceptor;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.vo.user.UserProfileView;
import com.imyeyu.api.modules.common.vo.user.UserView;
import com.imyeyu.api.modules.minecraft.annotation.RequiredFMCServerTokenInterceptor;
import com.imyeyu.api.modules.minecraft.entity.MinecraftPlayer;
import com.imyeyu.api.modules.mirror.vo.MirrorView;
import com.imyeyu.api.modules.system.util.SystemAPIInterceptor;
import com.imyeyu.api.util.GsonSerializerAdapter;
import com.imyeyu.spring.annotation.RequestSingleParamResolver;
import jakarta.validation.constraints.NotNull;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.List;
/**
* 系统配置
*
* @author 夜雨
* @since 2021-07-20 16:44
*/
@EnableWebMvc
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final SystemAPIInterceptor systemAPIInterceptor;
private final GsonSerializerAdapter gsonSerializerAdapter;
private final RequiredTokenInterceptor requiredTokenInterceptor;
private final EnableSettingInterceptor enableSettingInterceptor;
private final RequestSingleParamResolver requestSingleParamResolver;
private final RequestRateLimitInterceptor requestRateLimitInterceptor;
private final RequiredFMCServerTokenInterceptor requiredFMCServerTokenInterceptor;
/**
* 过滤器
*
* @param registry 注册表
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(systemAPIInterceptor).addPathPatterns(SystemAPIInterceptor.PATH);
registry.addInterceptor(requiredFMCServerTokenInterceptor).addPathPatterns("/fmc/server/**");
registry.addInterceptor(requiredTokenInterceptor).addPathPatterns("/**");
registry.addInterceptor(enableSettingInterceptor).addPathPatterns("/**");
registry.addInterceptor(requestRateLimitInterceptor).addPathPatterns("/**");
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(requestSingleParamResolver);
}
/**
* 通信消息转换
*
* @param converters 转换器
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
GsonHttpMessageConverter converter = new GsonHttpMessageConverter() {
@Override
protected void writeInternal(@NotNull Object object, Type type, @NonNull Writer writer) {
// 忽略参数类型,因为接口返回对象会被全局返回处理器包装为 TimiResponse否则会序列化转型错误
getGson().toJson(object, writer);
}
};
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Attachment.class, gsonSerializerAdapter);
builder.registerTypeAdapter(UserView.class, gsonSerializerAdapter);
builder.registerTypeAdapter(MirrorView.class, gsonSerializerAdapter);
builder.registerTypeAdapter(UserProfileView.class, gsonSerializerAdapter);
builder.registerTypeAdapter(MinecraftPlayer.class, gsonSerializerAdapter);
converter.setGson(builder.create());
converters.add(converter);
}
}

View File

@@ -0,0 +1,76 @@
package com.imyeyu.api.config.dbsource;
import com.zaxxer.hikari.HikariDataSource;
import com.imyeyu.utils.Time;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* ForeverMC 登录校验数据源
*
* @author 夜雨
* @since 2022-11-29 22:39
*/
@Configuration
@MapperScan(basePackages = "com.imyeyu.api.modules.forevermc.mapper", sqlSessionFactoryRef = "foreverMCSqlSessionFactory")
public class ForeverMCDBConfig {
public static final String ROLLBACKER = "foreverMCTransactionManager";
@Bean(name = "foreverMCDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.forevermc")
public DataSource getPrimaryDateSource() throws SQLException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setAutoCommit(true);
dataSource.setMinimumIdle(10);
dataSource.setMaximumPoolSize(100);
dataSource.setConnectionTestQuery("SELECT 1");
dataSource.setMaxLifetime(Time.S * 180);
dataSource.setIdleTimeout(Time.S * 120);
dataSource.setLoginTimeout(5);
dataSource.setValidationTimeout(Time.S * 3);
dataSource.setConnectionTimeout(Time.S * 8);
dataSource.setLeakDetectionThreshold(Time.S * 180);
return dataSource;
}
@Bean(name = "foreverMCSqlSessionFactory")
@Primary
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("foreverMCDataSource") DataSource datasource) throws Exception {
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
config.setUseGeneratedKeys(true);
config.setMapUnderscoreToCamelCase(true);
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setTypeAliasesPackage("com.imyeyu.api.modules.forevermc.entity");
bean.setConfiguration(config);
return bean.getObject();
}
@Bean("foreverMCSqlSessionTemplate")
@Primary
public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("foreverMCSqlSessionFactory") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
@Bean(name = "foreverMCTransactionManager")
public PlatformTransactionManager txManager(@Qualifier("foreverMCDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

View File

@@ -0,0 +1,104 @@
package com.imyeyu.api.config.dbsource;
import com.imyeyu.utils.Time;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.EnumTypeHandler;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Gitea 数据源
*
* @author 夜雨
* @since 2022-11-29 22:40
*/
@Configuration
@MapperScan(basePackages = {
"com.imyeyu.api.modules.gitea.mapper",
}, sqlSessionFactoryRef = "giteaSqlSessionFactory")
public class GiteaDBConfig {
public static final String ROLLBACKER = "giteaTransactionManager";
@Bean(name = "giteaDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.gitea")
public DataSource dateSource() throws SQLException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setAutoCommit(true);
dataSource.setMinimumIdle(10);
dataSource.setMaximumPoolSize(100);
dataSource.setConnectionTestQuery("SELECT 1");
dataSource.setMaxLifetime(Time.S * 180);
dataSource.setIdleTimeout(Time.S * 120);
dataSource.setLoginTimeout(5);
dataSource.setValidationTimeout(Time.S * 3);
dataSource.setConnectionTimeout(Time.S * 8);
dataSource.setLeakDetectionThreshold(Time.S * 180);
return dataSource;
}
@Bean(name = "giteaSqlSessionFactory")
@Primary
public SqlSessionFactory sessionFactory(@Qualifier("giteaDataSource") DataSource datasource) throws Exception {
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
config.setUseGeneratedKeys(true);
config.setMapUnderscoreToCamelCase(true);
config.setDefaultEnumTypeHandler(EnumTypeHandler.class);
List<Resource> resources = new ArrayList<>();
{
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<String> mapperLocations = new ArrayList<>();
mapperLocations.add("classpath:mapper/gitea/**/*.xml");
for (int i = 0; i < mapperLocations.size(); i++) {
resources.addAll(List.of(resourceResolver.getResources(mapperLocations.get(i))));
}
}
String[] typeAliases = {
"com.imyeyu.api.modules.gitea.entity",
};
String[] typeHandlers = {
"com.imyeyu.api.handler"
};
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setConfiguration(config);
bean.setMapperLocations(resources.toArray(new Resource[0]));
bean.setTypeAliasesPackage(String.join(",", typeAliases));
bean.setTypeHandlersPackage(String.join(",", typeHandlers));
return bean.getObject();
}
@Bean("giteaSqlSessionTemplate")
@Primary
public SqlSessionTemplate sessionTemplate(@Qualifier("giteaSqlSessionFactory") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
@Bean(name = "giteaTransactionManager")
public PlatformTransactionManager txManager(@Qualifier("giteaDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

View File

@@ -0,0 +1,122 @@
package com.imyeyu.api.config.dbsource;
import com.zaxxer.hikari.HikariDataSource;
import com.imyeyu.utils.Time;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.EnumTypeHandler;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* TimiServer 数据源
*
* @author 夜雨
* @since 2022-11-29 22:40
*/
@Configuration
@MapperScan(basePackages = {
"com.imyeyu.api.modules.git.mapper",
"com.imyeyu.api.modules.bill.mapper",
"com.imyeyu.api.modules.blog.mapper",
"com.imyeyu.api.modules.lyric.mapper",
"com.imyeyu.api.modules.mirror.mapper",
"com.imyeyu.api.modules.system.mapper",
"com.imyeyu.api.modules.common.mapper",
"com.imyeyu.api.modules.minecraft.mapper"
}, sqlSessionFactoryRef = "timiServerSqlSessionFactory")
public class TimiServerDBConfig {
public static final String ROLLBACKER = "timiServerTransactionManager";
@Bean(name = "timiServerDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.timiserver")
public DataSource getPrimaryDateSource() throws SQLException {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setAutoCommit(true);
dataSource.setMinimumIdle(10);
dataSource.setMaximumPoolSize(100);
dataSource.setConnectionTestQuery("SELECT 1");
dataSource.setMaxLifetime(Time.S * 180);
dataSource.setIdleTimeout(Time.S * 120);
dataSource.setLoginTimeout(5);
dataSource.setValidationTimeout(Time.S * 3);
dataSource.setConnectionTimeout(Time.S * 8);
dataSource.setLeakDetectionThreshold(Time.S * 180);
return dataSource;
}
@Bean(name = "timiServerSqlSessionFactory")
@Primary
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("timiServerDataSource") DataSource datasource) throws Exception {
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
config.setUseGeneratedKeys(true);
config.setMapUnderscoreToCamelCase(true);
config.setDefaultEnumTypeHandler(EnumTypeHandler.class);
List<Resource> resources = new ArrayList<>();
{
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<String> mapperLocations = new ArrayList<>();
mapperLocations.add("classpath:mapper/git/**/*.xml");
mapperLocations.add("classpath:mapper/blog/**/*.xml");
mapperLocations.add("classpath:mapper/common/**/*.xml");
mapperLocations.add("classpath:mapper/system/**/*.xml");
mapperLocations.add("classpath:mapper/minecraft/**/*.xml");
for (int i = 0; i < mapperLocations.size(); i++) {
resources.addAll(List.of(resourceResolver.getResources(mapperLocations.get(i))));
}
}
String[] typeAliases = {
"com.imyeyu.api.modules.git.entity",
"com.imyeyu.api.modules.bill.entity",
"com.imyeyu.api.modules.blog.entity",
"com.imyeyu.api.modules.lyric.entity",
"com.imyeyu.api.modules.mirror.entity",
"com.imyeyu.api.modules.system.entity",
"com.imyeyu.api.modules.common.entity",
"com.imyeyu.api.modules.minecraft.entity"
};
String[] typeHandlers = {
"com.imyeyu.api.handler"
};
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setConfiguration(config);
bean.setMapperLocations(resources.toArray(new Resource[0]));
bean.setTypeAliasesPackage(String.join(",", typeAliases));
bean.setTypeHandlersPackage(String.join(",", typeHandlers));
return bean.getObject();
}
@Bean("timiServerSqlSessionTemplate")
@Primary
public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("timiServerSqlSessionFactory") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
@Bean(name = "timiServerTransactionManager")
public PlatformTransactionManager txManager(@Qualifier("timiServerDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}