【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
这里的云计算多租户是指一个web应用,多个数据库。每一个租户对应着一个数据库。
数据库方面,简单分为一个基本库,记录着基本信息与租户的信息,还有租户数据库配置信息。N个租户库,这N个租户库,可能分布在一台服务器上,也可能分布在N台服务器上,可能两者兼有。所以在基本库中的租户的数据库所在服务器信息(下面称为数据源信息)与数据库信息。
Play的数据源配置,在conf/application.conf中,如:
jpa.dialect=org.hibernate.dialect.MySQLDialect
db.url=jdbc:mysql://basedbip:3306/pop?autoReconnect=true&useUnicode=true&characterEncoding=utf-8
db.driver=com.mysql.jdbc.Driver
db.user=root
db.pass=root
db=pop
db_01.url=jdbc:mysql://anotherdbip:3306/pop?autoReconnect=true&useUnicode=true&characterEncoding=utf-8
db_01.driver=com.mysql.jdbc.Driver
db_01.user=root
db_01.pass=root
db_01=pop01
因为Play是无状态的轻框架,所以要保持某个租户下面的单个用户一次会话中不同时间不同链接请求的库信息一样,就必须有相应的切库逻辑。同时需要有必要的切库凭证数据。
我们可以在登陆的时候,将用户的登陆信息与之对应租户的数据库信息封装成一个对象,以该登陆信息对象为value,用户本次会话的sessionid为Key,存放在缓存之中,如redis。
每次请求来临的时候,根据sessionid,从缓存中获取登陆信息对象,如果没有,则可认为该用户没有登陆,将其指向登陆页面(这里需要设定白名单,将登陆的链接排除)。 如果有对象,则将数据库信息取出,利用setCurrentConfigName切换数据源
JPA.setCurrentConfigName(dbconfigname);
利用user切换数据库
JPA.em().createNativeQuery("use "+dbname).executeUpdate();
从而达到了切库功能,在这个地方,不能使用@before注解,因为play框架会对请求参数中的对象参数数据进行JPA查询分装,而这个处理时机在处理@before之前,详细的请参考: Play 1.x框架学习之七:多数据库切换与源码修改 ( Databases Switch And Modify Source Code)
如果修改Play源码之后,就可就行自由切库。
有一个地方需要注意的是,如果用户表数据不是存放在基础库而是在租户库中,这时候就需要一个原始的切库凭据(如果没有,则无法到相应的租户库获取用户数据进行登录校验),这里提供两种解决方法,一是可以在登陆的时候让用户多填写一个与租户相关的凭证,也可以根据不同的租户,提供不同的url入口,来达到相同的结果,这样的用户体验较第一种好。
来源:oschina
链接:https://my.oschina.net/u/1386633/blog/498302