+ HikariHandler 新增 createDataSource 方法用于没有导入 HikariCP 库的项目使用。
+ 新增 /texecute 指令用于强制目标执行命令或发送聊天信息。 + 新增 hikarisettings.yml 配置用于更改默认连接池设置。 o 修复 HikariHandler 重复创建连接池的问题。 o 修复 SQLTable 中 addColumn 方法无效的问题。
This commit is contained in:
parent
33b90c64d2
commit
6cf9665d35
@ -8,11 +8,12 @@ import com.ilummc.tlib.util.IO;
|
||||
import com.ilummc.tlib.util.Strings;
|
||||
import me.skymc.taboolib.anvil.AnvilContainerAPI;
|
||||
import me.skymc.taboolib.bstats.Metrics;
|
||||
import me.skymc.taboolib.commands.TabooLibExecuteCommand;
|
||||
import me.skymc.taboolib.commands.TabooLibMainCommand;
|
||||
import me.skymc.taboolib.commands.internal.TBaseCommand;
|
||||
import me.skymc.taboolib.commands.language.Language2Command;
|
||||
import me.skymc.taboolib.commands.locale.TabooLibLocaleCommand;
|
||||
import me.skymc.taboolib.commands.plugin.TabooLibPluginMainCommand;
|
||||
import me.skymc.taboolib.commands.plugin.TabooLibPluginCommand;
|
||||
import me.skymc.taboolib.commands.taboolib.listener.ListenerItemListCommand;
|
||||
import me.skymc.taboolib.commands.taboolib.listener.ListenerSoundsCommand;
|
||||
import me.skymc.taboolib.database.GlobalDataManager;
|
||||
@ -45,6 +46,7 @@ import me.skymc.taboolib.update.UpdateTask;
|
||||
import me.skymc.tlm.TLM;
|
||||
import me.skymc.tlm.command.TLMCommands;
|
||||
import me.skymc.tlm.module.TabooLibraryModule;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -74,25 +76,15 @@ public class Main extends JavaPlugin implements Listener {
|
||||
}
|
||||
|
||||
private static Plugin inst;
|
||||
|
||||
private static net.milkbowl.vault.economy.Economy Economy;
|
||||
|
||||
private static Economy economy;
|
||||
private static File playerDataFolder;
|
||||
|
||||
private static File serverDataFolder;
|
||||
|
||||
private static StorageType storageType = StorageType.LOCAL;
|
||||
|
||||
private static boolean disable = false;
|
||||
|
||||
private static MySQLConnection connection = null;
|
||||
|
||||
private static Language2 exampleLanguage2;
|
||||
|
||||
private static boolean started;
|
||||
|
||||
private static boolean disable = false;
|
||||
private static boolean started = false;
|
||||
private static boolean isInternetOnline = false;
|
||||
|
||||
private FileConfiguration config = null;
|
||||
|
||||
@Override
|
||||
@ -132,6 +124,8 @@ public class Main extends JavaPlugin implements Listener {
|
||||
setupLibraries();
|
||||
// 载入牛逼玩意儿
|
||||
TLib.initPost();
|
||||
// 注册连接池
|
||||
HikariHandler.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -348,7 +342,8 @@ public class Main extends JavaPlugin implements Listener {
|
||||
getCommand("taboolibrarymodule").setExecutor(new TLMCommands());
|
||||
TBaseCommand.registerCommand("taboolib", new TabooLibMainCommand());
|
||||
TBaseCommand.registerCommand("tabooliblocale", new TabooLibLocaleCommand());
|
||||
TBaseCommand.registerCommand("taboolibplugin", new TabooLibPluginMainCommand());
|
||||
TBaseCommand.registerCommand("taboolibplugin", new TabooLibPluginCommand());
|
||||
TBaseCommand.registerCommand("taboolibexecute", new TabooLibExecuteCommand());
|
||||
TBaseCommand.registerCommand("translateuuid", new TranslateUUIDCommand());
|
||||
}
|
||||
|
||||
@ -390,11 +385,11 @@ public class Main extends JavaPlugin implements Listener {
|
||||
}
|
||||
|
||||
public static net.milkbowl.vault.economy.Economy getEconomy() {
|
||||
return Economy;
|
||||
return economy;
|
||||
}
|
||||
|
||||
public static void setEconomy(net.milkbowl.vault.economy.Economy economy) {
|
||||
Economy = economy;
|
||||
public static void setEconomy(Economy economy) {
|
||||
this.economy = economy;
|
||||
}
|
||||
|
||||
public static File getPlayerDataFolder() {
|
||||
|
@ -0,0 +1,116 @@
|
||||
package me.skymc.taboolib.commands;
|
||||
|
||||
import com.ilummc.tlib.resources.TLocale;
|
||||
import com.ilummc.tlib.util.Strings;
|
||||
import me.skymc.taboolib.commands.internal.BaseMainCommand;
|
||||
import me.skymc.taboolib.commands.internal.BaseSubCommand;
|
||||
import me.skymc.taboolib.commands.internal.type.CommandArgument;
|
||||
import me.skymc.taboolib.commands.internal.type.CommandRegister;
|
||||
import me.skymc.taboolib.string.ArrayUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-07-04 21:32
|
||||
*/
|
||||
public class TabooLibExecuteCommand extends BaseMainCommand {
|
||||
|
||||
@Override
|
||||
public String getCommandTitle() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.COMMAND-TITLE");
|
||||
}
|
||||
|
||||
@CommandRegister(priority = 1)
|
||||
BaseSubCommand chat = new BaseSubCommand() {
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "chat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.CHAT.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.CHAT.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.CHAT.ARGUMENTS.1"))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "INVALID-PLAYER-OFFLINE", args[0]);
|
||||
return;
|
||||
}
|
||||
player.chat(ArrayUtils.arrayJoin(args, 1));
|
||||
}
|
||||
};
|
||||
|
||||
@CommandRegister(priority = 1)
|
||||
BaseSubCommand command = new BaseSubCommand() {
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "command";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return TLocale.asString("COMMANDS.TEXECUTE.COMMAND.DESCRIPTION");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArgument[] getArguments() {
|
||||
return new CommandArgument[] {
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND.ARGUMENTS.0")),
|
||||
new CommandArgument(TLocale.asString("COMMANDS.TEXECUTE.COMMAND.ARGUMENTS.1"))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args[0].equalsIgnoreCase("console")) {
|
||||
dispatchCommand(Bukkit.getConsoleSender(), ArrayUtils.arrayJoin(args, 1));
|
||||
return;
|
||||
}
|
||||
Player player = Bukkit.getPlayerExact(args[0]);
|
||||
if (player == null) {
|
||||
TLocale.sendTo(sender, "INVALID-TARGET-NOT-FOUND", args[0]);
|
||||
return;
|
||||
}
|
||||
dispatchCommand(player, ArrayUtils.arrayJoin(args, 1));
|
||||
}
|
||||
};
|
||||
|
||||
public static boolean dispatchCommand(CommandSender sender, String command) {
|
||||
try {
|
||||
if ((sender instanceof Player)) {
|
||||
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent((Player) sender, "/" + command);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled() || Strings.isBlank(e.getMessage()) || !e.getMessage().startsWith("/")) {
|
||||
return false;
|
||||
}
|
||||
return Bukkit.dispatchCommand(e.getPlayer(), e.getMessage().substring(1));
|
||||
} else {
|
||||
ServerCommandEvent e = new ServerCommandEvent(sender, command);
|
||||
Bukkit.getPluginManager().callEvent(e);
|
||||
if (e.isCancelled() || Strings.isBlank(e.getCommand())) {
|
||||
return false;
|
||||
}
|
||||
return Bukkit.dispatchCommand(e.getSender(), e.getCommand());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ import java.util.stream.Collectors;
|
||||
* @Author sky
|
||||
* @Since 2018-05-07 20:14
|
||||
*/
|
||||
public class TabooLibPluginMainCommand extends BaseMainCommand {
|
||||
public class TabooLibPluginCommand extends BaseMainCommand {
|
||||
|
||||
@Override
|
||||
public String getCommandTitle() {
|
@ -78,13 +78,12 @@ public class SQLHost {
|
||||
Objects.equals(getUser(), sqlHost.getUser()) &&
|
||||
Objects.equals(getPort(), sqlHost.getPort()) &&
|
||||
Objects.equals(getPassword(), sqlHost.getPassword()) &&
|
||||
Objects.equals(getDatabase(), sqlHost.getDatabase()) &&
|
||||
Objects.equals(getPlugin(), sqlHost.getPlugin());
|
||||
Objects.equals(getDatabase(), sqlHost.getDatabase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase(), getPlugin());
|
||||
return Objects.hash(getHost(), getUser(), getPort(), getPassword(), getDatabase());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,11 +1,12 @@
|
||||
package me.skymc.taboolib.mysql.builder;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.ilummc.tlib.util.Strings;
|
||||
import me.skymc.taboolib.mysql.builder.query.RunnableQuery;
|
||||
import me.skymc.taboolib.mysql.builder.query.RunnableUpdate;
|
||||
import me.skymc.taboolib.string.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-05-14 19:07
|
||||
@ -28,17 +29,14 @@ public class SQLTable {
|
||||
if (columns == null) {
|
||||
columns = new SQLColumn[] {sqlColumn};
|
||||
} else {
|
||||
ArrayUtils.arrayAppend(columns, sqlColumn);
|
||||
columns = ArrayUtils.arrayAppend(columns, sqlColumn);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String createQuery() {
|
||||
Preconditions.checkNotNull(columns);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (SQLColumn sqlColumn : columns) {
|
||||
builder.append(sqlColumn.convertToCommand()).append(", ");
|
||||
}
|
||||
Arrays.stream(columns).forEach(sqlColumn -> builder.append(sqlColumn.convertToCommand()).append(", "));
|
||||
return Strings.replaceWithOrder("create table if not exists `{0}` ({1})", tableName, builder.substring(0, builder.length() - 2));
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,13 @@ import com.ilummc.tlib.resources.TLocale;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import me.skymc.taboolib.Main;
|
||||
import me.skymc.taboolib.fileutils.ConfigUtils;
|
||||
import me.skymc.taboolib.fileutils.FileUtils;
|
||||
import me.skymc.taboolib.mysql.builder.SQLHost;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@ -16,14 +21,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class HikariHandler {
|
||||
|
||||
private static ConcurrentHashMap<SQLHost, MapDataSource> dataSource = new ConcurrentHashMap<>();
|
||||
private static FileConfiguration settings;
|
||||
|
||||
public static void init() {
|
||||
settings = ConfigUtils.saveDefaultConfig(Main.getInst(), "hikarisettings.yml");
|
||||
}
|
||||
|
||||
public static DataSource createDataSource(SQLHost host) {
|
||||
return createDataSource(host, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数据库地址创建连接池,如果已经存在则返回引用
|
||||
*
|
||||
* @param host 数据库地址
|
||||
* @return {@link HikariDataSource}
|
||||
* @throws java.sql.SQLException 数据库连接失败异常
|
||||
*/
|
||||
public static HikariDataSource createDataSource(SQLHost host, HikariConfig hikariConfig) {
|
||||
MapDataSource mapDataSource = dataSource.computeIfAbsent(host, x -> new MapDataSource(x, new HikariDataSource(hikariConfig == null ? createConfig(host) : hikariConfig)));
|
||||
mapDataSource.getActivePlugin().getAndIncrement();
|
||||
@ -35,21 +42,11 @@ public class HikariHandler {
|
||||
return mapDataSource.getHikariDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制注销所有已注册的连接池
|
||||
* 只能在 TabooLib 卸载后调用
|
||||
*/
|
||||
public static void closeDataSourceForce() {
|
||||
Preconditions.checkArgument(Main.isDisable(), "Cannot be invoked when the server is running.");
|
||||
dataSource.values().forEach(x -> x.getHikariDataSource().close());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销连接池
|
||||
* 如果连接池有 1 个以上的插件正在使用则跳过,反之则注销并从缓存中移除
|
||||
*
|
||||
* @param host 地址
|
||||
*/
|
||||
public static void closeDataSource(SQLHost host) {
|
||||
if (host != null && dataSource.containsKey(host)) {
|
||||
MapDataSource mapDataSource = dataSource.get(host);
|
||||
@ -63,37 +60,26 @@ public class HikariHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数据库地址创建 HikariConfig 对象
|
||||
*
|
||||
* @param sqlHost 数据库地址
|
||||
* @return {@link HikariConfig}
|
||||
*/
|
||||
public static HikariConfig createConfig(SQLHost sqlHost) {
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setDriverClassName("com.mysql.jdbc.Driver");
|
||||
config.setDriverClassName(settings.getString("DefaultSettings.DriverClassName", "com.mysql.jdbc.Driver"));
|
||||
config.setJdbcUrl(sqlHost.getConnectionUrl());
|
||||
config.setUsername(sqlHost.getUser());
|
||||
config.setPassword(sqlHost.getPassword());
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setAutoCommit(true);
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(10);
|
||||
// 用来指定验证连接有效性的超时时间(毫秒/默认: 5秒)
|
||||
config.setValidationTimeout(3000);
|
||||
// 等待连接池分配连接的最大时长(毫秒/默认: 30秒),超过这个时长还没可用的连接则发生 SQLException
|
||||
config.setConnectionTimeout(10000);
|
||||
// 一个连接idle状态的最大时长(毫秒/默认: 10分钟),超时则被释放
|
||||
config.setIdleTimeout(60000);
|
||||
// 一个连接的生命时长(毫秒/默认: 30分钟),超时而且没被使用则被释放
|
||||
config.setMaxLifetime(60000);
|
||||
// 是否自定义配置,为true时下面两个参数才生效
|
||||
config.setAutoCommit(settings.getBoolean("DefaultSettings.AutoCommit", true));
|
||||
config.setMinimumIdle(settings.getInt("DefaultSettings.MinimumIdle", 1));
|
||||
config.setMaximumPoolSize(settings.getInt("DefaultSettings.MaximumPoolSize", 10));
|
||||
config.setValidationTimeout(settings.getInt("DefaultSettings.ValidationTimeout", 3000));
|
||||
config.setConnectionTimeout(settings.getInt("DefaultSettings.ConnectionTimeout", 10000));
|
||||
config.setIdleTimeout(settings.getInt("DefaultSettings.IdleTimeout", 60000));
|
||||
config.setMaxLifetime(settings.getInt("DefaultSettings.MaxLifetime", 60000));
|
||||
if (settings.contains("DefaultSettings.DataSourceProperty")) {
|
||||
settings.getConfigurationSection("DefaultSettings.DataSourceProperty").getKeys(false).forEach(key -> config.addDataSourceProperty(key, settings.getString("DefaultSettings.DataSourceProperty." + key)));
|
||||
} else {
|
||||
config.addDataSourceProperty("cachePrepStmts", "true");
|
||||
// 连接池大小默认25,官方推荐250-500
|
||||
config.addDataSourceProperty("prepStmtCacheSize", "250");
|
||||
// 单条语句最大长度默认256,官方推荐2048
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
|
||||
// 新版本MySQL支持服务器端准备,开启能够得到显著性能提升
|
||||
config.addDataSourceProperty("useServerPrepStmts", "true");
|
||||
config.addDataSourceProperty("useLocalSessionState", "true");
|
||||
config.addDataSourceProperty("useLocalTransactionState", "true");
|
||||
@ -102,6 +88,7 @@ public class HikariHandler {
|
||||
config.addDataSourceProperty("cacheServerConfiguration", "true");
|
||||
config.addDataSourceProperty("elideSetAutoCommits", "true");
|
||||
config.addDataSourceProperty("maintainTimeStats", "false");
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import com.google.gson.JsonParser;
|
||||
import com.ilummc.tlib.resources.TLocale;
|
||||
import me.skymc.taboolib.Main;
|
||||
import me.skymc.taboolib.TabooLib;
|
||||
import me.skymc.taboolib.commands.plugin.TabooLibPluginMainCommand;
|
||||
import me.skymc.taboolib.fileutils.FileUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
32
src/main/resources/hikarisettings.yml
Normal file
32
src/main/resources/hikarisettings.yml
Normal file
@ -0,0 +1,32 @@
|
||||
# 默认连接池配置
|
||||
DefaultSettings:
|
||||
DriverClassName: 'com.mysql.jdbc.Driver'
|
||||
AutoCommit: true
|
||||
MinimumIdle: 1
|
||||
# 连接池大小
|
||||
MaximumPoolSize: 10
|
||||
# 用来指定验证连接有效性的超时时间(毫秒/默认: 5秒)
|
||||
ValidationTimeout: 3000
|
||||
# 等待连接池分配连接的最大时长(毫秒/默认: 30秒)
|
||||
# 超过这个时长还没可用的连接则发生 SQLException
|
||||
ConnectionTimeout: 10000
|
||||
# 一个连接idle状态的最大时长(毫秒/默认: 10分钟),超时则被释放
|
||||
IdleTimeout: 60000
|
||||
# 一个连接的生命时长(毫秒/默认: 30分钟),超时而且没被使用则被释放
|
||||
MaxLifetime: 60000
|
||||
# 是否自定义配置,为true时下面两个参数才生效
|
||||
DataSourceProperty:
|
||||
cachePrepStmts: true
|
||||
# 连接池大小默认25,官方推荐250-500
|
||||
prepStmtCacheSize: 250
|
||||
# 单条语句最大长度默认256,官方推荐2048
|
||||
prepStmtCacheSqlLimit: 2048
|
||||
# 新版本MySQL支持服务器端准备,开启能够得到显著性能提升
|
||||
useServerPrepStmts: true
|
||||
useLocalSessionState: true
|
||||
useLocalTransactionState: true
|
||||
rewriteBatchedStatements: true
|
||||
cacheResultSetMetadata: true
|
||||
cacheServerConfiguration: true
|
||||
elideSetAutoCommits: true
|
||||
maintainTimeStats: false
|
@ -533,6 +533,20 @@ COMMANDS:
|
||||
RELOAD:
|
||||
DESCRIPTION: '重载配置及数据库'
|
||||
SUCCESS: '&8[&3&lTabooLib&8] &7请求已发送, 详细信息请查看控制台'
|
||||
TEXECUTE:
|
||||
COMMAND-TITLE: '&e&l----- &6&lTabooLibExecute Commands &e&l-----'
|
||||
CHAT:
|
||||
DESCRIPTION: '使玩家输入聊天内容'
|
||||
ARGUMENTS:
|
||||
0: '玩家'
|
||||
1: '内容'
|
||||
INVALID-PLAYER-OFFLINE: '&8[&3&lTabooLib&8] &4玩家 &c{0} &4不在线.'
|
||||
COMMAND:
|
||||
DESCRIPTION: '使目标输入执行指令'
|
||||
ARGUMENTS:
|
||||
0: '目标'
|
||||
1: '内容'
|
||||
INVALID-TARGET-NOT-FOUND: '&8[&3&lTabooLib&8] &4目标 &c{0} &4不存在.'
|
||||
|
||||
DATABASE:
|
||||
CONNECTION-ESTABLISHED: '成功连接到 {0} 数据库,连接池大小 {1}'
|
||||
|
@ -21,6 +21,9 @@ commands:
|
||||
taboolibplugin:
|
||||
aliases: [tabooplugin, tplugin]
|
||||
permission: taboolib.admin
|
||||
taboolibexecute:
|
||||
aliases: [texecute]
|
||||
permission: taboolib.admin
|
||||
taboolibrarymodule:
|
||||
aliases: [tlm]
|
||||
translateuuid:
|
||||
|
Loading…
Reference in New Issue
Block a user