在《企业级应用架构》系列文章发表之余,也得到了许多同行的反馈,有人说这套框架太重了或者技术学习太复杂了或者初学者不太好理解或者完全颠覆了传统APS.NET开发模式让人望而生畏。这些理由在笔者看来确实是问题,但笔者也不得不说,那样的框架组合架构在某些企业级应用中是必须的,因为它有着传统asp.net开发模式无可比拟的多项优势,还望初学者能够坚持下来。
另外鉴于此,经过我亲身实践项目,现推出一个更加轻量级,更容易学习,更适合许多公司日常开发的部门级管理系统业务的新框架体系结构。这就是本文今日的主题。
主要框架组件:ASP.NET、Spring.NET、NHibernate、Log4Net、NUnit、Membership、EasyUI
架构图:
下图来源于笔者实际项目架构图。
![](https://images0.cnblogs.com/blog/371129/201308/09091508-eb79d3f290284b27a32d63d189903f57.jpg)
总体来说,项目架构依然实现经典的三层架构,前端MVC模式采用多数人熟悉的基于事件通信模式的ASP.NET框架,这是一个优秀的MVC实现模式,在经典Java EE中,sun公司也将这种基于事件通信模式的JSF作为前端MVC的标准。而Spring.Net和NHibernate的作用和地位,我也不多说了,相信看过前面的系列文章的同行早已知晓。
在我们许多管理系统中因为很多都是些增删改的数据逻辑操作,所以我们的Service层就会变得很瘦,因为许多构建数据查询条件的代码都被分离到Dao层中去了。故与之前的架构相比我们少了隔离层,但在这里我们将原来在隔离层中的数据验证、类型转换、异常捕获等工作全部交由Service来完成,这样变可以减少一个中间层,同时也不会让Service层感觉到太瘦小。
另外一个重要应用是,任然使用DTO(数据传输对象模式)作为业务层和表现层数据交换的载体,与数据实体(或领域层)彻底隔离,这样做的好处是相当明显的,不会让底层业务对象参与到表现层中来,从而达到解耦的目的。虽然这样也在一定程度上增加了代码量,但我觉得还是很值得的,这些代码不会很复杂,只是多一点而已。有个方法是Domain中的数据库实体和DTO中的对象都可以使用模版来生成,且完全可以保持DTO实体的属性和Entity的属性是完全相同的,我的意思是一次性生成DTO时,开发过程中DTO属性肯定是要扩展的,因为DTO包装的数据应该直接反映页面的需求,如:一个员工所属的部门名称,这在Entity类中员工实体需要访问部门实体的名称属性才能得到,但DTO对象就不用了,可以直接在员工类中自定义其部门名称,在Service层中直接将这个名称赋值给员工DTO对象的该属性即可,这样前端表格取数据时可以直接绑定该属性,这可以最大程度的减少表现层代码,从而降低表现层耦合度。达到业务代码级重用。自定义属性可以使用C#语法中的Partial关键字声明DTO对象实现,这样同样可以降低DTO模版生成类和自定义类之间的耦合,如果你觉得由Entity转Dto对象代码量大,你也可以选择使用AutoMapp这样的中间件来帮助你。说道这里可能有点复杂,下面给个简单的图示说明之。
![](https://images0.cnblogs.com/blog/371129/201308/09091129-f5549770e6df4352bcb8d5af37f6503d.bmp)
Common为公共组件或代码模块,其也有一个抽象层,比如说Log4Net组件,他是属于第三方组件,且几乎每个层都会使用到,所以我们不好将其归为某个一层而使用,而是将其归为公共层。其使用一个接口访问,那是因为我们应用程序不需要强制依赖这个Log4net组件,而将来可以任意更换为别的日志组件如果有更好的。这样就可以做到更高级别的应用程序重用效果。
NUnit涉及到两层,但它不作为应用程序的一部分发布。一帮来说,单元测试需要测试Dao层和Service层。如果你的系统简单,只测试Service层也可以。
本系统Dao异常捕获使用了Spring.net的AOP技术,这样可以让Dao层代码看起来更加简介。
本文章只提供基本的架构示例代码,不会提供完整的项目事例,这是为了保护原公司著作权和版权。另外提供生成Dto和Domain、Dao等层和相关配置文件的生成模版(Codesmith)。具体使用我不详述。注意这个模版生成的实体对象对于自关联的实体,还需要手动修改其对于自身引用对象赋null值,否则会引发堆栈溢出异常!另外还有一些一对多关系,也需要手动添加解决。望大家见谅!这些问题需要你比较了解NHibernate。如果对本架构有不理解之处,请参见笔者之前《企业级应用架构XXX》系列文章。
运行本事例,请自行下载NorthWind数据库。
示例代码: