资源描述
Mifos平台软件架构文档
1. 概要
本文抓住了关键架构决议平台。文档目标是为平台总体结构提供一个向导;它适合在一个管理信息系统处理方案整体背景及其内部贡献者能够更有效地了解她们正在考虑能够改变,这些改变影响。
这个汇报目标受众是系统集成商(谁将使用文档来了解平台结构及其设计原理)和平台贡献者将使用文档来推断未来改变和谁会伴随系统发展更新文档。
2. 介绍
2.1. 理念
Mifos是一个出于期望创建和布署技术,许可小额信贷行业规模想法。我们目标是:
l 产生一个黄金标准管理信息系统适合小额信贷业务
l 作为小额信贷基础平台
l 开源,拥有和由组员组织在小区
l 使潜在生态系统提供商周围小额信贷机构
2.2. 历史
l : 项目始于Grameen基金会
l 底: Grameen基金会把全部责任移交给开源小区。
l :Mifos X平台开始。之前项目组员以开源小区小额信贷(COSM / OpenMF)名义聚在一起
l :COSM / OpenMF正式更名Mifos倡议和接收美国税法条款501 c3。
2.3. 项目相关
项目URL
下载
下载统计 Download stats
3. 系统概览
现在金融体系经过多种多样手段向用户提供服务。
l 用户能够直接打电话到分支机构(出纳员模型)
l 许可用户能够组织团体(或中心)形式,和金融体系职员在约定时间和地点开会(传统小额信贷)。
l 金融体系可能有一个公开门面信息门户网站,用户能够使用多种原因包含账户管理(网上银行)。
l 金融体系集成到一个ATM / POS /卡服务网络,用户能够使用
l 金融体系可能和移动支付运行商集成和支持移动货币服务用户(现在/未来小额信贷)。
l 一个金融体系可能使用第三方代理销售其它银行/金融体系产品/服务
如上面图表所表示,各利益相关者利用业务应用程序实施特定用户或金融体系相关操作。这些业务应用程序中包含功效能够以任何方法捆绑打包。在图中,多个应用程序能够组合成一个应用程序或任何一块代表一个应用程序能够依据需要深入分解。
该平台是管理信息系统关键引擎。它隐藏了很多存在复杂金融体系中管理信息系统所需业务和技术领域背后一个相对简单API。这个API,使应用程序开发人员按金融体系她们需要那样进行创新和开发通常或定制应用程序。
4. 功效概览
作为平台全部功效全部经过一个API,该API文档是最好地方来查看该平台是做什么具体分解。看到网上API文档。
经过更高等级上我们看到功效分为以下几类:
l 基础构件
¡ 规范
¡ 扩展数据表
¡ 报表
l 用户管理
¡ 用户
¡ 角色
¡ 权限
l 机构模型
¡ 机构
¡ 职员
¡ 货币
l 产品配置
¡ 手续费
¡ 贷款产品
¡ 存款产品
l 用户资料
¡ 了解你用户
l 投资组合管理
¡ 贷款账户
¡ 存款帐户
¡ 用户/团体
l 总帐账户管理
¡ 会计科目表
¡ 总帐
5. 技术
· Java 7:
· JAX-RS 1.0: using Jersey (1.17.x)
· JSON using 谷歌 GSON
· Spring I/O Platform:
o Spring Framework
o Spring Security
o Spring Data (JPA) backed by Hibernate
· MySQL:
5.1. 关键技术
5.1.1. RESTful API
该平台经过practically-RESTful API公开其全部功效,通信使用JSON。
我们使用术语practically-RESTful为了使其清楚我们不是去依从完整REST,但仍然保持关键基于REST属性:
l 无状态:平台维护没有会话或基于会话状态。这么做结果是轻松扩展能力水平。
l 面向资源:API是集中在一组资源经过使用HTTP词汇和约定比如GET、PUT、POST、DELETE, HTTP状态代码。以达成为用户端提供一个简单和一致API。
看到网上API文档更多细节。
5.1.2. 多租户技术
mifos平台开发支持多租户设计关键。这意味着它是易于使用软件即服务(SaaS)平台型产品,因为它是为当地安装。
平台使用一个方法隔离金融体系数据库/数据/模式(见单独数据库和共享数据库,单独模式)。
5.1.3. 可扩展
同时每个租户将有一组关键表,表平台能够扩展以不一样方法为每个租户经过使用数据表功效。
5.1.4. 读写分离
我们分离写命令(修改数据)和查询(读取数据)。
为何?有很多原因选择这种方法,现在不是一个尝试全方面CQRS。现在关键优点是:
l 状态改变命令连续提供审计状态改变。
l 用于支持maker-checker通常方法。
l 状态改变命令使用面向对象模式(所以ORM),而查询能够保持为数据模式。
5.1.5. 四眼标准
也称为四眼标准。使应用程序能够支持maker-checker风格工作流过程。命令,经过验证将被持久化。Maker-checker在细粒度等级能够启用/禁用任何状态改变API。
5.1.6. 良好权限控制
细粒度权限和每个API。管理员有细粒度控制权什么角色或用户访问权。
6. 代码打包
意图是使平台代码以垂直切分方法(而不是层)打包。
源代码在这里 mifosng-provider/src/main/java/org/mifosplatform
org.mifosplatform.
· accounting
· useradministration
· infrastructure
· portfolio
o charge
o client
o fund
o loanaccount
· accounting
在每一个垂直部分是部分常见包装结构:
org.mifosplatform.useradministration.
· api - XXXApiResource.java - REST api实现文件
· handler - XXXCommandHandler.java -具体处理程序调用
· service -包含读+写服务功效区
· domain - OO概念功效区域
· data - 数据区域概念
· serialization -为功效区域转换API JSON
7. 设计概览
注意:经过实现平台代码来处理命令处理程序同时支持maker-checker和授权检验现在有点复杂,一个领域类针对性进行清理,让新平台开发人员更轻易入门。同时以下内容用于解释其工作原理。
考虑上图所表示例子为用户资源。
1. 查询:GET /用户
2. HTTPS API: retrieveAll 方法 org.mifosplatform.useradministration.api.UsersApiResource调用
3. UsersApiResource.retrieveAll:检验用户访问该资源权限数据
4. UsersApiResource.retrieveAll: 使用'read service'来获取全部用户数据('read service'实施简单SQL使用JDBC查询数据库)
5. UsersApiResource.retrieveAll: 返回数据转换成JSON响应
命令:POST /users (注:数据在请求body中)
HTTPS API: create方法在org.mifosplatform.useradministration.api.UsersApiResource中被调用
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String create(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createUser() //
.withJson(apiRequestBodyAsJson) //
.build();
final CommandProcessingResult result = mandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
描述:创建一个CommandWrapper对象表示这个create user命令和JSON请求主体。交给PortfolioCommandSourceWritePlatformService.logCommandSource进行处理。
@Override
public CommandProcessingResult logCommandSource(final CommandWrapper wrapper) {
boolean isApprovedByChecker = false;
// check if is update of own account details
if (wrapper.isUpdateOfOwnUserDetails(this.context.authenticatedUser().getId())) {
// then allow this operation to proceed.
// maker checker doesnt mean anything here.
isApprovedByChecker = true; // set to true in case permissions have
// been maker-checker enabled by
// accident.
} else {
// if not user changing their own details - check user has
// permission to perform specific task.
this.context.authenticatedUser().validateHasPermissionTo(wrapper.getTaskPermissionName());
}
validateIsUpdateAllowed();
final String json = wrapper.getJson();
CommandProcessingResult result = null;
try {
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(json);
final JsonCommand command = JsonCommand.from(json, parsedCommand, this.fromApiJsonHelper, wrapper.getEntityName(),
wrapper.getEntityId(), wrapper.getSubentityId(), wrapper.getGroupId(), wrapper.getClientId(), wrapper.getLoanId(),
wrapper.getSavingsId(), wrapper.getCodeId(), wrapper.getSupportedEntityType(), wrapper.getSupportedEntityId(),
wrapper.getTransactionId(), wrapper.getHref(), wrapper.getProductId());
result = this.processAndLogCommandService.processAndLogCommand(wrapper, command, isApprovedByChecker);
} catch (final RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
result = this.processAndLogCommandService.logCommand(e.getCommandSourceResult());
}
return result;
}
描述:检验用户许可此操作。假如好,)解析json请求身体,b)创建一个JsonCommand对象包装命令细节,c)使用CommandProcessingService处理命令。
注意:假如出现RollbackTransactionAsCommandIsNotApprovedByCheckerException。最初事务将被打掉,我们只有日志条目标命令审计表中设置其状态为“等候”。
@Transactional
@Override
public CommandProcessingResult processAndLogCommand(final CommandWrapper wrapper, final JsonCommand command, final boolean isApprovedByChecker) {
final boolean rollbackTransaction = this.configurationDomainService.isMakerCheckerEnabledForTask(wrapper.taskPermissionName())
&& !isApprovedByChecker;
final NewCommandSourceHandler handler = findCommandHandler(wrapper);
final CommandProcessingResult result = handler.processCommand(command);
final AppUser maker = this.context.authenticatedUser();
CommandSource commandSourceResult = null;
if (mandId() != null) {
commandSourceResult = mandSourceRepository.findOne(mandId());
commandSourceResult.markAsChecked(maker, DateTime.now());
} else {
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker);
}
commandSourceResult.updateResourceId(result.resourceId());
commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId(),
result.getSavingsId(), result.getProductId());
String changesOnlyJson = null;
if (result.hasChanges()) {
changesOnlyJson = this.toApiJsonSerializer.serializeResult(result.getChanges());
commandSourceResult.updateJsonTo(changesOnlyJson);
}
if (!result.hasChanges() && wrapper.isUpdateOperation() && !wrapper.isUpdateDatatable()) {
commandSourceResult.updateJsonTo(null);
}
if (commandSourceResult.hasJson()) {
mandSourceRepository.save(commandSourceResult);
}
if (rollbackTransaction) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(commandSourceResult); }
return result;
}
1. 检验假如maker-checker配置支持这一行动。假如是,这不是一个“检验”同意命令——回滚。最终我们回滚为了测试假如命令将“域验证”需要提交数据库进行全方面检验。
2. findCommandHandler——找到正确Hanlder处理此命令。
3. 过程命令使用处理程序(在事务作用域)。
4. CommandSource对象创建/更新日志“m_portfolio_command_source”表全部细节。
5. 在更新场景中,我们看看那里真任何更改/更新。假如是只存放在审计日志JSON改变。
展开阅读全文