基于Spring Boot读写分离架构的理财系统
2022-11-28朱文杰姚雨晨伏胜洋
朱文杰,姚雨晨,伏胜洋,汪 洋
(1.湖北师范大学 计算机与信息工程学院,湖北 黄石 435000;2.华中师范大学 物理科学与技术学院,湖北 武汉 430000)
1 开发背景
近年来互联网金融的发展迅猛,拟开发一个具有操作特色的理财系统。现有的理财系统多数基于C#[1]和Android[2,3]等开发技术,开发难度较大,并且在效率和易维护性上存在一定问题。本文针对传统方案设计模式存在的问题及缺陷,设计并实现了一套以Spring Boot为框架的B/S快速设计系统;为了实现该系统前后端分离,引入MVC进行设计,使用Spring Boot以及MyBatis框架进行项目编码;其后端借助Spring Boot、MyBaits、MySQL[4,5]等服务平台,在实现基本功能的前提下,使用page helper进行页面操作,前台使用模板语言thyme leaf,并配以使用Maven、MyBatis[6]等提供的技术优势,有效地降低了开发复杂度,实现资源横向扩展、动态伸缩,快速响应外部需求的变化。此外,本系统还加入了个性化等设计,改善用户体验。
2 开发技术
Spring Boot是一个开源框架,其内部整合了众多配置功能,可以利用其控制反转、依赖注入以及切面编程的特性,实现通过简单的配置较为迅速地搭建出应用开发平台功能。同时,本理财系统通过合理的使用其注释功能来简化项目开发过程,以达到加快开发进程的目的。
“高内聚,低耦合”是代码编写的目标,内聚和耦合都是一种度量[7~9]。内聚包括偶然内聚、逻辑内聚、时间内聚以及过程内聚等等,其是指模块内各个部分之间的紧密程度,高内聚是指一个模块由相关性较强的代码组成且该模块只实现一项功能。耦合包括无直接耦合、数据耦合、标记耦合以及控制耦合等等,其是指模块之间的互连程度。与内聚不同,随着系统代码之间的耦合性的增强,系统各个功能模块互相调用关系混乱不清,代码的独立性就会因此降低。为了避免此问题,本理财系统采用面向服务架构技术开发。
面向服务架构SOA(Service-Oriented Architecture)是一种面向服务的、处理不同软件之间数据交互的粗粒架构[10~12];其根据整体应用的不同功能进行拆分来得到多个功能块,进而提供不同服务;服务之间通过协议进行联系,每个服务之间的功能都是彼此独立且可相互调用。为提高服务在不同系统中的适用性,我们在本理财系统中定义一个服务的接口或者协议时,往往采用能区分且用于实现服务系统的编程语言或者操作系统,以此来实现服务的跨系统交互。
读写分离(如图1)用于解决数据库的读取性能限制,但并不是所有的读性能受限制都是要用读写分离。对于大多数业务,多见读写不均的现象,主要是数据库读能力要比写能力强很多,而往往写数据库能力是数据库的瓶颈。本理财系统为了较大提升数据库的写性能,削弱读写冲突,提升数据库写入能力,就必须使用读写分离。
图1 读写分离适用场景
3 系统需求分析、总体设计
3.1 系统需求设计
本系统实现功能:权限管理、用户信息管理、理财产品管理等。用户可以使用该系统进行理财产品的购买以及贷款申请,理财方式包括零钱理财、工资理财等,同时该系统也会给用户更新理财产品信息。为满足网站用户的需求,系统管理者可以在管理端对用户端的使用权限进行修改,同时对用户端理财信息进行增删改查。
3.2 总体设计
本系统分为管理端和用户端,如图2.
1)用户端则分为四个模块:系统首页、个人理财、金融工具、个人中心。系统首页提供理财简介以及理财书籍推荐。个人理财包括零钱理财、工资理财、期限理财、基金理财四种理财产品以及银行推荐,用户可以在此进行理财产品的购买。金融工具包括资金记录和安全网贷,用户可以通过资金记录查找账户资金流向,同时可以通过安全网贷页面进行网络贷款。个人中心分为我的理财、我的借贷、银行卡管理、账户安全。用户可以通过我的理财界面进行对已购买理财产品的管理,在我的借贷界面进行还贷,账户安全页面可以进行账户密码的修改。
2)管理员通过登录管理账户对该理财系统进行管理。用户信息管理界面分为用户信息、银行卡、个人征信三个部分,管理员可在此进行用户信息以及征信管理。管理员可以在理财产品管理界面进行理财产品的管理以及银行推荐信息的更新。权限管理部分可以进行用户界面功能的修改以及管理员权限的设置。同时,对于用户提交的网贷申请,管理员可以在网贷管理界面进行审核,除此之外,管理员可以在网贷信息界面进行系统用户网贷信息的查看以及提醒还款操作。
3.3 微服务在理财系统开发中的应用
在本理财系统多功能模块的搭建中,如果简单地将以上功能模块进行打包整合,形成一个巨大的服务单元,也称为单体式应用[13,14]。虽然单体式应用在系统部署方面确实具有一定的优势,但是在系统不断迭代升级后,其内部功能模块关系会因此变得十分复杂,此时进行修改以及扩展是十分困难的。所以为了解决这一问题,引入微服务进行系统管理。
微服务是SOA的细粒级组件[15~17],相比于SOA,微服务更加注重于轻量级服务,虽然微服务和SOA实现服务所用的技术不同,但两者功能十分相似。对于一个SOA架构,我们可以将其拆分为松散耦合的微服务组件,这些微服务组件均可独立部署且可实现和SOA相同的功能,如图3.
图3 单体式应用以及微服务示意图
3.4 系统数据库组织与读写分离的实现
由于MySQL占用小且运行速度快,所以本理财系统采用MySQL用作数据库,其为一种关系型的数据库管理系统。选用MySQL可以将本理财系统的各类数据存放在不同的表中,如此可以使访问速度提高。在实际使用过程发现直接在MySQL对数据进行操作较为麻烦,为了简化数据库管理,且综合考虑便捷性以及成本,本系统采用Navicat对数据库进行管理,即MySQL对系统的数据进行管理[18,19],而Navicat对MySQL进行管理。
本理财系统创建19个数据库表,各用于存储管理员信息、管理员许可、银行信息、银行卡信息、零钱理财信息、资金记录、基金理财信息、通知信息、贷款信息、理财新闻信息、用户许可信息、期限理财信息等。以下列数据库表(表1)为例:
表1 数据库设计表格
在管理数据库时,我们发现理财系统的数据库在高并发写入时,表现出较大的压力。此时需要削弱读写冲突,以此提高数据库写能力。我们可以采用读写分离,将理财系统原本的数据库分为主从库,其中我们用主库进行写数据(增、删、改),剩余的从库用于读数据(查),其中在主库和多个从库之间进行数据同步,如图4.
图4 读写分离总体示意图
3.5 读写分离相关实现类
实现 MySQL数据库的动态读写分离,主要由以下几个类实现:
1) ResourceHandlers(ResourceHandlerRegistry registry) Springboot默认静态资源访问路径,若静态资源路径不是在Springboot规定的静态资源文件夹下面,则需要在下面添加映射路径;
public void ResourceHandlers(ResourceHandlerRegistry registry)
{registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/webjars/**").addResourceLocations("/webjars/"); }
2) determineTargetDataSource设置获取数据源,determineCurrentLookupKey决定当前数据源的对应的key,
DataSource determineTargetDataSource(){
Object lookupKey=this. determineCurrentLookupkey();
DataSource dataSource=(DataSource) this. resolvedDataSources. get(lookupkey); if(dataSource== null &&(this. lenientFallback II lookupkey ==null)){
dataSource=this. resolvedDefaultDataSource;
if(datasource ==nul1){throw new IllegalStateException("Cannot determine target Datasource for lookup key ["+lookupkey+"]");
} else{return dataSource;}
根据determineCurrentLookupKey获取的key,在resolvedDataSources这个Map中查找对应的datasource。
3) AfterPropertiesSet它在bean实例已经创建好,且属性值和依赖的其他bean实例都已经注入以后执行,也就是说调用,targetDataSources,defaultTargetDataSource的赋值一定要在afterPropertiesSet前边执行;
Override public void AfterPropertiesset(){
if(this. targetDatasourcesum null){
this.resolvedDatasources = new HashMop
object lookupkey=resolveSpecifiedLookupkey(entry. getkey());
DataSource datasource resolvespecifiedDataSource(entry.getvalue()); this.resolvedDataSources.put(lookupkey, dataSource); }}
4) DataSourceAOP实现AOP的前置通知,对所有返回值进行校验以判别对数据库是进行读操作还是写操作,使用request的getParameter方法,让其在返回值的时候检查提交方式;
public void DataSourceAOP (ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
response.setCharacterEncoding(code);
response.setContentType("text/html;charset=" + code);
MyHttpServletRequest myRequest = new MyHttpServletRequest((HttpServletRequest));
chain.doFilter(myRequest, response);}
通过上面介绍的相关类,便可高效快捷实现本理财系统数据库读写分离。此外,当用户数量增多,遇到性能瓶颈时,这种结构便于进行多方面扩展,例如添加数据源、添加数据库、负责均衡等,根据需求动态收缩,以实现系统升级迭代,实现示意图如图5所示:
图5 SpringBoot读写分离实现示意图
4 系统测试运行
用户在理财系统上的网页请求会被控制器转移给与之对应的模型进行处理,控制器只是选择适当的模型进行处理,处理完成后控制器再调用相应的视图来显示返回的数据。当我们需要对理财系统的用户体验进行改进时,不需要再次进行逻辑的编写,不需要再次编辑业务逻辑,以此减少项目编辑时长,提高项目开发的效率。
4.1 登录界面
该部分主要通过Shiro框架来实现。为了系统用户能顺利登入本理财系统(如图6),需要Shiro拦截器对URL进行拦截。Shiro Config配置首先设置安全管理器,再添加Shiro的内置过滤器并设置过滤器规则。在Realm可以增加验证码校验,当验证失败时抛出异常,Shiro认为登录失败,则记录异常信息并执行登录失败逻辑。
图6 登录界面
4.2 系统首页
该部分通过控制器controller实现。其作用是先根据不同的用户请求分配URL,再根据URL匹配不同的接收器,再分别进行处理,最后向用户返回结果。本部分与数据库匹配,管理员可以在数据库中对该部分内容进行修改。
系统首页包含了理财系统的大部分功能模块,如果在代码编写过程中不注意代码结构,很容易引发高耦合。若此时不对代码层进行调整,将会导致系统各功能模块产生混乱。我们可以通过代码解耦合来解决这一问题。
首先,抽象系统模块得到模块以及类之间的关系,通过模块依赖关系初步判断是否需要进行解耦合,如果依赖关系混乱,再结合参考间接衡量标准进行综合判断,若代码结构在可读性以及可维护性确实存在缺陷,则需要进行解耦合。
解耦合可分为三步,首先进行封装,其次进行中间层处理,最后进行模块化。常见的解耦合方式有以下几种:
Spring Aop(面向切片编程),主要实现业务代码以及非业务代码之间的解耦合。其中业务代码指直接实现响应用户需求的代码,非业务代码指脱离业务存在的代码,也被称之为辅助业务代码。
Ioc(控制反转),主要实现服务创建者与服务对象之间的解耦。
消息队列,实现观察者与被观察者之间的解耦合。
4.3 个人理财
管理员可以通过理财产品管理界面(如图7)进行系统理财产品的更新,通过Change Money Controller、Pay Money Controller、Term Financial Controller、Fund Product Controller、Bank Controller五个控制器来实现。使用Request Mapping来处理请求地址映射的注解,把WEB请求映射到相应的处理函数。Request Mapping的变体形式包括Get Mapping和Put Mapping,均用于向服务器提交信息。
图7 零钱理财界面
4.4 金融工具
金融工具页面包括资金记录和安全网贷。用户可以在资金记录界面(如图8)查询到账户资金的流向明细。该部分通过Recorder Controller控制器实现。为了跳转到资金记录界面,首先引入Page Helper插件,在查询之前使用Start Page方法,来传入页码以及每页大小。再使用Page Info打包查询后的结果,并移交给页面进行下一步处理。
图8 资金记录界面
4.5 个人中心
该部分由My Finance Controller、Loan Controller、Bank Card Controller、User Controller控制器实现,根据理财类别对用户已购买的理财产品进行明细显示(如图9)。
图9 我的理财界面
用户输入借贷金额以及借贷期限,即可进行贷款申请,管理员可以对申请进行审核。
5 结语
针对目前市面上理财系统存在的一些不足,分析并设计了一种读写分离的理财管理系统。系统开发基于SpringBoot微架构,其中Spring Boot使用Java构建微服务,利用Spring Boot + Mybatis框架搭建理财管理系统,本文重点描述了微服务系统读写分离功能原理以及相关实现的过程,通过实际运行测试,系统稳定性以及实用性符合设计要求,为理财新手提供一种更易上手的理财方式。
Design and implementation of financial management system with read-write separation based on Spring Boot
ZHU Wen-jie1,YAO Yu-chen1,FU Sheng-yang1,WANG Yang2