介绍一个最近项目上使用的一个架构

数据库:使用mysql主从复制+mysql proxy代理

             使用redis进行缓存机制,做一些交互比较频繁的业务

系统端:JAVA编写,提供接口服务,SOA框架

后台端:PHP编写

前台端:PHP编写

 

SOA 项目框架及应用中使用介绍

SOA介绍

SOA目录结构

\MultiSOA\

|__resources  ——资源文件夹

. |__js

扫描二维码关注公众号,回复: 615487 查看本文章

. . |__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.xmldynamicSchool2.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、层与层之间通过接口形式调用,严格禁止直接使用实现类作为方法调用入口。

2WebSc.层业务调用CTRL.层接口,以统一业务过程。

3、一般情况下只有对公业务才需要实现WebSc.层,内部业务不需要实现ESB

4、需要定时执行的业务计划,也可调用CTRL.层接口或SERV.层接口,例如需要预先产生缓存的业务控制计划,或留言发送的业务逻辑计划。

5、适当配置业务计划的执行间隔周期,可减轻轮询业务的代码编写工作量。

6、文件流可以配合Ftp服务分流减轻Http服务压力。

7、重要业务必须使用日志记录全部请求、时间、参数、执行结果。

8、所有异常必须捕获详细日志,并记录引起异常的事件、时间和请求参数

9、增加动态数据源建议新增Hibernate配置文件基本信息,再增加一个实现基类(baseDao)DAO接口实现数据持久化

10、同构数据库模型放在一齐,异构数据库模型应分别存放在不同的包中。

11、切换静态数据源调用utilDbContextHolder.setDb(SessionFactoryName)

12、切换学校源调用daoDynamicDaoI. changeCatalog(MX_HJT_000)

13、切换动态源调用daoDynamicDaoI.changeSessionFactiory(sessionFactoryName)

14、平台默认静态数据源是mysqlsessionFactory,因业务需要切换到非默认静态数据源以外的静态数据源DbContextHolder.setDb(SessionFactoryName)

在业务使用完毕后,需要主动切回到默认数据源DbContextHolder.setDb(mysqlsessionFactory),否则该会话的下一个业务请求如果需要使用默认数据源将找

不到SessionFactory

15DefaultController包含平台默认首页和错误跳转处理。

16HTTP GET请求的参数可通过路径映射参数,以隐藏参数名,提高传输安全性。@RequestMapping(value = "/get/{gpString}"),注意valueparams

的区别,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();

  }

17HTTP 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

  配置数据库datasourcesessionfactory和数据库事务

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

  实现SessionFactoryApplicationContextAware接口,以获得当前Session和上下文,

DbContextHolder.java

实现一个本地线程以获取当前的SessionFactoryObServer,并提供gettersetter方法,setter方法供给业务以切换不同的sessionFactorygetter

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)两者实现类是一致的,只是链接到不同得数据源目标。还需建立两个操作类(redisTemplateWredisTemplateR)依赖

JedisConnectionFactory 类进行不同目标的数据访问。

  JedisPoolConfig类是spring-data-redis提供的Redis连接池配置类,由于当前数据库架构已对数据库节点进行统一管理,此处不需要依赖连接池

 

SOA在应用中使用介绍

运行环境

硬件环境:WEB服务器 + 数据库服务器 + 核心业务服务器 + 数据库代理服务器 + 负载均衡器

软件环境:Linux + JDK6 + Apache + PHP + Tomcat 7 + MySQL 5 + Redis

平台架构

硬件架构采用分布式数据库与服务器分离相结合的架构设计。如图【图2.4.1】平台硬件架构

说明: C:\Users\Administrator\AppData\Roaming\Tencent\Users\1198917953\QQ\WinTemp\RichOle\IJ8DVR]SNB89SNY0`(]8Q3G.jpg

【图2.4.1】平台硬件架构

软件体系架构分为七个层次,分别是应用控制层/平台表现层、服务总线层、业务控制层、业务处理层、业务组件层、数据访问层、源数据层。各层功能模块的基本功能介绍如下图【图2.4.2】各层功能模块划分

说明: C:\Users\Administrator\AppData\Roaming\Tencent\Users\1198917953\QQ\WinTemp\RichOle\QG1VJS]X~%(H23O`LPU{NJ9.jpg

【图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】业务流程处理

 说明: C:\Users\Administrator\AppData\Roaming\Tencent\Users\1198917953\QQ\WinTemp\RichOle\LGT`2]_O6`X{]XRW4LPV@SR.jpg

【图2.5.1】业务流程处理

系统结构


数据读/写分布


 

使用redis存储在内存中,是一种nosql的方式,以key-value的方式存储,读取快。主要用于前台的读取

 

猜你喜欢

转载自jiony.iteye.com/blog/1856510
今日推荐