mirror of https://github.com/elunez/eladmin
Merge branch '2.4opt' into 2.4dev
commit
aa2da4e222
|
@ -3,15 +3,23 @@ package me.zhengjie.modules.mnt.rest;
|
|||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import me.zhengjie.aop.log.Log;
|
||||
import me.zhengjie.exception.BadRequestException;
|
||||
import me.zhengjie.modules.mnt.domain.Database;
|
||||
import me.zhengjie.modules.mnt.service.DatabaseService;
|
||||
import me.zhengjie.modules.mnt.service.dto.DatabaseDto;
|
||||
import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria;
|
||||
import me.zhengjie.modules.mnt.util.SqlUtils;
|
||||
import me.zhengjie.utils.FileUtil;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author zhanghouying
|
||||
|
@ -22,6 +30,8 @@ import org.springframework.web.bind.annotation.*;
|
|||
@RequestMapping("/api/database")
|
||||
public class DatabaseController {
|
||||
|
||||
private String fileSavePath = System.getProperty("java.io.tmpdir");
|
||||
|
||||
private final DatabaseService databaseService;
|
||||
|
||||
public DatabaseController(DatabaseService databaseService) {
|
||||
|
@ -61,4 +71,32 @@ public class DatabaseController {
|
|||
databaseService.delete(id);
|
||||
return new ResponseEntity(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("测试数据库链接")
|
||||
@ApiOperation(value = "测试数据库链接")
|
||||
@PostMapping("/testConnect")
|
||||
@PreAuthorize("@el.check('database:testConnect')")
|
||||
public ResponseEntity testConnect(@Validated @RequestBody Database resources){
|
||||
return new ResponseEntity<>(databaseService.testConnection(resources),HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("执行SQL脚本")
|
||||
@ApiOperation(value = "执行SQL脚本")
|
||||
@PostMapping(value = "/upload")
|
||||
@PreAuthorize("@el.check('database:add')")
|
||||
public ResponseEntity upload(@RequestBody MultipartFile file, HttpServletRequest request)throws Exception{
|
||||
String id = request.getParameter("id");
|
||||
DatabaseDto database = databaseService.findById(id);
|
||||
String fileName = "";
|
||||
if(database != null){
|
||||
fileName = file.getOriginalFilename();
|
||||
File executeFile = new File(fileSavePath+fileName);
|
||||
FileUtil.del(executeFile);
|
||||
file.transferTo(executeFile);
|
||||
String result = SqlUtils.executeFile(database.getJdbcUrl(), database.getUserName(), database.getPwd(), executeFile);
|
||||
return new ResponseEntity<>(result,HttpStatus.OK);
|
||||
}else{
|
||||
throw new BadRequestException("Database not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,4 +51,11 @@ public interface DatabaseService {
|
|||
* @param id /
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 测试连接数据库
|
||||
* @param resources
|
||||
* @return
|
||||
*/
|
||||
boolean testConnection(Database resources);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package me.zhengjie.modules.mnt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhengjie.modules.mnt.domain.Database;
|
||||
import me.zhengjie.modules.mnt.repository.DatabaseRepository;
|
||||
import me.zhengjie.modules.mnt.service.DatabaseService;
|
||||
import me.zhengjie.modules.mnt.service.dto.DatabaseDto;
|
||||
import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria;
|
||||
import me.zhengjie.modules.mnt.service.mapper.DatabaseMapper;
|
||||
import me.zhengjie.modules.mnt.util.SqlUtils;
|
||||
import me.zhengjie.utils.PageUtil;
|
||||
import me.zhengjie.utils.QueryHelp;
|
||||
import me.zhengjie.utils.ValidationUtil;
|
||||
|
@ -21,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
* @date 2019-08-24
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||
public class DatabaseServiceImpl implements DatabaseService {
|
||||
|
||||
|
@ -72,4 +75,15 @@ public class DatabaseServiceImpl implements DatabaseService {
|
|||
public void delete(String id) {
|
||||
databaseRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testConnection(Database resources) {
|
||||
try {
|
||||
return SqlUtils.testConnection(resources.getJdbcUrl(), resources.getUserName(), resources.getPwd());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* <<
|
||||
* Davinci
|
||||
* ==
|
||||
* Copyright (C) 2016 - 2019 EDP
|
||||
* ==
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* >>
|
||||
*
|
||||
*/
|
||||
|
||||
package me.zhengjie.modules.mnt.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public enum DataTypeEnum {
|
||||
|
||||
MYSQL("mysql", "mysql", "com.mysql.jdbc.Driver", "`", "`", "'", "'"),
|
||||
|
||||
ORACLE("oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "\"", "\"", "\"", "\""),
|
||||
|
||||
SQLSERVER("sqlserver", "sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "\"", "\"", "\"", "\""),
|
||||
|
||||
H2("h2", "h2", "org.h2.Driver", "`", "`", "\"", "\""),
|
||||
|
||||
PHOENIX("phoenix", "hbase phoenix", "org.apache.phoenix.jdbc.PhoenixDriver", "", "", "\"", "\""),
|
||||
|
||||
MONGODB("mongo", "mongodb", "mongodb.jdbc.MongoDriver", "`", "`", "\"", "\""),
|
||||
|
||||
ELASTICSEARCH("sql4es", "elasticsearch", "nl.anchormen.sql4es.jdbc.ESDriver", "", "", "'", "'"),
|
||||
|
||||
PRESTO("presto", "presto", "com.facebook.presto.jdbc.PrestoDriver", "", "", "\"", "\""),
|
||||
|
||||
MOONBOX("moonbox", "moonbox", "moonbox.jdbc.MbDriver", "`", "`", "`", "`"),
|
||||
|
||||
CASSANDRA("cassandra", "cassandra", "com.github.adejanovski.cassandra.jdbc.CassandraDriver", "", "", "'", "'"),
|
||||
|
||||
CLICKHOUSE("clickhouse", "clickhouse", "ru.yandex.clickhouse.ClickHouseDriver", "", "", "\"", "\""),
|
||||
|
||||
KYLIN("kylin", "kylin", "org.apache.kylin.jdbc.Driver", "\"", "\"", "\"", "\""),
|
||||
|
||||
VERTICA("vertica", "vertica", "com.vertica.jdbc.Driver", "", "", "'", "'"),
|
||||
|
||||
HANA("sap", "sap hana", "com.sap.db.jdbc.Driver", "", "", "'", "'"),
|
||||
|
||||
IMPALA("impala", "impala", "com.cloudera.impala.jdbc41.Driver", "", "", "'", "'");
|
||||
|
||||
|
||||
private String feature;
|
||||
private String desc;
|
||||
private String driver;
|
||||
private String keywordPrefix;
|
||||
private String keywordSuffix;
|
||||
private String aliasPrefix;
|
||||
private String aliasSuffix;
|
||||
|
||||
private static final String jdbcUrlPrefix = "jdbc:";
|
||||
|
||||
DataTypeEnum(String feature, String desc, String driver, String keywordPrefix, String keywordSuffix, String aliasPrefix, String aliasSuffix) {
|
||||
this.feature = feature;
|
||||
this.desc = desc;
|
||||
this.driver = driver;
|
||||
this.keywordPrefix = keywordPrefix;
|
||||
this.keywordSuffix = keywordSuffix;
|
||||
this.aliasPrefix = aliasPrefix;
|
||||
this.aliasSuffix = aliasSuffix;
|
||||
}
|
||||
|
||||
public static DataTypeEnum urlOf(String jdbcUrl) {
|
||||
String url = jdbcUrl.toLowerCase().trim();
|
||||
for (DataTypeEnum dataTypeEnum : values()) {
|
||||
if (url.startsWith(jdbcUrlPrefix + dataTypeEnum.feature)) {
|
||||
try {
|
||||
Class<?> aClass = Class.forName(dataTypeEnum.getDriver());
|
||||
if (null == aClass) {
|
||||
throw new RuntimeException("Unable to get driver instance for jdbcUrl: " + jdbcUrl);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unable to get driver instance: " + jdbcUrl);
|
||||
}
|
||||
return dataTypeEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
public String getKeywordPrefix() {
|
||||
return keywordPrefix;
|
||||
}
|
||||
|
||||
public String getKeywordSuffix() {
|
||||
return keywordSuffix;
|
||||
}
|
||||
|
||||
public String getAliasPrefix() {
|
||||
return aliasPrefix;
|
||||
}
|
||||
|
||||
public String getAliasSuffix() {
|
||||
return aliasSuffix;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
package me.zhengjie.modules.mnt.util;
|
||||
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.util.StringUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class SqlUtils {
|
||||
|
||||
public static final String COLON = ":";
|
||||
|
||||
private static volatile Map<String, DruidDataSource> map = new HashMap<>();
|
||||
|
||||
private static String getKey(String jdbcUrl, String username, String password) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringUtils.isEmpty(username)) {
|
||||
sb.append(username);
|
||||
}
|
||||
if (!StringUtils.isEmpty(password)) {
|
||||
sb.append(COLON).append(password);
|
||||
}
|
||||
sb.append(COLON).append(jdbcUrl.trim());
|
||||
|
||||
return SecureUtil.md5(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据源
|
||||
*
|
||||
* @param jdbcUrl
|
||||
* @param userName
|
||||
* @param password
|
||||
* @return
|
||||
*/
|
||||
private static DataSource getDataSource(String jdbcUrl, String userName, String password) {
|
||||
String key = getKey(jdbcUrl, userName, password);
|
||||
if (!map.containsKey(key) || null == map.get(key)) {
|
||||
DruidDataSource druidDataSource = new DruidDataSource();
|
||||
|
||||
String className = null;
|
||||
try {
|
||||
className = DriverManager.getDriver(jdbcUrl.trim()).getClass().getName();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Get class name error: =" + jdbcUrl);
|
||||
}
|
||||
if (StringUtils.isEmpty(className)) {
|
||||
DataTypeEnum dataTypeEnum = DataTypeEnum.urlOf(jdbcUrl);
|
||||
if (null == dataTypeEnum) {
|
||||
throw new RuntimeException("Not supported data type: jdbcUrl=" + jdbcUrl);
|
||||
}
|
||||
druidDataSource.setDriverClassName(dataTypeEnum.getDriver());
|
||||
} else {
|
||||
druidDataSource.setDriverClassName(className);
|
||||
}
|
||||
|
||||
|
||||
druidDataSource.setUrl(jdbcUrl);
|
||||
druidDataSource.setUsername(userName);
|
||||
druidDataSource.setPassword(password);
|
||||
// 配置获取连接等待超时的时间
|
||||
druidDataSource.setMaxWait(3000);
|
||||
// 配置初始化大小、最小、最大
|
||||
druidDataSource.setInitialSize(1);
|
||||
druidDataSource.setMinIdle(1);
|
||||
druidDataSource.setMaxActive(1);
|
||||
|
||||
// 配置间隔多久才进行一次检测需要关闭的空闲连接,单位是毫秒
|
||||
druidDataSource.setTimeBetweenEvictionRunsMillis(50000);
|
||||
// 配置一旦重试多次失败后等待多久再继续重试连接,单位是毫秒
|
||||
druidDataSource.setTimeBetweenConnectErrorMillis(18000);
|
||||
// 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
druidDataSource.setMinEvictableIdleTimeMillis(300000);
|
||||
// 这个特性能解决 MySQL 服务器8小时关闭连接的问题
|
||||
druidDataSource.setMaxEvictableIdleTimeMillis(25200000);
|
||||
|
||||
try {
|
||||
druidDataSource.init();
|
||||
} catch (SQLException e) {
|
||||
log.error("Exception during pool initialization", e);
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
map.put(key, druidDataSource);
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
private static Connection getConnection(String jdbcUrl, String userName, String password) {
|
||||
DataSource dataSource = getDataSource(jdbcUrl, userName, password);
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = dataSource.getConnection();
|
||||
} catch (Exception e) {
|
||||
connection = null;
|
||||
}
|
||||
try {
|
||||
if (null == connection || connection.isClosed() || !connection.isValid(5)) {
|
||||
log.info("connection is closed or invalid, retry get connection!");
|
||||
connection = dataSource.getConnection();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("create connection error, jdbcUrl: {}", jdbcUrl);
|
||||
throw new RuntimeException("create connection error, jdbcUrl: " + jdbcUrl);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static void releaseConnection(Connection connection) {
|
||||
if (null != connection) {
|
||||
try {
|
||||
connection.close();
|
||||
connection = null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("connection close error", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void closeResult(ResultSet rs) {
|
||||
if (rs != null) {
|
||||
try {
|
||||
rs.close();
|
||||
rs = null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean testConnection(String jdbcUrl, String userName, String password) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection(jdbcUrl, userName, password);
|
||||
if (null != connection) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("Get connection failed:", e.getMessage());
|
||||
} finally {
|
||||
releaseConnection(connection);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String executeFile(String jdbcUrl, String userName, String password, File sqlFile) {
|
||||
Connection connection = getConnection(jdbcUrl, userName, password);
|
||||
try {
|
||||
batchExecute(connection, readSqlList( sqlFile));
|
||||
} catch (Exception e) {
|
||||
log.error("sql脚本执行发生异常:{}",e.getMessage());
|
||||
return e.getMessage();
|
||||
}finally {
|
||||
releaseConnection(connection);
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量执行sql
|
||||
* @param connection
|
||||
* @param sqlList
|
||||
* @return
|
||||
*/
|
||||
public static void batchExecute(Connection connection, List<String> sqlList) throws SQLException {
|
||||
Statement st = connection.createStatement();
|
||||
for (String sql : sqlList) {
|
||||
if (sql.endsWith(";")) {
|
||||
sql = sql.substring(0, sql.length() - 1);
|
||||
}
|
||||
st.addBatch(sql);
|
||||
}
|
||||
st.executeBatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件中的sql语句以;为单位读取到列表中
|
||||
* @param sqlFile
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private static List<String> readSqlList(File sqlFile) throws Exception {
|
||||
List<String> sqlList = Lists.newArrayList();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(sqlFile), "UTF-8"));
|
||||
String tmp = null;
|
||||
while ((tmp = reader.readLine()) != null) {
|
||||
log.info("line:{}", tmp);
|
||||
if (tmp.endsWith(";")) {
|
||||
sb.append(tmp);
|
||||
sqlList.add(sb.toString());
|
||||
sb.delete(0, sb.length());
|
||||
} else {
|
||||
sb.append(tmp);
|
||||
}
|
||||
}
|
||||
if (!"".endsWith(sb.toString().trim())) {
|
||||
sqlList.add(sb.toString());
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException e1) {
|
||||
}
|
||||
}
|
||||
|
||||
return sqlList;
|
||||
}
|
||||
|
||||
}
|
|
@ -367,6 +367,8 @@ CREATE TABLE `mnt_database` (
|
|||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
|
||||
|
||||
INSERT INTO `mnt_database` VALUES ('604dd98ae8b44b128544c2135628f87d', '本机', 'jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=UTC', 'root', '123456');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for mnt_deploy
|
||||
-- ----------------------------
|
||||
|
|
Loading…
Reference in New Issue