数据库:使用mysql主从复制+mysql proxy代理
使用redis进行缓存机制,做一些交互比较频繁的业务
系统端:JAVA编写,提供接口服务,SOA框架
后台端:PHP编写
前台端:PHP编写
SOA 项目框架及应用中使用介绍
SOA介绍
SOA目录结构
\MultiSOA\
|__resources ——资源文件夹
. |__js
. . |__hjt
. . . |__soa
. . . . |__hbm ——主要数据源映射文件夹
. . . . |__school ——动态学校库数据映射文件夹
. . . . |__seed ——旧系统主要数据映射文件夹
|__src ——编码文件夹
. |__js
. . |__hjt
. . . |__soa
. . . . |__component ——业务组件接口
. . . . . |__impl ——业务组件实现方法
. . . . |__controller ——业务控制器接口
. . . . . |__exception ——业务异常拦截器
. . . . . . |__resolver
. . . . . |__impl ——业务控制器实现方法
. . . . |__dao ——数据层访问接口
. . . . . |__impl ——数据层访问实现方法
. . . . |__httpModel ——输入输出层模型包
. . . . |__interceptors ——全局拦截器包
. . . . |__model ——数据模型文件夹
. . . . |__quartz ——定时任务应用包
. . . . |__service ——业务逻辑接口
. . . . . |__impl ——业务逻辑实现方法
. . . . |__util ——公共方法
. . . . |__webservice ——服务接口(esb)
. . . . . |__impl ——服务实现方法
已实现的技术关键:
可分布的部署、
动态的多数据源
定时执行任务计划
一级、二级缓存(三级缓存需要较高性能的CPU,暂不考虑)
FTPserver
Webservice
静态路径映射
参数对象化封装
Redis持久化
开发要点:
明确层级之间的分工:
DAO层作为数据处理层,基于BASEDAO,可实现80%的数据库输入输出工作,只有特殊业务的数据传输方式,才需要建立DAO层代码,同时需要扩
展BASEDAO以实现基类方法。
COMP.层作为业务组件层,同样建有BASECOMP.,组件间存在共性的业务组件,在基类中实现,但要考虑松散耦合,共性较高的才放在基类,所有COMP.
都需要扩展基类以获得默认事务控制,该层可理解为“组件工厂”。
SERV.层作为业务逻辑层,基于BASESERV.,共性基类应包含如鉴权、会话标记、登入登出、数据转换等业务逻辑,该层的主要作用是“业务车间”,
针对业务特性封装不同的组件层代码以完成业务过程,同时把元数据与JSON 格式之间做转换处理。
CTRL.层作为业务控制层,对业务请求进行分配管理和特殊数据格式处理(系统默认数据格式采用JSON,特殊格式需求全部在CTRL.层转换)。
WebSc.层作为ESB总线,用户可以一览所有服务列表,该层如增加服务,需要手动添加到配置文件(spring-cxf.xml),并重启项目。
Quartz层作为定时执行的任务计划资源,该层需要增加执行计划时,也需要手动添加到配置文件(spring-quartz.xml),并重启项目。
Ehcache使用前需要在配置文件(ehcache.xml)中预先声明缓存变量,然后在需要使用缓存的方法上添加@Cacheable(value = "已声明的缓存变量",[key=”
区分条件,一般是以传入的参数作为区分”]),需要重启项目。
明确资源文件和包之间的分工:
impl包作为父包中接口的实现类库。
httpModel包作为封装对外数据模型的类库,也就是用于集成数据的VO。
model包则仅作为与数据源格式一致的模型类库。
util 包无需解释,就是常用的公共方法啦,但是这里的是类不应该依赖注入,如无可避免,需要手动在配置文件(随便一个spring的配置文件都行)中
主动注入。
datasource.properties稳定数据源链接的信息资源,包括分布数据源。
dynamicSchool.cfg.xml、dynamicSchool2.cfg.xml 动态数据源示例配置文件
ehcache.xml 缓存配置文件。
ftpConfig.properties FTP权限配置文件。
hibernate.cfg.xml 动态学校数据源链接的基础信息。
log4j.properties log4j 框架配置文件。
spring-apacheFtpServer.xml FTP服务配置文件。
spring-cxf.xml ESB服务列表配置文件。
spring-ehcache.xml spring缓存开启配置文件。
spring-hibernate.xml静态数据源、事务管理配置文件。
spring-redis.xml Redis数据源链接配置文件。
spring-mvc.xml spring-mvc框架配置文件。
spring-quartz.xml 定时计划配置文件。
spring.xml spring框架配置文件。
明确开发使用技巧:
1、层与层之间通过接口形式调用,严格禁止直接使用实现类作为方法调用入口。
2、WebSc.层业务调用CTRL.层接口,以统一业务过程。
3、一般情况下只有对公业务才需要实现WebSc.层,内部业务不需要实现ESB。
4、需要定时执行的业务计划,也可调用CTRL.层接口或SERV.层接口,例如需要预先产生缓存的业务控制计划,或留言发送的业务逻辑计划。
5、适当配置业务计划的执行间隔周期,可减轻轮询业务的代码编写工作量。
6、文件流可以配合Ftp服务分流减轻Http服务压力。
7、重要业务必须使用日志记录全部请求、时间、参数、执行结果。
8、所有异常必须捕获详细日志,并记录引起异常的事件、时间和请求参数
9、增加动态数据源建议新增Hibernate配置文件基本信息,再增加一个实现基类(baseDao)的DAO接口实现数据持久化
10、同构数据库模型放在一齐,异构数据库模型应分别存放在不同的包中。
11、切换静态数据源调用util包DbContextHolder.setDb(SessionFactoryName)。
12、切换学校源调用dao包DynamicDaoI. changeCatalog(MX_HJT_000)。
13、切换动态源调用dao包DynamicDaoI.changeSessionFactiory(sessionFactoryName)。
14、平台默认静态数据源是mysqlsessionFactory,因业务需要切换到非默认静态数据源以外的静态数据源DbContextHolder.setDb(SessionFactoryName),
在业务使用完毕后,需要主动切回到默认数据源DbContextHolder.setDb(mysqlsessionFactory),否则该会话的下一个业务请求如果需要使用默认数据源将找
不到SessionFactory。
15、DefaultController包含平台默认首页和错误跳转处理。
16、HTTP GET请求的参数可通过路径映射参数,以隐藏参数名,提高传输安全性。@RequestMapping(value = "/get/{gpString}"),注意value和params
的区别,params是作为此方法被调用的判定条件,可增加method=RequestMethod.GET以区分请求类型。
Javascript:
function _get() {
$.ajax({
type : 'GET',
contentType : 'application/json',
url : 'http://129.1.8.17:8080/MultiSOA/my/get/2012-12-21 12:21:00.json',
dataType : 'text/html',
success : function(data) {
alert(data);
},
error : function() {
alert('Err...');
}
});
}
Ctrl:
public String _get(@PathVariable Date gpString) {
return gpString.toString();
}
17、HTTP POST请求的参数可直接通过JSON 进行封装,绑定到指定的对象,平台自动根据对象类型把协议转换成对象。(@RequestBody Demo)。需要
多个对象可整合多个JSON 对象封装传递(demo = '{"demo1":{"gpName":"档载工"},"demo2":{"dtStr":"2012-12-21"}}')
Javascript:
function _post() {
var demo = '{"demo1":{"gpName":"档载工"},"demo2":{"dtStr":"2012-12-21"}}';
$.ajax({
type : 'POST',
contentType : 'application/json',
url : 'http://129.1.8.17:8080/MultiSOA/my/post.json',
dataType : 'json',
data : demo,
success : function(data) {
alert(data.demo1.gpName + "\n" + data.demo2.dtStr);
},
error : function() {
alert('Err...');
}
});
}
Ctrl:
public Demo _post(@RequestBody Demo demo) {
return demo;
}
普通表单封装成JSON 格式的函数,要引用JQ.JS,JSON.JS
$.fn.serializeObject = function(){
var obj = {};
var count = 0;
$.each( this.serializeArray(), function(i,o){
var n = o.name, v = o.value;
count++;
obj[n] = obj[n] === undefined ? v
: $.isArray( obj[n] ) ? obj[n].concat( v )
: [ obj[n], v ];
});
//obj.nameCounts = count + "";//表单name个数
return JSON.stringify(obj);
};
调用方法:$(“#formID”). serializeObject();
18、上传文件到平台使用AJAX提交,平台不提供任何可操作的展示界面。
19、以表单方式提交表单对象,可以再表单对象中以[对象.字段名]的方式绑定到指定子VO,但是表单VO必须唯一
HTML:
<form id="demo" method="post" action="http://129.1.8.17:8080/MultiSOA/my/form.json">
<input name="demo1.gpname" value="档载工"/>
<input name="demo2.dtStr" value="2012-12-21"/>
<input type="submit" value="Gou P" />
</form>
Ctrl:
public Demo _form(Demo demo) {
return demo;
}
明确注解规范:
@Controller ——声明Controller
@Service ——声明Service
@Repository ——声明Dao
@Component ——声明Component(不便分类的Bean也注册为组件)
@Resource ——资源注入,默认按名称装配
@Autowired ——对象注入,默认按类型装配
@Transactional ——纳入事务管理
@Scope ——定义作用域
@WebService ——声明WebService
@WebMethod ——声明WebService中的方法
@WebParam ——声明WebService中的参数名
@Cacheable ——声明缓存方法
@InitBinder ——绑定属性有效值,表单数据格式
@RequestMapping ——路径请求映射
@PathVariable ——绑定路径映射参数名
@RequestParam ——绑带请求地址的参数名
@RequestBody ——绑定请求对象
@ResponseBody ——将对象转换为JSON 协议输出
框架集成过程:
项目信息设置(web.xml)
项目名、项目描述(description & display-name)
会话超时时间(session-config/session-timeout)
首页(welcome-file-list/welcome-file)
错误页面(error-page/error-code/location)
集成Spring (spring.xml & web.xml)
web.xml
集成上下文(Context-param/param-name & param-value)
定义字符集过滤器(filter/encodingFilter)
Spring监听器(listener : spring监听器)
spring.xml
注入资源文件(context:property-placeholder)
自动注入资源包(context:component-scan [dao & component & service])
配置Log4j全局日志附着器和日志记录等级(后期需要细化配置)
集成Hibernate (spring-hibernate.xml & datasource.properties & web.xml)
datasource.properties
设置数据库连接属性和hibernate属性
spring-hibernate.xml
配置数据库datasource、sessionfactory和数据库事务
web.xml
设置在会话中保持session状态(filter:openSessionInViewFilter)
设置一个会话当中只能打开一个session,避免打开多个session的异常(init-param/param-name : singleSession & param-value : true)
集成Ehcache (spring-ehcache.xml & ehcache.xml & web.xml)
spring-ehcache.xml
开启spring缓存,并将缓存事务委托給ehcache
ehcache.xml
设置默认缓存属性和缓存路径(defaultCache & diskStore)
定义缓存属性(cache)
web.xml
缓存清理监听器(listener : Introspector 缓存清理监听器)
集成ApacheFtpServer (spring-apacheFtpServer.xml & ftpConfig.properties & web.xml)
spring-apacheFtpServer.xml
设置FTP服务器属性
ftpConfig.properties
设置FTP服务器文件目录、权限
web.xml
FTP监听器(listener : apache ftp server 监听器)
集成CXF (spring-cxf.xml & web.xml)
spring-cxf.xml
自动注入服务资源包(controller & webservice)
引用服务资源(impor)
定义服务列表(jaxws:endpoint)
web.xml
设置servlet服务路径(servlet : cxf)
设置cxf启动时加载(load-on-startup : 1)
集成Quartz(spring-quartz.xml)
自动注入任务资源包(quartz)
配置任务(jobDetail & cronTrigger & schedulerFactory)
延迟执行(startupDelay : value = “sec”)
集成Spring MVC (spring-mvc.xml & web.xml)
spring-mvc.xml
自动注入控制器资源包(controller)
协议转换拦截,输入输出通过JSON 协议传递
定义模板文件前后缀,初步定义为JSP文件模板,一般用不上。。。
限制上传文件SIZE,可以通过AJAX上传到平台
设置编码拦截(EncodingInterceptor)
设置日志拦截(LoggerInterceptor)
web.xml
设置servlet服务路径(servlet : MultiSOA)
设置MultiSOA启动时加载(load-on-startup : 1)
集成多数据源 (MultiSessionFactory.java & DbContextHolder.java & spring-hibernate.xml)
MultiSessionFactory.java
实现SessionFactory和ApplicationContextAware接口,以获得当前Session和上下文,
DbContextHolder.java
实现一个本地线程以获取当前的SessionFactoryObServer,并提供getter和setter方法,setter方法供给业务以切换不同的sessionFactory,getter供
给MultiSessionFactory.java在获取DataSource时以sessionFactoryName作为参照获取其目标数据源
spring-hibernate.xml
由于多数据源并不包含在自动注入的资源包中,所以需要手动配置注入Bean,并且需要指定默认的sessionFactory,这里指定默认的数据源为
MYSQL主数据源
集成动态数据源(DynamicDaoI.java & DynamicDaoImpl.java & hibernate.cfg.xml & dynamicSchool.cfg.xml & dynamicSchool2.cfg.xml)
DynamicDaoI.java
动态数据源调用接口
DynamicDaoImpl.java
动态数据源实现方法
分开2个方法处理不同情况的动态数据源,一种是学校数据源,在同一服务器地址,不同数据库,可以直接调用changeCatalog切换数据库,不
需要重新申请资源;另外一种是独立数据库、独立地址的过渡性数据源,调用changeSessionFactory注册资源;并关闭上一个活动Session,一个
会话只能保留一个活动Session
hibernate.cfg.xml
默认动态数据源配置文件
默认配置没有sessionFactoryName
dynamicSchool.cfg.xml & dynamicSchool2.cfg.xml
指定加载的动态数据源配置文件
通过不同的SessionFactoryName(文件名)区分不同的动态数据源
集成spring-data-redis(spring-redis.xml)
spring-redis.xml
配置redis数据源
因为需要手动实现读写分离,所以建立两个JedisConnectionFactory,一个进行写入(jedisConnectionFactoryW),另一个用来读取
(jedisConnectionFactoryR)两者实现类是一致的,只是链接到不同得数据源目标。还需建立两个操作类(redisTemplateW、redisTemplateR)依赖
JedisConnectionFactory 类进行不同目标的数据访问。
JedisPoolConfig类是spring-data-redis提供的Redis连接池配置类,由于当前数据库架构已对数据库节点进行统一管理,此处不需要依赖连接池
SOA在应用中使用介绍
运行环境
硬件环境:WEB服务器 + 数据库服务器 + 核心业务服务器 + 数据库代理服务器 + 负载均衡器
软件环境:Linux + JDK6 + Apache + PHP + Tomcat 7 + MySQL 5 + Redis
平台架构
硬件架构采用分布式数据库与服务器分离相结合的架构设计。如图【图2.4.1】平台硬件架构
【图2.4.1】平台硬件架构
软件体系架构分为七个层次,分别是应用控制层/平台表现层、服务总线层、业务控制层、业务处理层、业务组件层、数据访问层、源数据层。各层功能模块的基本功能介绍如下图【图2.4.2】各层功能模块划分
【图2.4.2】各层功能模块划分
总体设计采用SOA分层设计模式:
<!--[if !supportLists]-->① <!--[endif]-->业务请求从商家应用或用户平台表现层传入到请求控制中心;
<!--[if !supportLists]-->② <!--[endif]-->控制中心通过对业务特性分析分配到指定的业务控制器;
<!--[if !supportLists]-->③ <!--[endif]-->控制器开始命令业务车间执行相应的业务流程;
<!--[if !supportLists]-->④ <!--[endif]-->业务车间按照控制器的要求向组件工厂获取需要的组件进行装嵌;
<!--[if !supportLists]-->⑤ <!--[endif]-->组件工厂的逻辑如果需要读取系统数据,它只能通过数据访问层的不同接口获得相应返回结果;
<!--[if !supportLists]-->⑥ <!--[endif]-->数据访问层可以对系统数据进行直接的CRUD操作,是平台唯一能对数据进行处理的地方;
详见【图2.5.1】业务流程处理
【图2.5.1】业务流程处理
系统结构
数据读/写分布
使用redis存储在内存中,是一种nosql的方式,以key-value的方式存储,读取快。主要用于前台的读取。