cross-store这个样例程序使用Mongodb和Mysql两种数据库交叉存储开发了一个能部署在Cloud Foundry上的应用程序。该应用程序存储两种数据,一种是Customer数据,使用Mysql存储;另一种是Survey数据,也就是对Customer的调查问卷数据,使用Mongodb存储。一个customer可与多条survey关联。
程序repository地址:https://github.com/SpringSource/cloudfoundry-samples/tree/master/cross-store
在分析程序之前,我们首先构建并在浏览器登陆程序,获得一个直观的概念。
一、构建并使用应用程序
进入源代码根目录(your_path/cross-store/)下执行命令:$ mvn clean install
待程序构建成功后即可使用VMC推送。我们可以看到程序根目录下有一个manifest.yml文件,其中附带了该程序希望Cloud Foundry为其提供的所有配置,比如分配多少内存、访问的url、和使用什么云服务等。
---
applications:
target/customer-survey-1.0.0-BUILD-SNAPSHOT/:
name: customer-survey
url: ${name}.${target-base}
framework:
name: java_web
info:
mem: 512M
description: Java Web Application
exec:
mem: 512M
instances: 1
services:
mongodb-67f01:
type: mongodb
mysql-7bfaa:
type: mysql
manifest.yml文件简化了应用推送过程,执行命令“$ vmc --path target/customer-survey-1.0.0-BUILD-SNAPSHOT/ push” 即可轻松完成部署。之后,即可按照yml文件中配置的url访问该应用程序了。由于我是push到本地的vcap,所以url是 customer-survey.vcap.me。
图1 首页
图2 customer与survey的关联
图3 数据库信息
二、Cloud Foundry运行时环境依赖注入
应用程序上下文配置
这在cross-store / src / main / java / org / cloudfoundry / config目录下进行。其中除了注入必要的数据源、持久化、以及用于Spring Data Mongodb交叉存储的依赖,还需要引入cloud foundry运行时依赖并对所使用的云服务进行配置。文件
package org.cloudfoundry.config;
import org.cloudfoundry.runtime.env.CloudEnvironment;
import org.cloudfoundry.runtime.env.MongoServiceInfo;
import org.cloudfoundry.runtime.env.RdbmsServiceInfo;
import org.cloudfoundry.runtime.service.document.MongoServiceCreator;
import org.cloudfoundry.runtime.service.relational.RdbmsServiceCreator;
//导入其他必要的依赖包
public class ServicesConfiguration {
@Bean
public CloudEnvironment cloudEnvironment() {
return new CloudEnvironment();
}
@Bean
public MongoServiceInfo mongoServiceInfo() {
MongoServiceInfo mongoServiceInfo = cloudEnvironment().getServiceInfos( MongoServiceInfo.class).iterator().next();
assert null != mongoServiceInfo : "there needs to be at least one MongoDB instance bound to this application" ;
return mongoServiceInfo;
}
@Bean
public MongoDbFactory mongoDbFactory() {
MongoServiceCreator mongoServiceCreator = new MongoServiceCreator();
return mongoServiceCreator.createService(mongoServiceInfo());
}
@Bean
public DataSource dataSource() {
RdbmsServiceInfo rdbmsServiceInfo = cloudEnvironment().getServiceInfos( RdbmsServiceInfo.class).iterator().next();
assert null != rdbmsServiceInfo : "there needs to be at least one MySQL RDBMS bound to this application";
RdbmsServiceCreator rdbmsServiceCreator = new RdbmsServiceCreator();
return rdbmsServiceCreator.createService(rdbmsServiceInfo);
}
//JPA、Spring Data Mongodb cross store,更多依赖注入
}
云环境拦截器
位于同目录下的文件进行的是Web应用程序的全局环境配置,其中注入了Cloud Foundry环境拦截器Bean,用来得到程序运行的云平台的主机地址、端口等环境变量,比如上面程序页面截图下方的地址。该依赖注入如下:
import org.springframework.data.mongodb.examples.custsvc.web.CloudFoundryEnvironmentHandlerInterceptor;
//import more necessary dependencies here...
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public CloudFoundryEnvironmentHandlerInterceptor interceptor() {
return new CloudFoundryEnvironmentHandlerInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.interceptor());
}
//more necessary Injection & @Override here...
}
CloudFoundryEnvironmentHandlerInterceptor类继承自HandlerInterceptorAdapter,对云环境变量的拦截就是由它完成的。
三、Spring model和controller
看完了云平台环境配置和服务的使用方法,下面再来看看程序model和controller。
Model
程序存储两类数据:客户customer和调查survey。一个customer通过持有一个surveyInfo(调查问卷)与多条survey(调查问题项)关联。main / java / org / springframework / data / mongodb /examples / custsvc / domain 目录下即为这三者的域文件。
由于customer和survey分别使用Mysql和Mongodb两种不同的数据库存储,因而为了建立二者的关联关系,需要依赖Spring Data MongoDB交叉存储(cross store)的支持。实体类Customer中的实现如下:
import org.springframework.data.mongodb.crossstore.RelatedDocument;
//import more necessary dependencies here...
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
@RelatedDocument
private SurveyInfo surveyInfo;
//set() & get() methods here...
}
通过使用 @RelatedDocument 标记建立起客户与调查问卷交叉存储的关联关系。当然,在这之前你要对pom文件和应用程序上下文做适当的配置,请参考Spring Data的官方文档。
对于customer数据的增删查等操作,在main / java / org / springframework / data / mongodb /examples / custsvc / data 目录下建立了JPA持久化事务类CrossStoreCustomerRepository与Mysql数据库打交道。对Mongodb数据库中survey数据的操作,也是通过Customer对象所持有的SurveyInfo引用间接进行的。
Controller
Controller就比较简单了。main / java / org / springframework / data / mongodb /examples / custsvc / web目录下,除了刚才提到的云环境拦截器外,还有三个控制器分别处理新建customer、customer信息展示和survey维护、数据库增删查等请求。
四、总结
如果要在应用程序中同时使用多个不同类型的数据库,如关系型数据库MySQL和文档数据库MongoDB,那么Spring Data MongoDB的cross store交叉存储机制可以满足这种需求。这个样例程序不仅展示了Cloud Foundry中MySQL和MongoDB云服务的使用方法,也为云平台上不同类型数据库间交叉存储的应用程序开发提供了一个很好的学习范例。