| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- package manager;
- import com.fasterxml.jackson.databind.DeserializationFeature;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import util.ClassLoaderHelper;
- import util.StringUtil;
- import util.SysUtil;
- import java.io.*;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.util.*;
- import java.util.concurrent.ConcurrentHashMap;
- public class STableManager {
- private static final Logger LOGGER = LoggerFactory.getLogger(STableManager.class);
- /**
- * table表包名
- */
- private static String data_parackage = null;
- private static String jsonPath;
- private static int currentDbVersion;
- /**
- * des 配置类缓存
- * 1 懒加载 各个模块各取所需
- * 2 为了热更新 整体替换 避免表相互依赖造成的安全问题
- * 3 为保证所有数据一致性 做了以下处理
- * a 去掉了配置类中静态配置数据 所有获取都应该从此map中拿 保证最新和一致
- */
- private static final Map<String, Object> tableBeanMap = new ConcurrentHashMap<>();
- /**
- * des 模块内的配置2次处理的静态数据
- * 1 模块数据和纯配置数据分离
- * 2 为了热更新 整体替换 避免表相互依赖造成的安全问题
- */
- private static final Map<String, AbstractClassStaticConfig> classStaticConfigMap = new ConcurrentHashMap<>();
- public static void initialize(String data_parackage) throws Exception {
- STableManager.data_parackage = data_parackage;
- updateTablesWithTableNames(false);
- initJsonPath();
- initDbVersion();
- }
- /**
- * 根据表名字更新表数据
- *
- * @throws Exception
- */
- public static void updateTablesWithTableNames(boolean isHotFix) throws Exception {
- String[] tableList = null;
- if (isHotFix) {
- CDataBaseVersion version = getJsonFilePathInJsonConf("c_database_version.json", CDataBaseVersion.class);
- if (version == null || version.getTables().isEmpty() || currentDbVersion >= version.getVersion()) { // 启动而不是热更
- return;
- }
- currentDbVersion = version.getVersion();
- //更新指定表
- tableList = version.getTables().split("\\|");
- }
- Set<Class<?>> messageCommandClasses = ClassScanner.listClassesWithAnnotation(data_parackage, Table.class);
- for (Class<?> cls : messageCommandClasses) {
- String tableName = cls.getAnnotation(Table.class).name();
- if (tableList != null) {
- if (!isHotFixContainTableName(tableList, tableName)) {
- continue;
- }
- //TODO 应该说有数据都加载后统一替换 但是现在部分静态数据遗留在cfg类中 只能一个一个加载
- if(!tableName.equals("Map"))
- loadInCache(cls);
- LOGGER.info("hotfix table"+tableName);
- }
- Object stable = cls.newInstance();
- Method method = cls.getMethod("init");
- method.invoke(stable);
- }
- try {
- //加载逻辑数据
- Set<String> staticConfigsNames = new HashSet<>();
- Set<String> tables = null;
- if (tableList != null) {
- tables = new HashSet<>(Arrays.asList(tableList));
- }
- for (Map.Entry<String, AbstractClassStaticConfig> entry : classStaticConfigMap.entrySet()) {
- if (tables != null && entry.getValue().checkChange(tables).size() <= 0) {
- continue;
- }
- staticConfigsNames.add(entry.getKey());
- }
- List<Class<?>> staticConfigsclass = new LinkedList<>();
- try {
- ClassLoaderHelper.findLocalClass("com.ljsd.jieling.config.clazzStaticCfg", AbstractClassStaticConfig.class,Thread.currentThread().getContextClassLoader(), staticConfigsclass);
- }catch (RuntimeException e){
- }
- try {
- ClassLoaderHelper.findClassJar("com.ljsd.jieling.config.clazzStaticCfg", AbstractClassStaticConfig.class, Thread.currentThread().getContextClassLoader(), staticConfigsclass);
- }catch (RuntimeException e){
- }
- for (Class<?> cls : staticConfigsclass) {
- if (tables != null) {
- if(!staticConfigsNames.contains(cls.getName())){
- continue;
- }
- }
- AbstractClassStaticConfig newClassConfig = (AbstractClassStaticConfig) cls.newInstance();
- classStaticConfigMap.put(cls.getName(), newClassConfig);
- }
- } catch (InstantiationException | IllegalAccessException e2) {
- LOGGER.error("e={}",e2);
- }
- }
- private static void registFigureConfig(AbstractClassStaticConfig classStaticConfig) {
- if (classStaticConfig == null) {
- return;
- }
- classStaticConfigMap.put(classStaticConfig.getClass().getName(), classStaticConfig);
- }
- /**
- * 获取类的二次处理配置类
- */
- public static <T extends AbstractClassStaticConfig> T getFigureConfig(Class<T> tClass) {
- if (!classStaticConfigMap.containsKey(tClass.getName())) {
- if (ClassLoaderHelper.filter(tClass, AbstractClassStaticConfig.class)) {
- try {
- registFigureConfig((AbstractClassStaticConfig) tClass.newInstance());
- } catch (Exception e) {
- }
- }
- }
- return (T) classStaticConfigMap.get(tClass.getName());
- }
- private static boolean isHotFixContainTableName(String[] tableNames, String curTableName) {
- if (tableNames == null) {
- return false;
- }
- if (tableNames.length == 0) {
- return false;
- }
- for (String oneTable : tableNames) {
- if (oneTable.equalsIgnoreCase(curTableName)) {
- return true;
- }
- }
- return false;
- }
- /**
- * 读取配置表到内存
- */
- @SuppressWarnings("unchecked")
- public static <T> Map<Integer, T> getConfig(Class<T> clazz) {
- Object o = tableBeanMap.get(clazz.getName());
- if (null == o) {
- o = loadInCache(clazz);
- }
- java.util.TreeMap<Integer, T> result = null;
- try {
- result = (java.util.TreeMap<Integer, T>) o;
- } catch (ClassCastException e) {
- e.printStackTrace();
- }
- if (null == result) {
- throw new NullPointerException("clazz.null" + clazz.getName());
- }
- return result;
- }
- private static <T> Object loadInCache(Class<T> clazz){
- TreeMap<Integer, T> map = new TreeMap<>();
- try {
- String tableName = clazz.getAnnotation(Table.class).name();
- // String path = SysUtil.getPath("conf", "server", tableName + ".txt");
- String path = "conf/server/"+tableName+".txt";
- File file = new File(path);
- if (!file.exists()) {
- LOGGER.error("file not find {}, do not find sheet with {} you need rebuild all sheet by gen sheet tool!", path, tableName);
- throw new NullPointerException("clazz.null" + clazz.getName());
- }
- LOGGER.info("initMap:{}", clazz.getSimpleName());
- readFileToCache(clazz, map, file);
- } catch (Exception e) {
- e.printStackTrace();
- }
- tableBeanMap.put(clazz.getName(), map);
- return map;
- }
- private static <T> void readFileToCache(Class<T> clazz, Map<Integer, T> map, File file) throws IOException, InstantiationException, IllegalAccessException, NoSuchFieldException {
- String line;
- List<String> key = new ArrayList<>();
- List<String> type = new ArrayList<>();
- int lineNum = 0;
- try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
- while ((line = bufferedReader.readLine()) != null) {
- if (line.isEmpty()) {
- continue;
- }
- T obj = clazz.newInstance();
- String[] prarms = line.split("\\t");
- switch (lineNum) {
- case 0:
- prarms = StringUtil.fieldHandle(prarms);
- key.addAll(Arrays.asList(prarms));
- break;
- case 1:
- type.addAll(Arrays.asList(prarms));
- break;
- default:
- try {
- dealParams(clazz, map, key, type, obj, prarms);
- }catch (Exception e){
- LOGGER.error("clazz = {}, line = {}, para = {}, excep = {}",clazz, line.substring(0,10), Arrays.toString(prarms), e);
- throw e;
- }
- break;
- }
- lineNum++;
- }
- }
- }
- /**
- * 读取配置表到内存
- */
- public static <T> Map<Integer, Map<Integer, T>> getMapConfig(Class<T> clazz) {
- Map<Integer, Map<Integer, T>> map = new HashMap<>();
- try {
- String tableName = clazz.getAnnotation(Table.class).name();
- String pathDir = "conf/server/";
- File mapDir = new File(pathDir);
- String prefix = tableName + "_";
- int preLength = prefix.length();
- for (File mapFile : mapDir.listFiles()) {
- tableName = mapFile.getName();
- if (!mapFile.getName().startsWith(prefix)) {
- continue;
- }
- int mapId = Integer.parseInt(tableName.substring(preLength).split("\\.")[0]);
- LOGGER.info("initMap:{}", tableName);
- Map<Integer, T> mapConf = new HashMap<>();
- readFileToCache(clazz, mapConf, mapFile);
- map.put(mapId, mapConf);
- }
- } catch (Exception e) {
- e.printStackTrace();
- LOGGER.error("getMapConfig= {}", e.toString());
- }
- return map;
- }
- /**
- * 处理参数
- */
- private static <T> void dealParams(Class<T> clazz, Map<Integer, T> map, List<String> key, List<String> type, T obj, String[] prarms) throws NoSuchFieldException, IllegalAccessException {
- int id = Integer.parseInt(prarms[0]);
- for (int i = 0; i < prarms.length; i++) {
- try {
- Field field = clazz.getDeclaredField(key.get(i));
- boolean flag = field.isAccessible();
- field.setAccessible(true);
- switch (type.get(i)) {
- case "int":
- field.set(obj, Integer.parseInt(prarms[i]));
- break;
- case "string":
- case "stringt":
- if (!"null".equalsIgnoreCase(prarms[i]) || !"".equalsIgnoreCase(prarms[i])) {
- field.set(obj, prarms[i]);
- }
- break;
- case "long":
- field.set(obj, Long.parseLong(prarms[i]));
- break;
- case "double":
- field.set(obj, Double.parseDouble(prarms[i]));
- break;
- case "float":
- field.set(obj, Float.parseFloat(prarms[i]));
- break;
- case "bool":
- field.set(obj, Boolean.parseBoolean(prarms[i]));
- break;
- default:
- if (type.get(i).startsWith("ref")) {
- field.set(obj, Integer.parseInt(prarms[i]));
- } else if (type.get(i).startsWith("mut")) {
- mut(key, type, obj, prarms, i, field);
- }
- break;
- }
- field.setAccessible(flag);
- map.put(id, obj);
- } catch (NoSuchFieldException e) {
- e.printStackTrace();
- LOGGER.error("Key={} Clazz={} Exception={}", key.get(i), clazz, e.toString());
- }
- }
- }
- /**
- * 操作mut开头的类型
- */
- private static <T> void mut(List<String> key, List<String> type, T obj, String[] prarms, int i, Field field) throws IllegalAccessException {
- String[] params = type.get(i).split(",");
- String[] type1 = params[1].split("#");
- int dimension = dimension(type1, params);
- if (dimension == 0) {
- field.set(obj, prarms[i]);
- } else {
- //全为int或者float
- switch (type1[0]) {
- case "int":
- intField(obj, prarms, i, field, dimension);
- break;
- case "float":
- floatField(obj, prarms, i, field, dimension);
- break;
- default:
- break;
- }
- }
- }
- private static <T> void floatField(T obj, String[] prarms, int i, Field field, int dimension) throws IllegalAccessException {
- switch (dimension) {
- case 1:
- field.set(obj, StringUtil.parseFiledFloat(prarms[i]));
- break;
- case 2:
- field.set(obj, StringUtil.parseFiledFloat2(prarms[i]));
- break;
- case 3:
- field.set(obj, StringUtil.parseFiledFloat3(prarms[i]));
- break;
- default:
- break;
- }
- }
- private static <T> void intField(T obj, String[] prarms, int i, Field field, int dimension) throws IllegalAccessException {
- switch (dimension) {
- case 1:
- field.set(obj, StringUtil.parseFiledInt(prarms[i]));
- break;
- case 2:
- field.set(obj, StringUtil.parseFiledInt2(prarms[i]));
- break;
- case 3:
- field.set(obj, StringUtil.parseFiledInt3(prarms[i]));
- break;
- default:
- break;
- }
- }
- /**
- * 判断是几维数组
- */
- private static int dimension(String type[], String[] params) throws IllegalAccessException {
- String type1 = type[0];
- boolean flag = false;
- for (int i = 0; i < type.length; i++) {
- if (!type1.equals(type[i])) {
- flag = true;
- }
- }
- if (flag) {
- return 0;
- }
- return Integer.parseInt(params[2]);
- }
- private static String getType(String param) {
- String[] params = param.split(",");
- String[] type = params[1].split("#");
- return type[0];
- }
- public static <T> T getJsonFilePathInJsonConf(String fileName, Class<T> fileClass) {
- File file = new File(jsonPath + fileName);
- if (!file.exists()) {
- LOGGER.info("the {} is not exist", fileName);
- return null;
- }
- try (InputStream in = new FileInputStream(file);) {
- ObjectMapper mapper = new ObjectMapper();
- mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
- return mapper.readValue(in, fileClass);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static void initJsonPath() {
- String osName = System.getProperty("os.name");
- jsonPath = "../conf/";
- if (osName.matches("^(?i)Windows.*$")) {// Window 系统
- jsonPath = "conf/";
- }
- }
- private static void initDbVersion() {
- CDataBaseVersion cDataBaseVersion = getJsonFilePathInJsonConf("c_database_version.json", CDataBaseVersion.class);
- if (null == cDataBaseVersion) {
- currentDbVersion = 0;
- } else {
- currentDbVersion = cDataBaseVersion.getVersion();
- }
- }
- }
|