class=\ 5.2.2. 数据访问请求路由(Routing In CobarSqlMapClientTemplate) 除了依赖某个ICobarDataSourceService进行多数据源的管理, CobarSqlMapClientTemplate的另一个主要依赖就是ICobarRouter, ICobarRouter负责将相应的数据访问请求路由到指定的数据源上去. 5.2.2.1. Router Design ICobarRouter抽象接口定义如下: public interface ICobarRouter 我们可以根据情况提供不同的ICobarRouter实现类, 比如Cobar Client默认提供的com.alibaba.cobar.client.router.CobarClientInternalRouter和 om.alibaba.cobar.client.router.DefaultCobarClientInternalRouter, 或者如果路由规则数量很多, 为了保证性能, 也可以实现基于Rete等算法的实现类等. 没有特殊需求的情况下,我们默认采用CobarClientInternalRouter作为CobarSqlMapClientTemplate使用的默认Router实现. 但用户也可以根据情况选用DefaultCobarClientInternalRouter, 二者的使用是类似的。 DefaultCobarClientInternalRouter在CobarClientInternalRouter的基础上, 对路由规则的匹配进行了分组优化, 通过配置时期的复杂度换取运行时期的简单高效。 如果规则很多的话,可以考虑使用DefaultCobarClientInternalRouter。 Note DefaultCobarClientInternalRouter的配置可以通过两个专门的FactoryBean进行, 即 com.alibaba.cobar.client.router.config.DefaultCobarClientInternalRouterXmlFactoryBean 和 com.alibaba.cobar.client.router.config.StaticCobarClientInternalRouterFactoryBean, 前者允许用户通过外部XML的配置文件形式来定义和加载路由规则, 后者运行用户直接在Spring的IoC容器中以bean定义的形式定义路由规则。 应用方可以根据情况选用。详细使用情况可以参考相应类的javadoc以及下面有关CobarClientInternalRouter的使用和配置信息。 因为CobarSqlMapClientTemplate主要面向iBatis, 所以, 它使用的CobarClientInternalRouter接受的路由上下文信息(routingFact)类型为IBatisRoutingFact: public class IBatisRoutingFact { // SQL identity private String action; // the argument of SQL action private Object argument; // ... } 也就是说, CobarClientInternalRouter将根据两部分信息进行路由, 一就是sqlmap中的sqlmap id, 另一个就是传入的数据访问方法参数. CobarClientInternalRouter将根据一组或则多组路由规则对传入的IBatisRoutingFact类型的路由上下文信息进行匹配, 将匹配的结果返回, 之后, CobarClientInternalRouter就可以根据匹配的结果来决定最终的数据访问操作将在哪些数据源上执行了. 5.2.2.1.1. CobarClientInternalRouter的配置(Configuration of CobarClientInternalRouter) 默认情况下, CobarClientInternalRouter将接收4组不同类型的路由规则, 但路由规则的类型对于用户来说实际上是不必要的, 所以, 为了避免用户过多的纠缠于 CobarClientInternalRouter的实现细节, 我们给出了针对CobarClientInternalRouter配置的一个Spring的FactoryBean实现, 以帮助简化CobarClientInternalRouter的配置, 该FactoryBean实现类为com.alibaba.cobar.client.router.config.CobarInteralRouterXmlFactoryBean, 其一般的配置方式如下: CobarClientInternalRouter实例之上. 而读取, 解析配置信息, 并构建不同类型路由规则等 “琐事 ” 将完全对用户透明.不过, 再怎么屏蔽, 有得事情还是需要用户提供的, 比如配置文件的内容, 用户必须按照应用程序的部署情况提供正确地路由规则定义, CobarClientInternalRouter才会正确的工作.所以, 下面我们将详细介绍路由规则的相关信息. Tip 除了可以通过configLocation属性指定单一的配置文件路径, 也可以通过configLocations指定多个配置文件路径,这通常有助于模块化并行开发. Note 虽然默认情况下我们推荐使用CobarInteralRouterXmlFactoryBean进行 CobarClientInternalRouter的配置, 但我们同样可以给出基于DSL甚至Excel等形式路由规则 定义对应的FactoryBean.只要应用需要, 这些都是可以在现有的基础上进行扩展的. 5.2.2.2. 路由规则详解(Rules In Details) 5.2.2.2.1. 路由规则定义格式(Rule Definitions) 一个最简单的路由规则定义文件内容可以如下所示: namespace 或者 sqlmap. 属于路由规则条件的一部分, 二者的唯一区别在于指定的条件明确程度不同, sqlmap直接对应每一个iBatis的SqlMap文件中某个statement的定义的id,而namespace则对应每一个iBatis的SqlMap文件中定义的namespace. 这两个元素在 shardingExpression. 遵循MVEL形式的表达式定义, 同样属于路由规则条件的一部分, 主要对数据访问请求的参数进行匹配, 属于动态条件, 通常用于横向切分规则的定义. shards. 路由规则结果部分, 如果以上多个路由规则条件匹配成功, 则返回该元素的值作为路由结果. 以上rule定义简单来说表达了condition->action的语义, 即具体化为(namespace | sqlamp) + shardingExpression -> shards. 以上规则定义其实很简单,所以并不强制使用DTD或者XML Schema等来验证文档的合法性, 如果需要, 可以参考如下的DTD定义: 那么, 以上元素到底应该如何根据应用程序的情况进行定义那? 让我们接着来看下一节的 “路由规则类型详解 ” 吧! Note CobarClient使用MVEL对shardingExpression进行求值, 所以, 起草的shardingExpression只要符合MVEL的语法就可以。有关MVEL的语法, 可以参考MVEL的 官方文档 。 5.2.2.2.2. 路由规则类型详解(Rule Types Explained) 路由规则的定义初看起来简单, 但到底应该如何定义, 以及为什么要如此定义, 在没有为你揭开这些疑问之前,我想, 你还是很难搞清楚这些路由规则定义到底是怎么回事, 不过没关系, 我们现在就为你揭开这些疑团. 在使用iBatis进行数据访问的时候,我们通常会定义相关的SqlMap文件, 例如: 我们本着从特殊到一般的情况进行推演. 以create操作为例, 假设我们的offer数据现在分布在两台数据库上, 而根据切分规则, memberId为奇数的数据分布在数据库1上, memberId为偶数的数据分布在数据库2上, 在这一前提下, 要路由offer的创建相关的数据请求, 最明了的方式就是, 检查当前数据访问对应的sql statement是哪个, 并判断传入的参数包含的memberId是奇数还是偶数, 这样, 我们就有了以下2个路由规则定义: 有了以上的基础, 我们来变换假设场景, 我们依然是create操作, 但现在我们不是做的水平切分, 而只是做垂直切分, 也就是说, 所有的offer数据现在假设都会落在同一台数据库上, 那么, 以上的定义可以变更为: