|
@@ -7,11 +7,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
|
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
+import org.springframework.context.annotation.Import;
|
|
|
import org.springframework.context.annotation.Lazy;
|
|
|
import org.springframework.core.Ordered;
|
|
|
import org.springframework.core.env.Environment;
|
|
@@ -32,7 +34,7 @@ import org.ssssssss.magicapi.cache.DefaultSqlCache;
|
|
|
import org.ssssssss.magicapi.cache.SqlCache;
|
|
|
import org.ssssssss.magicapi.config.*;
|
|
|
import org.ssssssss.magicapi.controller.*;
|
|
|
-import org.ssssssss.magicapi.dialect.*;
|
|
|
+import org.ssssssss.magicapi.dialect.Dialect;
|
|
|
import org.ssssssss.magicapi.interceptor.RequestInterceptor;
|
|
|
import org.ssssssss.magicapi.interceptor.SQLInterceptor;
|
|
|
import org.ssssssss.magicapi.logging.LoggerManager;
|
|
@@ -40,6 +42,7 @@ import org.ssssssss.magicapi.modules.*;
|
|
|
import org.ssssssss.magicapi.provider.*;
|
|
|
import org.ssssssss.magicapi.provider.impl.*;
|
|
|
import org.ssssssss.magicapi.utils.ClassScanner;
|
|
|
+import org.ssssssss.magicapi.utils.PathUtils;
|
|
|
import org.ssssssss.script.MagicResourceLoader;
|
|
|
import org.ssssssss.script.MagicScript;
|
|
|
import org.ssssssss.script.MagicScriptEngine;
|
|
@@ -58,6 +61,7 @@ import java.util.*;
|
|
|
@Configuration
|
|
|
@ConditionalOnClass({RequestMappingHandlerMapping.class})
|
|
|
@EnableConfigurationProperties(MagicAPIProperties.class)
|
|
|
+@Import({MagicRedisAutoConfiguration.class, MagicMongoAutoConfiguration.class, MagicSwaggerConfiguration.class})
|
|
|
public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(MagicAPIAutoConfiguration.class);
|
|
@@ -66,10 +70,10 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
private MagicAPIProperties properties;
|
|
|
|
|
|
@Autowired(required = false)
|
|
|
- private List<RequestInterceptor> requestInterceptors = Collections.emptyList();
|
|
|
+ private final List<RequestInterceptor> requestInterceptors = Collections.emptyList();
|
|
|
|
|
|
@Autowired(required = false)
|
|
|
- private List<SQLInterceptor> sqlInterceptors = Collections.emptyList();
|
|
|
+ private final List<SQLInterceptor> sqlInterceptors = Collections.emptyList();
|
|
|
|
|
|
@Autowired
|
|
|
@Lazy
|
|
@@ -82,19 +86,19 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
* 自定义的类型扩展
|
|
|
*/
|
|
|
@Autowired(required = false)
|
|
|
- private List<ExtensionMethod> extensionMethods = Collections.emptyList();
|
|
|
+ private final List<ExtensionMethod> extensionMethods = Collections.emptyList();
|
|
|
|
|
|
/**
|
|
|
* 内置的消息转换
|
|
|
*/
|
|
|
@Autowired(required = false)
|
|
|
- private List<HttpMessageConverter<?>> httpMessageConverters = Collections.emptyList();
|
|
|
+ private final List<HttpMessageConverter<?>> httpMessageConverters = Collections.emptyList();
|
|
|
|
|
|
/**
|
|
|
* 自定义的方言
|
|
|
*/
|
|
|
@Autowired(required = false)
|
|
|
- private List<Dialect> dialects = Collections.emptyList();
|
|
|
+ private final List<Dialect> dialects = Collections.emptyList();
|
|
|
|
|
|
/**
|
|
|
* 自定义的列名转换
|
|
@@ -120,9 +124,6 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
@Autowired
|
|
|
FunctionServiceProvider functionServiceProvider;
|
|
|
|
|
|
- @Autowired(required = false)
|
|
|
- MagicDynamicDataSource magicDynamicDataSource;
|
|
|
-
|
|
|
@Autowired
|
|
|
MappingHandlerMapping mappingHandlerMapping;
|
|
|
|
|
@@ -162,10 +163,36 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
return ALL_CLASS_TXT;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 注入动态数据源
|
|
|
+ */
|
|
|
+ @Bean
|
|
|
+ @ConditionalOnMissingBean(MagicDynamicDataSource.class)
|
|
|
+ @ConditionalOnBean({DataSource.class})
|
|
|
+ public MagicDynamicDataSource magicDynamicDataSource(DataSource dataSource) {
|
|
|
+ MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource();
|
|
|
+ dynamicDataSource.put(dataSource);
|
|
|
+ return dynamicDataSource;
|
|
|
+ }
|
|
|
+
|
|
|
@Bean
|
|
|
@ConditionalOnMissingBean(Resource.class)
|
|
|
- public Resource magicWorkspaceResource() throws IOException {
|
|
|
- return ResourceAdapter.getResource(properties.getWorkspace());
|
|
|
+ @ConditionalOnProperty(prefix = "magic-api", name = "resource.type", havingValue = "database")
|
|
|
+ public Resource magicDatabaseResource(MagicDynamicDataSource magicDynamicDataSource) throws IOException {
|
|
|
+ ResourceConfig resourceConfig = properties.getResource();
|
|
|
+ MagicDynamicDataSource.DataSourceNode dataSourceNode = magicDynamicDataSource.getDataSource(resourceConfig.getDatasource());
|
|
|
+ if (dataSourceNode == null) {
|
|
|
+ throw new IllegalArgumentException(String.format("找不到数据源:%s", resourceConfig.getDatasource()));
|
|
|
+ }
|
|
|
+ return ResourceAdapter.getResource(properties.getWorkspace(), resourceConfig.isReadonly());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ @ConditionalOnMissingBean(Resource.class)
|
|
|
+ @ConditionalOnProperty(prefix = "magic-api", name = "resource.type", havingValue = "file", matchIfMissing = true)
|
|
|
+ public Resource magicResource() throws IOException {
|
|
|
+ ResourceConfig resourceConfig = properties.getResource();
|
|
|
+ return ResourceAdapter.getResource(properties.getWorkspace(), resourceConfig.isReadonly());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -190,8 +217,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
|
|
|
@Override
|
|
|
public void addInterceptors(InterceptorRegistry registry) {
|
|
|
- String web = properties.getWeb();
|
|
|
- if (web != null) {
|
|
|
+ if (properties.isSupportCrossDomain()) {
|
|
|
registry.addInterceptor(new HandlerInterceptor() {
|
|
|
@Override
|
|
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
|
@@ -208,7 +234,14 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
- public FilterRegistrationBean magicCorsFilterRegistrationBean() {
|
|
|
+ public MagicCorsFilter magicCorsFilter() {
|
|
|
+ return new MagicCorsFilter();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ @ConditionalOnProperty(prefix = "magic-api", value = "cors", havingValue = "true", matchIfMissing = true)
|
|
|
+ public FilterRegistrationBean<MagicCorsFilter> magicCorsFilterRegistrationBean() {
|
|
|
FilterRegistrationBean<MagicCorsFilter> registration = new FilterRegistrationBean<>(magicCorsFilter);
|
|
|
registration.addUrlPatterns("/*");
|
|
|
registration.setName("Magic Cors Filter");
|
|
@@ -217,12 +250,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
- public MagicCorsFilter magicCorsFilter() {
|
|
|
- return new MagicCorsFilter();
|
|
|
- }
|
|
|
-
|
|
|
@ConditionalOnMissingBean(PageProvider.class)
|
|
|
- @Bean
|
|
|
public PageProvider pageProvider() {
|
|
|
PageConfig pageConfig = properties.getPageConfig();
|
|
|
logger.info("未找到分页实现,采用默认分页实现,分页配置:(页码={},页大小={},默认首页={},默认页大小={})", pageConfig.getPage(), pageConfig.getSize(), pageConfig.getDefaultPage(), pageConfig.getDefaultSize());
|
|
@@ -232,8 +260,8 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
/**
|
|
|
* 注入结果构建方法
|
|
|
*/
|
|
|
- @ConditionalOnMissingBean(ResultProvider.class)
|
|
|
@Bean
|
|
|
+ @ConditionalOnMissingBean(ResultProvider.class)
|
|
|
public ResultProvider resultProvider() {
|
|
|
return new DefaultResultProvider();
|
|
|
}
|
|
@@ -241,8 +269,8 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
/**
|
|
|
* 注入SQL缓存实现
|
|
|
*/
|
|
|
- @ConditionalOnMissingBean(SqlCache.class)
|
|
|
@Bean
|
|
|
+ @ConditionalOnMissingBean(SqlCache.class)
|
|
|
public SqlCache sqlCache() {
|
|
|
CacheConfig cacheConfig = properties.getCacheConfig();
|
|
|
logger.info("未找到SQL缓存实现,采用默认缓存实现(LRU+TTL),缓存配置:(容量={},TTL={})", cacheConfig.getCapacity(), cacheConfig.getTtl());
|
|
@@ -254,26 +282,15 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
*/
|
|
|
@Bean
|
|
|
public MappingHandlerMapping mappingHandlerMapping() throws NoSuchMethodException {
|
|
|
- MappingHandlerMapping handlerMapping = new MappingHandlerMapping();
|
|
|
- if (StringUtils.isNotBlank(properties.getPrefix())) {
|
|
|
- String prefix = properties.getPrefix().trim();
|
|
|
- if (!prefix.startsWith("/")) {
|
|
|
- prefix = "/" + prefix;
|
|
|
- }
|
|
|
- if (!prefix.endsWith("/")) {
|
|
|
- prefix = prefix + "/";
|
|
|
- }
|
|
|
- handlerMapping.setPrefix(prefix);
|
|
|
- }
|
|
|
- handlerMapping.setAllowOverride(properties.isAllowOverride());
|
|
|
- return handlerMapping;
|
|
|
+ String prefix = StringUtils.isNotBlank(properties.getPrefix()) ? PathUtils.replaceSlash("/" + properties.getPrefix() + "/") : null;
|
|
|
+ return new MappingHandlerMapping(prefix, properties.isAllowOverride());
|
|
|
}
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
@ConditionalOnMissingBean(FunctionServiceProvider.class)
|
|
|
- public FunctionServiceProvider functionServiceProvider(GroupServiceProvider groupServiceProvider,Resource magicWorkspaceResource) {
|
|
|
- return new DefaultFunctionServiceProvider(groupServiceProvider, magicWorkspaceResource);
|
|
|
+ public FunctionServiceProvider functionServiceProvider(GroupServiceProvider groupServiceProvider, Resource magicResource) {
|
|
|
+ return new DefaultFunctionServiceProvider(groupServiceProvider, magicResource);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -281,17 +298,17 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
*/
|
|
|
@Bean
|
|
|
@ConditionalOnMissingBean(GroupServiceProvider.class)
|
|
|
- public GroupServiceProvider groupServiceProvider(Resource magicWorkspaceResource) {
|
|
|
- return new DefaultGroupServiceProvider(magicWorkspaceResource);
|
|
|
+ public GroupServiceProvider groupServiceProvider(Resource magicResource) {
|
|
|
+ return new DefaultGroupServiceProvider(magicResource);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 注入接口存储service
|
|
|
*/
|
|
|
- @ConditionalOnMissingBean(ApiServiceProvider.class)
|
|
|
@Bean
|
|
|
- public ApiServiceProvider apiServiceProvider(GroupServiceProvider groupServiceProvider,Resource magicWorkspaceResource) {
|
|
|
- return new DefaultApiServiceProvider(groupServiceProvider, magicWorkspaceResource);
|
|
|
+ @ConditionalOnMissingBean(ApiServiceProvider.class)
|
|
|
+ public ApiServiceProvider apiServiceProvider(GroupServiceProvider groupServiceProvider, Resource magicResource) {
|
|
|
+ return new DefaultApiServiceProvider(groupServiceProvider, magicResource);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -308,7 +325,6 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
try {
|
|
|
clazz = Class.forName("org.springframework.security.core.context.SecurityContextHolder");
|
|
|
} catch (ClassNotFoundException ignored) {
|
|
|
-
|
|
|
}
|
|
|
if (clazz != null) {
|
|
|
try {
|
|
@@ -333,30 +349,13 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
sqlModule.setPageProvider(pageProvider);
|
|
|
sqlModule.setSqlInterceptors(sqlInterceptors);
|
|
|
ColumnMapperAdapter columnMapperAdapter = new ColumnMapperAdapter();
|
|
|
- columnMapperAdapter.setDefault(new DefaultColumnMapperProvider());
|
|
|
- columnMapperAdapter.add(new CamelColumnMapperProvider());
|
|
|
- columnMapperAdapter.add(new PascalColumnMapperProvider());
|
|
|
- columnMapperAdapter.add(new LowerColumnMapperProvider());
|
|
|
- columnMapperAdapter.add(new UpperColumnMapperProvider());
|
|
|
- for (ColumnMapperProvider mapperProvider : this.columnMapperProviders) {
|
|
|
- if (!"default".equals(mapperProvider.name())) {
|
|
|
- columnMapperAdapter.add(mapperProvider);
|
|
|
- }
|
|
|
- }
|
|
|
+ this.columnMapperProviders.stream().filter(mapperProvider -> !"default".equals(mapperProvider.name())).forEach(columnMapperAdapter::add);
|
|
|
columnMapperAdapter.setDefault(properties.getSqlColumnCase());
|
|
|
sqlModule.setColumnMapperProvider(columnMapperAdapter);
|
|
|
sqlModule.setColumnMapRowMapper(columnMapperAdapter.getDefaultColumnMapRowMapper());
|
|
|
sqlModule.setRowMapColumnMapper(columnMapperAdapter.getDefaultRowMapColumnMapper());
|
|
|
sqlModule.setSqlCache(sqlCache);
|
|
|
DialectAdapter dialectAdapter = new DialectAdapter();
|
|
|
- dialectAdapter.add(new MySQLDialect());
|
|
|
- dialectAdapter.add(new OracleDialect());
|
|
|
- dialectAdapter.add(new PostgreSQLDialect());
|
|
|
- dialectAdapter.add(new ClickhouseDialect());
|
|
|
- dialectAdapter.add(new DB2Dialect());
|
|
|
- dialectAdapter.add(new SQLServerDialect());
|
|
|
- dialectAdapter.add(new SQLServer2005Dialect());
|
|
|
- dialectAdapter.add(new DmDialect());
|
|
|
dialects.forEach(dialectAdapter::add);
|
|
|
sqlModule.setDialectAdapter(dialectAdapter);
|
|
|
return sqlModule;
|
|
@@ -391,47 +390,27 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
MagicResourceLoader.addModule("response", new ResponseModule(resultProvider));
|
|
|
logger.info("注册模块:{} -> {}", "assert", AssertModule.class);
|
|
|
MagicResourceLoader.addModule("assert", AssertModule.class);
|
|
|
- for (MagicModule module : magicModules) {
|
|
|
+ magicModules.forEach(module -> {
|
|
|
logger.info("注册模块:{} -> {}", module.getModuleName(), module.getClass());
|
|
|
MagicResourceLoader.addModule(module.getModuleName(), module);
|
|
|
- }
|
|
|
- Set<String> moduleNames = MagicResourceLoader.getModuleNames();
|
|
|
- for (String moduleName : moduleNames) {
|
|
|
- if (importModules.contains(moduleName)) {
|
|
|
- logger.info("自动导入模块:{}", moduleName);
|
|
|
- MagicScriptEngine.addDefaultImport(moduleName, MagicResourceLoader.loadModule(moduleName));
|
|
|
- }
|
|
|
- }
|
|
|
- List<String> importPackages = properties.getAutoImportPackageList();
|
|
|
- for (String importPackage : importPackages) {
|
|
|
+ });
|
|
|
+ MagicResourceLoader.getModuleNames().stream().filter(importModules::contains).forEach(moduleName -> {
|
|
|
+ logger.info("自动导入模块:{}", moduleName);
|
|
|
+ MagicScriptEngine.addDefaultImport(moduleName, MagicResourceLoader.loadModule(moduleName));
|
|
|
+ });
|
|
|
+ properties.getAutoImportPackageList().forEach(importPackage -> {
|
|
|
logger.info("自动导包:{}", importPackage);
|
|
|
MagicResourceLoader.addPackage(importPackage);
|
|
|
- }
|
|
|
- for (ExtensionMethod extension : extensionMethods) {
|
|
|
- List<Class<?>> supports = extension.supports();
|
|
|
- for (Class<?> support : supports) {
|
|
|
- logger.info("注册扩展:{} -> {}", support, extension.getClass());
|
|
|
- AbstractReflection.getInstance().registerMethodExtension(support, extension);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 注入动态数据源
|
|
|
- */
|
|
|
- @Bean
|
|
|
- @ConditionalOnMissingBean(MagicDynamicDataSource.class)
|
|
|
- @ConditionalOnBean({DataSource.class})
|
|
|
- public MagicDynamicDataSource magicDynamicDataSource(DataSource dataSource) {
|
|
|
- MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource();
|
|
|
- dynamicDataSource.put(dataSource);
|
|
|
- return dynamicDataSource;
|
|
|
+ });
|
|
|
+ extensionMethods.forEach(extension -> extension.supports().forEach(support -> {
|
|
|
+ logger.info("注册扩展:{} -> {}", support, extension.getClass());
|
|
|
+ AbstractReflection.getInstance().registerMethodExtension(support, extension);
|
|
|
+ }));
|
|
|
}
|
|
|
|
|
|
@Bean
|
|
|
- public MagicConfiguration magicConfiguration(@Autowired List<MagicModule> magicModules,@Autowired Resource magicWorkspaceResource) {
|
|
|
- logger.info("magic-api工作目录:{}",magicWorkspaceResource);
|
|
|
+ public MagicConfiguration magicConfiguration(List<MagicModule> magicModules, @Autowired(required = false) MagicDynamicDataSource magicDynamicDataSource, Resource magicResource) {
|
|
|
+ logger.info("magic-api工作目录:{}", magicResource);
|
|
|
setupSpringSecurity();
|
|
|
AsyncCall.setThreadPoolExecutorSize(properties.getThreadPoolExecutorSize());
|
|
|
// 设置模块和扩展方法
|
|
@@ -450,7 +429,7 @@ public class MagicAPIAutoConfiguration implements WebMvcConfigurer {
|
|
|
configuration.setThrowException(properties.isThrowException());
|
|
|
configuration.setMagicDynamicDataSource(magicDynamicDataSource);
|
|
|
configuration.setEditorConfig(properties.getEditorConfig());
|
|
|
- configuration.setWorkspace(magicWorkspaceResource);
|
|
|
+ configuration.setWorkspace(magicResource);
|
|
|
// 注册函数
|
|
|
this.magicFunctions.forEach(JavaReflection::registerFunction);
|
|
|
// 向页面传递配置信息时不传递用户名密码,增强安全性
|