mirror of
https://github.com/vran-dev/databasir.git
synced 2025-08-08 18:10:26 +08:00
feat: support custom database types
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package com.databasir.core.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
|
||||
RestTemplate restTemplate = new RestTemplate(factory);
|
||||
// 支持中文编码
|
||||
restTemplate.getMessageConverters().set(1,
|
||||
new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
return restTemplate;
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setReadTimeout(1000 * 30);//单位为ms
|
||||
factory.setConnectTimeout(1000 * 5);//单位为ms
|
||||
return factory;
|
||||
}
|
||||
}
|
@@ -27,7 +27,11 @@ public enum DomainErrors implements DatabasirErrors {
|
||||
INVALID_CRON_EXPRESSION("A_10012", "不合法的 cron 表达式"),
|
||||
REGISTRATION_ID_DUPLICATE("A_10013", "应用注册 ID 不能重复"),
|
||||
REGISTRATION_ID_NOT_FOUND("A_10014", "应用 ID 不存在"),
|
||||
MISS_REQUIRED_PARAMETERS("A_10015", "缺少必填参数");
|
||||
MISS_REQUIRED_PARAMETERS("A_10015", "缺少必填参数"),
|
||||
DATABASE_TYPE_NAME_DUPLICATE("A_10016", "数据库类型名已存在"),
|
||||
MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE("A_10017", "禁止修改系统默认数据库类型"),
|
||||
DOWNLOAD_DRIVER_ERROR("A_10018", "驱动下载失败"),
|
||||
;
|
||||
|
||||
private final String errCode;
|
||||
|
||||
@@ -46,6 +50,6 @@ public enum DomainErrors implements DatabasirErrors {
|
||||
}
|
||||
|
||||
public DatabasirException exception(String s) {
|
||||
return exception(s, (Throwable) null);
|
||||
return exception(s, null);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
package com.databasir.core.domain.database.converter;
|
||||
|
||||
import com.databasir.core.domain.database.data.DatabaseTypeCreateRequest;
|
||||
import com.databasir.core.domain.database.data.DatabaseTypeDetailResponse;
|
||||
import com.databasir.core.domain.database.data.DatabaseTypePageResponse;
|
||||
import com.databasir.core.domain.database.data.DatabaseTypeUpdateRequest;
|
||||
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DatabaseTypePojoConverter {
|
||||
|
||||
DatabaseTypePojo of(DatabaseTypeCreateRequest request);
|
||||
|
||||
DatabaseTypePojo of(DatabaseTypeUpdateRequest request);
|
||||
|
||||
DatabaseTypeDetailResponse toDetailResponse(DatabaseTypePojo data);
|
||||
|
||||
DatabaseTypePageResponse toPageResponse(DatabaseTypePojo pojo, Integer projectCount);
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.databasir.core.domain.database.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
public class DatabaseTypeCreateRequest {
|
||||
|
||||
@NotBlank
|
||||
private String databaseType;
|
||||
|
||||
private String icon;
|
||||
|
||||
@NotBlank
|
||||
private String description;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcDriverFileUrl;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcDriverClassName;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcProtocol;
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package com.databasir.core.domain.database.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class DatabaseTypeDetailResponse {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String databaseType;
|
||||
|
||||
private String icon;
|
||||
|
||||
private String description;
|
||||
|
||||
private String jdbcDriverFileUrl;
|
||||
|
||||
private String jdbcDriverClassName;
|
||||
|
||||
private String jdbcProtocol;
|
||||
|
||||
private Boolean deleted;
|
||||
|
||||
private Integer deletedToken;
|
||||
|
||||
private LocalDateTime updateAt;
|
||||
|
||||
private LocalDateTime createAt;
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.databasir.core.domain.database.data;
|
||||
|
||||
import com.databasir.dao.Tables;
|
||||
import lombok.Data;
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DatabaseTypePageCondition {
|
||||
|
||||
private String databaseTypeContains;
|
||||
|
||||
public Condition toCondition() {
|
||||
List<Condition> conditions = new ArrayList<>();
|
||||
conditions.add(Tables.DATABASE_TYPE.DELETED.eq(false));
|
||||
if (databaseTypeContains != null && !databaseTypeContains.trim().equals("")) {
|
||||
conditions.add(Tables.DATABASE_TYPE.DATABASE_TYPE_.containsIgnoreCase(databaseTypeContains));
|
||||
}
|
||||
return conditions.stream()
|
||||
.reduce(Condition::and)
|
||||
.orElse(DSL.trueCondition());
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package com.databasir.core.domain.database.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class DatabaseTypePageResponse {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String databaseType;
|
||||
|
||||
private String icon;
|
||||
|
||||
private String description;
|
||||
|
||||
private String jdbcDriverFileUrl;
|
||||
|
||||
private String jdbcDriverClassName;
|
||||
|
||||
private String jdbcProtocol;
|
||||
|
||||
private Boolean deleted;
|
||||
|
||||
private Integer deletedToken;
|
||||
|
||||
private Integer projectCount;
|
||||
|
||||
private LocalDateTime updateAt;
|
||||
|
||||
private LocalDateTime createAt;
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.databasir.core.domain.database.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class DatabaseTypeUpdateRequest {
|
||||
|
||||
@NotNull
|
||||
private Integer id;
|
||||
|
||||
@NotBlank
|
||||
private String databaseType;
|
||||
|
||||
private String icon;
|
||||
|
||||
@NotBlank
|
||||
private String description;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcDriverFileUrl;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcDriverClassName;
|
||||
|
||||
@NotBlank
|
||||
private String jdbcProtocol;
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
package com.databasir.core.domain.database.service;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.core.domain.database.converter.DatabaseTypePojoConverter;
|
||||
import com.databasir.core.domain.database.data.*;
|
||||
import com.databasir.core.infrastructure.connection.DatabaseTypes;
|
||||
import com.databasir.core.infrastructure.driver.DriverResources;
|
||||
import com.databasir.dao.impl.DatabaseTypeDao;
|
||||
import com.databasir.dao.impl.ProjectDao;
|
||||
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class DatabaseTypeService {
|
||||
|
||||
private final DriverResources driverResources;
|
||||
|
||||
private final DatabaseTypeDao databaseTypeDao;
|
||||
|
||||
private final ProjectDao projectDao;
|
||||
|
||||
private final DatabaseTypePojoConverter databaseTypePojoConverter;
|
||||
|
||||
public Integer create(DatabaseTypeCreateRequest request) {
|
||||
DatabaseTypePojo pojo = databaseTypePojoConverter.of(request);
|
||||
try {
|
||||
return databaseTypeDao.insertAndReturnId(pojo);
|
||||
} catch (DuplicateKeyException e) {
|
||||
throw DomainErrors.DATABASE_TYPE_NAME_DUPLICATE.exception();
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(DatabaseTypeUpdateRequest request) {
|
||||
databaseTypeDao.selectOptionalById(request.getId()).ifPresent(data -> {
|
||||
if (DatabaseTypes.has(data.getDatabaseType())) {
|
||||
throw DomainErrors.MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE.exception();
|
||||
}
|
||||
|
||||
DatabaseTypePojo pojo = databaseTypePojoConverter.of(request);
|
||||
try {
|
||||
databaseTypeDao.updateById(pojo);
|
||||
} catch (DuplicateKeyException e) {
|
||||
throw DomainErrors.DATABASE_TYPE_NAME_DUPLICATE.exception();
|
||||
}
|
||||
|
||||
// 名称修改,下载地址修改需要删除原有的 driver
|
||||
if (!Objects.equals(request.getDatabaseType(), data.getDatabaseType())
|
||||
|| !Objects.equals(request.getJdbcDriverFileUrl(), data.getJdbcDriverFileUrl())) {
|
||||
driverResources.delete(data.getDatabaseType());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void deleteById(Integer id) {
|
||||
databaseTypeDao.selectOptionalById(id).ifPresent(data -> {
|
||||
if (DatabaseTypes.has(data.getDatabaseType())) {
|
||||
throw DomainErrors.MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE.exception();
|
||||
}
|
||||
databaseTypeDao.deleteById(id);
|
||||
driverResources.delete(data.getDatabaseType());
|
||||
});
|
||||
}
|
||||
|
||||
public Page<DatabaseTypePageResponse> findByPage(Pageable page,
|
||||
DatabaseTypePageCondition condition) {
|
||||
Page<DatabaseTypePojo> pageData = databaseTypeDao.selectByPage(page, condition.toCondition());
|
||||
List<String> databaseTypes = pageData.map(DatabaseTypePojo::getDatabaseType).toList();
|
||||
Map<String, Integer> projectCountMapByDatabaseType = projectDao.countByDatabaseTypes(databaseTypes);
|
||||
return pageData
|
||||
.map(data -> {
|
||||
Integer count = projectCountMapByDatabaseType.getOrDefault(data.getDatabaseType(), 0);
|
||||
return databaseTypePojoConverter.toPageResponse(data, count);
|
||||
});
|
||||
}
|
||||
|
||||
public List<String> listSimpleDatabaseTypes() {
|
||||
return databaseTypeDao.selectAll()
|
||||
.stream()
|
||||
.map(DatabaseTypePojo::getDatabaseType)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Optional<DatabaseTypeDetailResponse> selectOne(Integer id) {
|
||||
return databaseTypeDao.selectOptionalById(id)
|
||||
.map(databaseTypePojoConverter::toDetailResponse);
|
||||
}
|
||||
}
|
@@ -35,6 +35,7 @@ public @interface Operation {
|
||||
String GROUP = "group";
|
||||
String LOGIN_APP = "login_app";
|
||||
String SETTING = "setting";
|
||||
String DATABASE_TYPE = "database_type";
|
||||
}
|
||||
|
||||
interface Types {
|
||||
|
@@ -0,0 +1,80 @@
|
||||
package com.databasir.core.infrastructure.connection;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.core.infrastructure.driver.DriverResources;
|
||||
import com.databasir.dao.impl.DatabaseTypeDao;
|
||||
import com.databasir.dao.tables.pojos.DatabaseTypePojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CustomDatabaseConnectionFactory implements DatabaseConnectionFactory {
|
||||
|
||||
private final DatabaseTypeDao databaseTypeDao;
|
||||
|
||||
private final DriverResources driverResources;
|
||||
|
||||
@Override
|
||||
public boolean support(String databaseType) {
|
||||
return databaseTypeDao.existsByDatabaseType(databaseType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(Context context) throws SQLException {
|
||||
DatabaseTypePojo type = databaseTypeDao.selectByDatabaseType(context.getDatabaseType());
|
||||
File driverFile;
|
||||
try {
|
||||
driverFile = driverResources.download(context.getDatabaseType(), type.getJdbcDriverFileUrl());
|
||||
} catch (IOException e) {
|
||||
log.error("download driver error " + context, e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
|
||||
}
|
||||
|
||||
URLClassLoader loader = null;
|
||||
try {
|
||||
loader = new URLClassLoader(
|
||||
new URL[]{
|
||||
driverFile.toURI().toURL()
|
||||
},
|
||||
this.getClass().getClassLoader()
|
||||
);
|
||||
} catch (MalformedURLException e) {
|
||||
log.error("load driver error " + context, e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage());
|
||||
}
|
||||
|
||||
Class<?> clazz = null;
|
||||
Driver driver = null;
|
||||
try {
|
||||
clazz = Class.forName(type.getJdbcDriverClassName(), true, loader);
|
||||
driver = (Driver) clazz.getConstructor().newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error("init driver error", e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常, 请检查 Driver name:" + e.getMessage());
|
||||
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
|
||||
log.error("init driver error", e);
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception("驱动初始化异常:" + e.getMessage());
|
||||
}
|
||||
|
||||
Properties info = new Properties();
|
||||
info.put("user", context.getUsername());
|
||||
info.put("password", context.getPassword());
|
||||
String jdbcUrl = type.getJdbcProtocol() + "://" + context.getUrl() + "/" + context.getSchema();
|
||||
return driver.connect(jdbcUrl, info);
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
package com.databasir.core.infrastructure.connection;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
@@ -8,9 +11,22 @@ public interface DatabaseConnectionFactory {
|
||||
|
||||
boolean support(String databaseType);
|
||||
|
||||
Connection getConnection(String username,
|
||||
String password,
|
||||
String url,
|
||||
String schema,
|
||||
Properties properties) throws SQLException;
|
||||
Connection getConnection(Context context) throws SQLException;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
class Context {
|
||||
|
||||
private String databaseType;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String url;
|
||||
|
||||
private String schema;
|
||||
|
||||
private Properties properties;
|
||||
}
|
||||
}
|
||||
|
@@ -32,11 +32,19 @@ public class DatabaseConnectionService {
|
||||
Properties info = new Properties();
|
||||
dataSourceProperties.forEach(prop -> info.put(prop.getKey(), prop.getValue()));
|
||||
try {
|
||||
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.schema(dataSource.getDatabaseName())
|
||||
.properties(info)
|
||||
.databaseType(dataSource.getDatabaseType())
|
||||
.build();
|
||||
return factories.stream()
|
||||
.filter(factory -> factory.support(dataSource.getDatabaseType()))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
|
||||
.getConnection(username, password, url, dataSource.getDatabaseName(), info);
|
||||
.getConnection(context);
|
||||
} catch (SQLException e) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
|
||||
}
|
||||
@@ -49,11 +57,19 @@ public class DatabaseConnectionService {
|
||||
String databaseType,
|
||||
Properties properties) {
|
||||
try {
|
||||
DatabaseConnectionFactory.Context context = DatabaseConnectionFactory.Context.builder()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.schema(databaseName)
|
||||
.properties(properties)
|
||||
.databaseType(databaseType)
|
||||
.build();
|
||||
factories.stream()
|
||||
.filter(factory -> factory.support(databaseType))
|
||||
.findFirst()
|
||||
.orElseThrow(DomainErrors.NOT_SUPPORT_DATABASE_TYPE::exception)
|
||||
.getConnection(username, password, url, databaseName, properties);
|
||||
.getConnection(context);
|
||||
} catch (SQLException e) {
|
||||
throw DomainErrors.CONNECT_DATABASE_FAILED.exception(e.getMessage(), e);
|
||||
}
|
||||
|
@@ -1,10 +1,19 @@
|
||||
package com.databasir.core.infrastructure.connection;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public interface DatabaseTypes {
|
||||
|
||||
String MYSQL = "mysql";
|
||||
|
||||
String POSTGRESQL = "postgresql";
|
||||
|
||||
String ORACLE = "oracle";
|
||||
static boolean has(String name) {
|
||||
if (name == null) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(MYSQL, name.toLowerCase())
|
||||
|| Objects.equals(POSTGRESQL, name.toLowerCase());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,11 +16,7 @@ public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String username,
|
||||
String password,
|
||||
String url,
|
||||
String schema,
|
||||
Properties properties) throws SQLException {
|
||||
public Connection getConnection(Context context) throws SQLException {
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
} catch (ClassNotFoundException e) {
|
||||
@@ -28,10 +24,10 @@ public class MysqlDatabaseConnectionFactory implements DatabaseConnectionFactory
|
||||
}
|
||||
|
||||
Properties info = new Properties();
|
||||
info.put("user", username);
|
||||
info.put("password", password);
|
||||
info.putAll(properties);
|
||||
String jdbcUrl = "jdbc:mysql://" + url + "/" + schema;
|
||||
info.put("user", context.getUsername());
|
||||
info.put("password", context.getPassword());
|
||||
info.putAll(context.getProperties());
|
||||
String jdbcUrl = "jdbc:mysql://" + context.getUrl() + "/" + context.getSchema();
|
||||
return DriverManager.getConnection(jdbcUrl, info);
|
||||
}
|
||||
|
||||
|
@@ -16,11 +16,7 @@ public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFa
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String username,
|
||||
String password,
|
||||
String url,
|
||||
String schema,
|
||||
Properties properties) throws SQLException {
|
||||
public Connection getConnection(Context context) throws SQLException {
|
||||
try {
|
||||
Class.forName("org.postgresql.Driver");
|
||||
} catch (ClassNotFoundException e) {
|
||||
@@ -28,10 +24,10 @@ public class PostgresqlDatabaseConnectionFactory implements DatabaseConnectionFa
|
||||
}
|
||||
|
||||
Properties info = new Properties();
|
||||
info.put("user", username);
|
||||
info.put("password", password);
|
||||
info.putAll(properties);
|
||||
String jdbcUrl = "jdbc:postgresql://" + url + "/" + schema;
|
||||
info.put("user", context.getUsername());
|
||||
info.put("password", context.getPassword());
|
||||
info.putAll(context.getProperties());
|
||||
String jdbcUrl = "jdbc:postgresql://" + context.getUrl() + "/" + context.getSchema();
|
||||
return DriverManager.getConnection(jdbcUrl, info);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,84 @@
|
||||
package com.databasir.core.infrastructure.driver;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class DriverResources {
|
||||
|
||||
@Value("${databasir.db.driver-directory}")
|
||||
private String driverBaseDirectory;
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
public File download(String databaseType, String driverFileUrl) throws IOException {
|
||||
// create parent directory
|
||||
if (Files.notExists(Path.of(driverBaseDirectory))) {
|
||||
Files.createDirectory(Path.of(driverBaseDirectory));
|
||||
}
|
||||
|
||||
String filePath = driverPath(databaseType);
|
||||
Path path = Path.of(filePath);
|
||||
if (Files.exists(path)) {
|
||||
// ignore
|
||||
log.debug("{} already exists, ignore download from {}", filePath, driverFileUrl);
|
||||
return path.toFile();
|
||||
} else {
|
||||
// download
|
||||
try {
|
||||
return restTemplate.execute(driverFileUrl, HttpMethod.GET, null, response -> {
|
||||
if (response.getStatusCode().is2xxSuccessful()) {
|
||||
File file = path.toFile();
|
||||
StreamUtils.copy(response.getBody(), new FileOutputStream(file));
|
||||
log.info("{} download success ", filePath);
|
||||
return file;
|
||||
} else {
|
||||
log.error("{} download error from {}: {} ", filePath, driverFileUrl, response);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception("驱动下载失败:"
|
||||
+ response.getStatusCode()
|
||||
+ ", "
|
||||
+ response.getStatusText());
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error(filePath + " download driver error", e);
|
||||
throw DomainErrors.DOWNLOAD_DRIVER_ERROR.exception(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(String databaseType) {
|
||||
Path path = Paths.get(driverPath(databaseType));
|
||||
try {
|
||||
Files.deleteIfExists(path);
|
||||
} catch (IOException e) {
|
||||
log.error("delete driver error " + databaseType, e);
|
||||
}
|
||||
}
|
||||
|
||||
private String driverPath(String databaseType) {
|
||||
String fileName = databaseType + ".jar";
|
||||
String filePath;
|
||||
if (driverBaseDirectory.endsWith(File.separator)) {
|
||||
filePath = driverBaseDirectory + fileName;
|
||||
} else {
|
||||
filePath = driverBaseDirectory + File.separator + fileName;
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
package com.databasir.core.infrastructure.meta;
|
||||
|
||||
public class DatabaseMetaResolver {
|
||||
|
||||
}
|
Reference in New Issue
Block a user