[置顶] MyCat
数据库路由中间件MyCat - 源代码篇(12) 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat中虚拟化的数据库的配置): XMLSchemaLoader.java private void loadSchemas(Element root) { NodeList list = root . getElemen
数据库路由中间件MyCat - 源代码篇(12)
4.配置模块
4.2 schema.xml
接上一篇,接下来载入每个schema的配置(也就是每个MyCat中虚拟化的数据库的配置):
XMLSchemaLoader.java
<code class=" hljs lasso"><span class="hljs-keyword">private</span> <span class="hljs-literal">void</span> loadSchemas(Element root) { NodeList <span class="hljs-built_in">list</span> <span class="hljs-subst">=</span> root<span class="hljs-built_in">.</span>getElementsByTagName(<span class="hljs-string">"schema"</span>); for (int i <span class="hljs-subst">=</span> <span class="hljs-number">0</span>, n <span class="hljs-subst">=</span> <span class="hljs-built_in">list</span><span class="hljs-built_in">.</span>getLength(); i <span class="hljs-subst"><</span> n; i<span class="hljs-subst">++</span>) { Element schemaElement <span class="hljs-subst">=</span> (Element) <span class="hljs-built_in">list</span><span class="hljs-built_in">.</span>item(i); <span class="hljs-comment">//读取各个属性</span> <span class="hljs-built_in">String</span> name <span class="hljs-subst">=</span> schemaElement<span class="hljs-built_in">.</span>getAttribute(<span class="hljs-string">"name"</span>); <span class="hljs-built_in">String</span> dataNode <span class="hljs-subst">=</span> schemaElement<span class="hljs-built_in">.</span>getAttribute(<span class="hljs-string">"dataNode"</span>); <span class="hljs-built_in">String</span> checkSQLSchemaStr <span class="hljs-subst">=</span> schemaElement<span class="hljs-built_in">.</span>getAttribute(<span class="hljs-string">"checkSQLschema"</span>); <span class="hljs-built_in">String</span> sqlMaxLimitStr <span class="hljs-subst">=</span> schemaElement<span class="hljs-built_in">.</span>getAttribute(<span class="hljs-string">"sqlMaxLimit"</span>); int sqlMaxLimit <span class="hljs-subst">=</span> <span class="hljs-subst">-</span><span class="hljs-number">1</span>; <span class="hljs-comment">//读取sql返回结果集限制</span> <span class="hljs-keyword">if</span> (sqlMaxLimitStr <span class="hljs-subst">!=</span> <span class="hljs-built_in">null</span> <span class="hljs-subst">&&</span> <span class="hljs-subst">!</span>sqlMaxLimitStr<span class="hljs-built_in">.</span>isEmpty()) { sqlMaxLimit <span class="hljs-subst">=</span> <span class="hljs-built_in">Integer</span><span class="hljs-built_in">.</span>valueOf(sqlMaxLimitStr); } <span class="hljs-comment">// check dataNode already exists or not,看schema标签中是否有datanode</span> <span class="hljs-built_in">String</span> defaultDbType <span class="hljs-subst">=</span> <span class="hljs-built_in">null</span>; <span class="hljs-comment">//校验检查并添加dataNode</span> <span class="hljs-keyword">if</span> (dataNode <span class="hljs-subst">!=</span> <span class="hljs-built_in">null</span> <span class="hljs-subst">&&</span> <span class="hljs-subst">!</span>dataNode<span class="hljs-built_in">.</span>isEmpty()) { <span class="hljs-built_in">List</span><span class="hljs-subst"><</span><span class="hljs-built_in">String</span><span class="hljs-subst">></span> dataNodeLst <span class="hljs-subst">=</span> <span class="hljs-literal">new</span> ArrayList<span class="hljs-subst"><</span><span class="hljs-built_in">String</span><span class="hljs-subst">></span>(<span class="hljs-number">1</span>); dataNodeLst<span class="hljs-built_in">.</span>add(dataNode); checkDataNodeExists(dataNodeLst); <span class="hljs-built_in">String</span> dataHost <span class="hljs-subst">=</span> dataNodes<span class="hljs-built_in">.</span>get(dataNode)<span class="hljs-built_in">.</span>getDataHost(); defaultDbType <span class="hljs-subst">=</span> dataHosts<span class="hljs-built_in">.</span>get(dataHost)<span class="hljs-built_in">.</span>getDbType(); } <span class="hljs-keyword">else</span> { dataNode <span class="hljs-subst">=</span> <span class="hljs-built_in">null</span>; } <span class="hljs-comment">//加载schema下所有tables</span> <span class="hljs-built_in">Map</span><span class="hljs-subst"><</span><span class="hljs-built_in">String</span>, TableConfig<span class="hljs-subst">></span> tables <span class="hljs-subst">=</span> loadTables(schemaElement); <span class="hljs-comment">//判断schema是否重复</span> <span class="hljs-keyword">if</span> (schemas<span class="hljs-built_in">.</span>containsKey(name)) { throw <span class="hljs-literal">new</span> ConfigException(<span class="hljs-string">"schema "</span> <span class="hljs-subst">+</span> name <span class="hljs-subst">+</span> <span class="hljs-string">" duplicated!"</span>); } <span class="hljs-comment">// 设置了table的不需要设置dataNode属性,没有设置table的必须设置dataNode属性</span> <span class="hljs-keyword">if</span> (dataNode <span class="hljs-subst">==</span> <span class="hljs-built_in">null</span> <span class="hljs-subst">&&</span> tables<span class="hljs-built_in">.</span>size() <span class="hljs-subst">==</span> <span class="hljs-number">0</span>) { throw <span class="hljs-literal">new</span> ConfigException( <span class="hljs-string">"schema "</span> <span class="hljs-subst">+</span> name <span class="hljs-subst">+</span> <span class="hljs-string">" didn't config tables,so you must set dataNode property!"</span>); } SchemaConfig schemaConfig <span class="hljs-subst">=</span> <span class="hljs-literal">new</span> SchemaConfig(name, dataNode, tables, sqlMaxLimit, <span class="hljs-string">"true"</span><span class="hljs-built_in">.</span>equalsIgnoreCase(checkSQLSchemaStr)); <span class="hljs-comment">//设定DB类型,这对之后的sql语句路由解析有帮助</span> <span class="hljs-keyword">if</span> (defaultDbType <span class="hljs-subst">!=</span> <span class="hljs-built_in">null</span>) { schemaConfig<span class="hljs-built_in">.</span>setDefaultDataNodeDbType(defaultDbType); <span class="hljs-keyword">if</span> (<span class="hljs-subst">!</span><span class="hljs-string">"mysql"</span><span class="hljs-built_in">.</span>equalsIgnoreCase(defaultDbType)) { schemaConfig<span class="hljs-built_in">.</span>setNeedSupportMultiDBType(<span class="hljs-literal">true</span>); } } <span class="hljs-comment">// 判断是否有不是mysql的数据库类型,方便解析判断是否启用多数据库分页语法解析</span> for (<span class="hljs-built_in">String</span> tableName : tables<span class="hljs-built_in">.</span>keySet()) { TableConfig tableConfig <span class="hljs-subst">=</span> tables<span class="hljs-built_in">.</span>get(tableName); <span class="hljs-keyword">if</span> (isHasMultiDbType(tableConfig)) { schemaConfig<span class="hljs-built_in">.</span>setNeedSupportMultiDBType(<span class="hljs-literal">true</span>); break; } } <span class="hljs-comment">//记录每种dataNode的DB类型</span> <span class="hljs-built_in">Map</span><span class="hljs-subst"><</span><span class="hljs-built_in">String</span>, <span class="hljs-built_in">String</span><span class="hljs-subst">></span> dataNodeDbTypeMap <span class="hljs-subst">=</span> <span class="hljs-literal">new</span> HashMap<span class="hljs-subst"><></span>(); for (<span class="hljs-built_in">String</span> dataNodeName : dataNodes<span class="hljs-built_in">.</span>keySet()) { DataNodeConfig dataNodeConfig <span class="hljs-subst">=</span> dataNodes<span class="hljs-built_in">.</span>get(dataNodeName); <span class="hljs-built_in">String</span> dataHost <span class="hljs-subst">=</span> dataNodeConfig<span class="hljs-built_in">.</span>getDataHost(); DataHostConfig dataHostConfig <span class="hljs-subst">=</span> dataHosts<span class="hljs-built_in">.</span>get(dataHost); <span class="hljs-keyword">if</span> (dataHostConfig <span class="hljs-subst">!=</span> <span class="hljs-built_in">null</span>) { <span class="hljs-built_in">String</span> dbType <span class="hljs-subst">=</span> dataHostConfig<span class="hljs-built_in">.</span>getDbType(); dataNodeDbTypeMap<span class="hljs-built_in">.</span>put(dataNodeName, dbType); } } schemaConfig<span class="hljs-built_in">.</span>setDataNodeDbTypeMap(dataNodeDbTypeMap); schemas<span class="hljs-built_in">.</span>put(name, schemaConfig); } }</code>
首先读取schema每个配置属性项,并作有效性判断。比如默认的dataNode是否存在。只要验证之前读取的dataNode里面有没有就可以
<code class=" hljs cs"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">checkDataNodeExists</span>(Collection<String> nodes) { <span class="hljs-keyword">if</span> (nodes == <span class="hljs-keyword">null</span> || nodes.size() < <span class="hljs-number">1</span>) { <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">for</span> (String node : nodes) { <span class="hljs-keyword">if</span> (!dataNodes.containsKey(node)) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"dataNode '"</span> + node + <span class="hljs-string">"' is not found!"</span>); } } }</code>
之后载入所有的table和childTable:
<code class=" hljs javascript">private Map<<span class="hljs-built_in">String</span>, TableConfig> loadTables(Element node) { <span class="hljs-comment">// Map<String, TableConfig> tables = new HashMap<String, TableConfig>();</span> <span class="hljs-comment">// 支持表名中包含引号[`] BEN GONG</span> Map<<span class="hljs-built_in">String</span>, TableConfig> tables = <span class="hljs-keyword">new</span> TableConfigMap(); NodeList nodeList = node.getElementsByTagName(<span class="hljs-string">"table"</span>); <span class="hljs-keyword">for</span> (int i = <span class="hljs-number">0</span>; i < nodeList.getLength(); i++) { Element tableElement = (Element) nodeList.item(i); <span class="hljs-built_in">String</span> tableNameElement = tableElement.getAttribute(<span class="hljs-string">"name"</span>).toUpperCase(); <span class="hljs-comment">//TODO:路由, 增加对动态日期表的支持</span> <span class="hljs-built_in">String</span> tableNameSuffixElement = tableElement.getAttribute(<span class="hljs-string">"nameSuffix"</span>).toUpperCase(); <span class="hljs-keyword">if</span> ( !<span class="hljs-string">""</span>.equals( tableNameSuffixElement ) ) { <span class="hljs-keyword">if</span>( tableNameElement.split(<span class="hljs-string">","</span>).length > <span class="hljs-number">1</span> ) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"nameSuffix "</span> + tableNameSuffixElement + <span class="hljs-string">", require name parameter cannot multiple breaks!"</span>); } <span class="hljs-comment">//前缀用来标明日期格式</span> tableNameElement = doTableNameSuffix(tableNameElement, tableNameSuffixElement); } <span class="hljs-comment">//记录主键,用于之后路由分析,以及启用自增长主键</span> <span class="hljs-built_in">String</span>[] tableNames = tableNameElement.split(<span class="hljs-string">","</span>); <span class="hljs-built_in">String</span> primaryKey = tableElement.hasAttribute(<span class="hljs-string">"primaryKey"</span>) ? tableElement.getAttribute(<span class="hljs-string">"primaryKey"</span>).toUpperCase() : <span class="hljs-literal">null</span>; <span class="hljs-comment">//记录是否主键自增,默认不是,(启用全局sequence handler)</span> boolean autoIncrement = <span class="hljs-literal">false</span>; <span class="hljs-keyword">if</span> (tableElement.hasAttribute(<span class="hljs-string">"autoIncrement"</span>)) { autoIncrement = <span class="hljs-built_in">Boolean</span>.parseBoolean(tableElement.getAttribute(<span class="hljs-string">"autoIncrement"</span>)); } <span class="hljs-comment">//记录是否需要加返回结果集限制,默认需要加</span> boolean needAddLimit = <span class="hljs-literal">true</span>; <span class="hljs-keyword">if</span> (tableElement.hasAttribute(<span class="hljs-string">"needAddLimit"</span>)) { needAddLimit = <span class="hljs-built_in">Boolean</span>.parseBoolean(tableElement.getAttribute(<span class="hljs-string">"needAddLimit"</span>)); } <span class="hljs-comment">//记录type,是否为global</span> <span class="hljs-built_in">String</span> tableTypeStr = tableElement.hasAttribute(<span class="hljs-string">"type"</span>) ? tableElement.getAttribute(<span class="hljs-string">"type"</span>) : <span class="hljs-literal">null</span>; int tableType = TableConfig.TYPE_GLOBAL_DEFAULT; <span class="hljs-keyword">if</span> (<span class="hljs-string">"global"</span>.equalsIgnoreCase(tableTypeStr)) { tableType = TableConfig.TYPE_GLOBAL_TABLE; } <span class="hljs-comment">//记录dataNode,就是分布在哪些dataNode上</span> <span class="hljs-built_in">String</span> dataNode = tableElement.getAttribute(<span class="hljs-string">"dataNode"</span>); TableRuleConfig tableRule = <span class="hljs-literal">null</span>; <span class="hljs-keyword">if</span> (tableElement.hasAttribute(<span class="hljs-string">"rule"</span>)) { <span class="hljs-built_in">String</span> ruleName = tableElement.getAttribute(<span class="hljs-string">"rule"</span>); tableRule = tableRules.get(ruleName); <span class="hljs-keyword">if</span> (tableRule == <span class="hljs-literal">null</span>) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"rule "</span> + ruleName + <span class="hljs-string">" is not found!"</span>); } } boolean ruleRequired = <span class="hljs-literal">false</span>; <span class="hljs-comment">//记录是否绑定有分片规则</span> <span class="hljs-keyword">if</span> (tableElement.hasAttribute(<span class="hljs-string">"ruleRequired"</span>)) { ruleRequired = <span class="hljs-built_in">Boolean</span>.parseBoolean(tableElement.getAttribute(<span class="hljs-string">"ruleRequired"</span>)); } <span class="hljs-keyword">if</span> (tableNames == <span class="hljs-literal">null</span>) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"table name is not found!"</span>); } <span class="hljs-comment">//distribute函数,重新编排dataNode</span> <span class="hljs-built_in">String</span> distPrex = <span class="hljs-string">"distribute("</span>; boolean distTableDns = dataNode.startsWith(distPrex); <span class="hljs-keyword">if</span> (distTableDns) { dataNode = dataNode.substring(distPrex.length(), dataNode.length() - <span class="hljs-number">1</span>); } <span class="hljs-comment">//分表功能</span> <span class="hljs-built_in">String</span> subTables = tableElement.getAttribute(<span class="hljs-string">"subTables"</span>); <span class="hljs-keyword">for</span> (int j = <span class="hljs-number">0</span>; j < tableNames.length; j++) { <span class="hljs-built_in">String</span> tableName = tableNames[j]; TableConfig table = <span class="hljs-keyword">new</span> TableConfig(tableName, primaryKey, autoIncrement, needAddLimit, tableType, dataNode, getDbType(dataNode), (tableRule != <span class="hljs-literal">null</span>) ? tableRule.getRule() : <span class="hljs-literal">null</span>, ruleRequired, <span class="hljs-literal">null</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>,subTables); checkDataNodeExists(table.getDataNodes()); <span class="hljs-keyword">if</span> (distTableDns) { distributeDataNodes(table.getDataNodes()); } <span class="hljs-comment">//检查去重</span> <span class="hljs-keyword">if</span> (tables.containsKey(table.getName())) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"table "</span> + tableName + <span class="hljs-string">" duplicated!"</span>); } <span class="hljs-comment">//放入map</span> tables.put(table.getName(), table); } <span class="hljs-comment">//只有tableName配置的是单个表(没有逗号)的时候才能有子表</span> <span class="hljs-keyword">if</span> (tableNames.length == <span class="hljs-number">1</span>) { TableConfig table = tables.get(tableNames[<span class="hljs-number">0</span>]); <span class="hljs-comment">// process child tables</span> processChildTables(tables, table, dataNode, tableElement); } } <span class="hljs-keyword">return</span> tables; }</code>
对于子表,有递归读取配置:
<code class=" hljs javascript">private <span class="hljs-keyword">void</span> processChildTables(Map<<span class="hljs-built_in">String</span>, TableConfig> tables, TableConfig parentTable, <span class="hljs-built_in">String</span> dataNodes, Element tableNode) { <span class="hljs-comment">// parse child tables</span> NodeList childNodeList = tableNode.getChildNodes(); <span class="hljs-keyword">for</span> (int j = <span class="hljs-number">0</span>; j < childNodeList.getLength(); j++) { Node theNode = childNodeList.item(j); <span class="hljs-keyword">if</span> (!theNode.getNodeName().equals(<span class="hljs-string">"childTable"</span>)) { <span class="hljs-keyword">continue</span>; } Element childTbElement = (Element) theNode; <span class="hljs-comment">//读取子表信息</span> <span class="hljs-built_in">String</span> cdTbName = childTbElement.getAttribute(<span class="hljs-string">"name"</span>).toUpperCase(); <span class="hljs-built_in">String</span> primaryKey = childTbElement.hasAttribute(<span class="hljs-string">"primaryKey"</span>) ? childTbElement.getAttribute(<span class="hljs-string">"primaryKey"</span>).toUpperCase() : <span class="hljs-literal">null</span>; boolean autoIncrement = <span class="hljs-literal">false</span>; <span class="hljs-keyword">if</span> (childTbElement.hasAttribute(<span class="hljs-string">"autoIncrement"</span>)) { autoIncrement = <span class="hljs-built_in">Boolean</span>.parseBoolean(childTbElement.getAttribute(<span class="hljs-string">"autoIncrement"</span>)); } boolean needAddLimit = <span class="hljs-literal">true</span>; <span class="hljs-keyword">if</span> (childTbElement.hasAttribute(<span class="hljs-string">"needAddLimit"</span>)) { needAddLimit = <span class="hljs-built_in">Boolean</span>.parseBoolean(childTbElement.getAttribute(<span class="hljs-string">"needAddLimit"</span>)); } <span class="hljs-built_in">String</span> subTables = childTbElement.getAttribute(<span class="hljs-string">"subTables"</span>); <span class="hljs-comment">//子表join键,和对应的parent的键,父子表通过这个关联</span> <span class="hljs-built_in">String</span> joinKey = childTbElement.getAttribute(<span class="hljs-string">"joinKey"</span>).toUpperCase(); <span class="hljs-built_in">String</span> parentKey = childTbElement.getAttribute(<span class="hljs-string">"parentKey"</span>).toUpperCase(); TableConfig table = <span class="hljs-keyword">new</span> TableConfig(cdTbName, primaryKey, autoIncrement, needAddLimit, TableConfig.TYPE_GLOBAL_DEFAULT, dataNodes, getDbType(dataNodes), <span class="hljs-literal">null</span>, <span class="hljs-literal">false</span>, parentTable, <span class="hljs-literal">true</span>, joinKey, parentKey, subTables); <span class="hljs-keyword">if</span> (tables.containsKey(table.getName())) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(<span class="hljs-string">"table "</span> + table.getName() + <span class="hljs-string">" duplicated!"</span>); } tables.put(table.getName(), table); <span class="hljs-comment">//对于子表的子表,递归处理</span> processChildTables(tables, table, dataNodes, childTbElement); } }</code>
对于表的dataNode对应关系,有个特殊配置即类似dataNode=”distributed(dn$1-10)”,这个含义是:
<code class="java hljs "><span class="hljs-javadoc">/** * distribute datanodes in multi hosts,means ,dn1 (host1),dn100 * (host2),dn300(host3),dn2(host1),dn101(host2),dn301(host3)...etc * 将每个host上的datanode按照host重新排列。比如上面的例子host1拥有dn1,dn2,host2拥有dn100,dn101,host3拥有dn300,dn301, * 按照host重新排列: 0->dn1 (host1),1->dn100(host2),2->dn300(host3),3->dn2(host1),4->dn101(host2),5->dn301(host3) * *<span class="hljs-javadoctag"> @param</span> theDataNodes */</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">distributeDataNodes</span>(ArrayList<String> theDataNodes) { Map<String, ArrayList<String>> newDataNodeMap = <span class="hljs-keyword">new</span> HashMap<String, ArrayList<String>>(dataHosts.size()); <span class="hljs-keyword">for</span> (String dn : theDataNodes) { DataNodeConfig dnConf = dataNodes.get(dn); String host = dnConf.getDataHost(); ArrayList<String> hostDns = newDataNodeMap.get(host); hostDns = (hostDns == <span class="hljs-keyword">null</span>) ? <span class="hljs-keyword">new</span> ArrayList<String>() : hostDns; hostDns.add(dn); newDataNodeMap.put(host, hostDns); } ArrayList<String> result = <span class="hljs-keyword">new</span> ArrayList<String>(theDataNodes.size()); <span class="hljs-keyword">boolean</span> hasData = <span class="hljs-keyword">true</span>; <span class="hljs-keyword">while</span> (hasData) { hasData = <span class="hljs-keyword">false</span>; <span class="hljs-keyword">for</span> (ArrayList<String> dns : newDataNodeMap.values()) { <span class="hljs-keyword">if</span> (!dns.isEmpty()) { result.add(dns.remove(<span class="hljs-number">0</span>)); hasData = <span class="hljs-keyword">true</span>; } } } theDataNodes.clear(); theDataNodes.addAll(result); }</code>
读取完所有表之后,记录好DB类型,这对之后的sql语句路由解析有帮助。将所有schema的配置保存在:
<code class=" hljs java"><span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Map<String, SchemaConfig> schemas;</code>
4.3 server.xml
之后会读取载入server配置。
XMLConfigLoader.java:
<code class=" hljs avrasm">public XMLConfigLoader(SchemaLoader schemaLoader) { XMLServerLoader serverLoader = new XMLServerLoader()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.system</span> = serverLoader<span class="hljs-preprocessor">.getSystem</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.users</span> = serverLoader<span class="hljs-preprocessor">.getUsers</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.quarantine</span> = serverLoader<span class="hljs-preprocessor">.getQuarantine</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.cluster</span> = serverLoader<span class="hljs-preprocessor">.getCluster</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.dataHosts</span> = schemaLoader<span class="hljs-preprocessor">.getDataHosts</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.dataNodes</span> = schemaLoader<span class="hljs-preprocessor">.getDataNodes</span>()<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.schemas</span> = schemaLoader<span class="hljs-preprocessor">.getSchemas</span>()<span class="hljs-comment">;</span> schemaLoader = null<span class="hljs-comment">;</span> }</code>
XMLServerLoader.java
<code class=" hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-title">XMLServerLoader</span>() { <span class="hljs-keyword">this</span>.system = <span class="hljs-keyword">new</span> SystemConfig(); <span class="hljs-keyword">this</span>.users = <span class="hljs-keyword">new</span> HashMap<String, UserConfig>(); <span class="hljs-keyword">this</span>.quarantine = <span class="hljs-keyword">new</span> QuarantineConfig(); <span class="hljs-keyword">this</span>.load(); } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">load</span>() { <span class="hljs-comment">//读取server.xml配置</span> InputStream dtd = <span class="hljs-keyword">null</span>; InputStream xml = <span class="hljs-keyword">null</span>; <span class="hljs-keyword">try</span> { dtd = XMLServerLoader.class.getResourceAsStream(<span class="hljs-string">"/server.dtd"</span>); xml = XMLServerLoader.class.getResourceAsStream(<span class="hljs-string">"/server.xml"</span>); Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement(); <span class="hljs-comment">//加载System标签</span> loadSystem(root); <span class="hljs-comment">//加载User标签</span> loadUsers(root); <span class="hljs-comment">//加载集群配置</span> <span class="hljs-keyword">this</span>.cluster = <span class="hljs-keyword">new</span> ClusterConfig(root, system.getServerPort()); <span class="hljs-comment">//加载权限和黑白名单</span> loadQuarantine(root); } <span class="hljs-keyword">catch</span> (ConfigException e) { <span class="hljs-keyword">throw</span> e; } <span class="hljs-keyword">catch</span> (Exception e) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ConfigException(e); } <span class="hljs-keyword">finally</span> { <span class="hljs-keyword">if</span> (dtd != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">try</span> { dtd.close(); } <span class="hljs-keyword">catch</span> (IOException e) { } } <span class="hljs-keyword">if</span> (xml != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">try</span> { xml.close(); } <span class="hljs-keyword">catch</span> (IOException e) { } } } }</code>
首先加载System标签

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Go语言是一种高效、简洁且易于学习的编程语言,因其在并发编程和网络编程方面的优势而备受开发者青睐。在实际开发中,数据库操作是不可或缺的一部分,本文将介绍如何使用Go语言实现数据库的增删改查操作。在Go语言中,我们通常使用第三方库来操作数据库,比如常用的sql包、gorm等。这里以sql包为例介绍如何实现数据库的增删改查操作。假设我们使用的是MySQL数据库。

抖音里面有用户会拍摄很多的视频作品,一旦视频作品多了以后,各种优秀的视频作品就会被掩埋了,置顶功能就很有用了,那么我们怎么置顶自己的视频作品呢?接下来小编就为大家带来了抖音置顶自己视频作品方法图文教程,还不知道怎么置顶视频的用户快来看看吧。抖音使用教程抖音怎么置顶自己视频1、首先我们打开抖音,点击主界面右下角如图所示的我。2、接着我们进入个人界面后,找到想要置顶的视频作品,点击进入播放即可。3、然后我们在视频界面,点击右下角如图所示的三个点选项。4、最后我们点击新弹出窗口中的置顶即可,返回个人界

Hibernate多态映射可映射继承类到数据库,提供以下映射类型:joined-subclass:为子类创建单独表,包含父类所有列。table-per-class:为子类创建单独表,仅包含子类特有列。union-subclass:类似joined-subclass,但父类表联合所有子类列。

苹果公司最新发布的iOS18、iPadOS18以及macOSSequoia系统为Photos应用增添了一项重要功能,旨在帮助用户轻松恢复因各种原因丢失或损坏的照片和视频。这项新功能在Photos应用的"工具"部分引入了一个名为"已恢复"的相册,当用户设备中存在未纳入其照片库的图片或视频时,该相册将自动显示。"已恢复"相册的出现为因数据库损坏、相机应用未正确保存至照片库或第三方应用管理照片库时照片和视频丢失提供了解决方案。用户只需简单几步

HTML无法直接读取数据库,但可以通过JavaScript和AJAX实现。其步骤包括建立数据库连接、发送查询、处理响应和更新页面。本文提供了利用JavaScript、AJAX和PHP来从MySQL数据库读取数据的实战示例,展示了如何在HTML页面中动态显示查询结果。该示例使用XMLHttpRequest建立数据库连接,发送查询并处理响应,从而将数据填充到页面元素中,实现了HTML读取数据库的功能。

如何在PHP中使用MySQLi建立数据库连接:包含MySQLi扩展(require_once)创建连接函数(functionconnect_to_db)调用连接函数($conn=connect_to_db())执行查询($result=$conn->query())关闭连接($conn->close())

PHP中处理数据库连接报错,可以使用以下步骤:使用mysqli_connect_errno()获取错误代码。使用mysqli_connect_error()获取错误消息。通过捕获并记录这些错误信息,可以轻松识别并解决数据库连接问题,确保应用程序的顺畅运行。

PHP是一种广泛应用于网站开发的后端编程语言,它具有强大的数据库操作功能,常用于与MySQL等数据库进行交互。然而,由于中文字符编码的复杂性,在处理数据库中文乱码时常常会出现问题。本文将介绍PHP处理数据库中文乱码的技巧与实践,包括常见的乱码原因、解决方法和具体的代码示例。常见的乱码原因数据库字符集设置不正确:数据库在创建时需选择正确的字符集,如utf8或u
