基于SOA架构采用Extjs展现的权限系统之总体设计探讨

  上一篇文章说过,系统由数据层,业务层,服务层,数据契约层,WCF代理层,ExtJs代理层,展现层组成。现在我们一起探讨这些层之间的作用。

  众所周知,主流的三层结构由数据库,业务层与展现层组成。我认为:SOA架构在三层的基础上添加服务层,数据契约层,WCF代理层。

现在一起探讨一下各层之间的作用吧!

 

  数据层:用于与数据库交互的层。提供简洁实用的数据库访问方法,如:添加,删除,更新,查找等等。我这里的数据层采用Linq技术,由Linq自动生成数据访问层,节省了不少开发时间哦。

 

  业务层:用于支撑业务需求,该层一般要具备高度灵活性,可扩展性,可配置等。大部份情况下会提供相关的工具一起支撑业务需求。如:配置管理器。在设计此层的时候,要考虑重用,节省下次开发软件的成本。个人认为:这也是衡量软件开发人员水平的一个重要因素。

 

  服务层:SOA架构下,该层是必不可少的。服务层的作用是:业务以服务的形式提供外部接口。使业务的访问方式与平台,技术无关。把握服务的粒度是相当重要的。比如:权限系统中包含用户,用户组,权限,模块和他们这间的分配等操作。大家认为,服务的粒度该如何把握。我这里先提供两种个人想法:1. 将整个权限系统作为一个服务;2.将权限系统的各个功能块分别成为服务。如:用户服务,用户组服务等。目前我采用的是第一种方式,如果大家有更好的想法,希望一起探讨哦。

 

  数据契约层:服务是离不开契约的,就像鱼和水的故事。因为契约是发布服务的方式。没有了它外部对服务就不可见了。既然他们不能分离,为什么不将数据契约层与服务层合并在一起呢,你这不是棒打鸳鸯麻。我也是迫不得已呀,因为我要让服务的实现代码与公开的接口进行分离,这样我们就可以使实现细节安全一些,保护鱼儿哇。

 

     WCF代理层:该是用在客户端,也是必不可少呢。一般通过添加服务引用即可自动生成。

 

     ExtJs代理层:为什么要有ExtJS代理层呢?因为ExtJs在与WCF直接交互将会遇到很多问题。如:WCFExtJs通过JSON序列化后日期格式的冲突,树的JSON格式(ExtJS树有自己的固定格式),WCF获取ExtJs的参数等。最最关键的是:我不能为了使用ExtJs而使服务层变成只支持ExtJs的服务,这脱离了服务的本质。因此我加入的ExtJs代理层。解决服务与ExtJS交互的问题。

 

     ExtJs展现层:当我在07年的时候第一次看到ExtJs时,是多么的兴奋与喜悦。这世上还有如何美妙的Web界面。着实让我激动了好几天。当时JS还是菜鸟的我,就凭的一股傻劲肯下了这块硬骨头。家谈唠叨完了,下面说正题,大家见谅哇。ExtJs展现层是提供给用户操作的,直接影响的用户体验。现在的部份客户,已经不仅仅只要求软件能满足由业务需要,而且还要美观,易用,最好能一见钟情哇。有人说ExtJs很庞大,速度慢,难维护等相关缺点。是的,我不否认这些观点,ExtJs并不是十全十美,但它也解决了很多问题。如:树。ASP.NET提供的树与ExtJs提供的树根本不在一个层次。记得有篇文章《为了树,也要学习ExtJs》。我现在为用户组分配用户等这类的功能,准备以拖放的形式进行分配,提高易用性及用户体验,使Web的应用程序也能拥有Winform的效果。如果大家有更易用的分配方式,请不吝赐教哦。关于ExtJs很庞大,我觉的ASP.NET更庞大。为什么不排斥呢?我觉得,它由容易调试,写代码方便等因素决定的。反之JS,难调试,写代码也没有像样的智能提示。关于速度慢, 200K的文件下载,第一次的访问的速度确实快不到哪去。所以我推荐将ExtJs用于后台管理,前端访问量大的可以采用JQuery这些轻量极的工具。但ExtJs将很多事情放在客户端作,一定程度降低了服务端的压力。关于难维护这个缺点,我也谈谈个人的看法。如果将JS代码进行良好的组织,维护还是可以的。我目前的JS代码都采用了命名空间并以包含或继承的方式实现。如:用户界面。我先实现自己的EditorGridPanel,然后User继承于EditorGridPanel实现用户的界面。如果分配用户的功能需要用户的界面,直接new User()就可以获得用户界面。这样可扩展性,可维护性,可重用性不就提高了么。下面贴一下这块的代码。欢迎大家拍砖哇~~

 


/// <reference path="~/extjs/ext-all-debug.js"/>
/*
*
 * author: 许道松
 * email: fjfuqingxds@163.com
 * createDate: 2008-9-28
*/
// EditorGridPanel类
//
 ================================
//
创建自定义Grid,并继承自 Ext.grid.EditorGridPanel
XDS.Platform.Grid.EditorGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
    constructor: 
function(config) {
        
this.clicksToEdit = 1;
        
this.autoScroll = true;
        Ext.applyIf(
this, {
            store: 
new XDS.Platform.Data.Store({
                url: XDS.Platform.config.UrlUnion(
this.url, XDS.Platform.config.SelectOperation),
                id: 
this.dataKey,
                fields: 
this.fields,
                grid: 
this,
                listeners: {
                    beforeload: 
function() {
                        
this.help = new XDS.Platform.Help();
                        
this.help.beforeload(this.grid);
                    },
                    load: 
function() {
                        
this.help.completeload(this.grid);
                    }
                }
            })
        });
        Ext.applyIf(
this, {
            viewConfig: {
                forceFit: 
true,
                columnsText: 
'',
                sortAscText: 
'升序',
                sortDescText: 
'降序'
            },
            bbar: 
new Ext.PagingToolbar({
                pageSize: 
this.pageSize,
                store: 
this.store,
                displayInfo: 
true,
                displayMsg: 
'总记录数{0} - {1} of {2}',
                emptyMsg: 
"没有记录"
            })
        });
        
if (Ext.isArray(this.operate)) {
            Ext.applyIf(
this, { tbar: new XDS.Platform.Grid.GridToolBar(this) });
        }
        XDS.Platform.Grid.EditorGridPanel.superclass.constructor.call(
this, config);
    },
    load: 
function() {
        
this.getStore().load({ params: { start: 0, limit: this.pageSize} }); 
    }
});

 

 


/// <reference path="~/extjs/ext-all-debug.js"/>
/*
*
 * author: 许道松
 * email: fjfuqingxds@163.com
 * createDate: 2008-9-28
*/
// 用户类
//
=================================================
XDS.Security.User = Ext.extend(XDS.Platform.Grid.EditorGridPanel, {
    autoExpandColumn: 
'UserName',
    url: XDS.Platform.config.UserUrl,
    dataKey: 
'UserName',
    pageSize: XDS.Platform.config.PageSize,
    fields: Ext.data.Record.create([
               { name: 
'UserID' }, 
               { name: 
'UserName' },
               { name: 
'Email' },
               { name: 
'IsApproved' },
               { name: 
'IsLockedOut' },
               { name: 
'CreationDate' },
               { name: 
'LastLoginDate' },
               { name: 
'LastActivityDate' },
               { name: 
'LastPasswordChangedDate' },
               { name: 
'LastLockoutDate' },
               { name: 
'Comment' },
               { name: 
'PasswordQuestion' }
     ]),

    constructor: 
function(config) {
        config 
= config || {};
        Ext.applyIf(
this, config);
        
this.operate = config.operate || ["add""delete""save""refresh"];
        
var chkIsApproved = new Ext.grid.CheckColumn({
            header: 
"是否审核",
            tooltip: 
"是否审核",
            dataIndex: 
'IsApproved',
            width: 
60
        });
        
var chkIsLockedOut = new Ext.grid.CheckColumn({
            header: 
"是否锁定",
            tooltip: 
"是否锁定",
            dataIndex: 
'IsLockedOut',
            width: 
60
        });
        
this.sm = new Ext.grid.CheckboxSelectionModel();
        
this.cm = new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), this.sm, {
            id: 
'UserName',
            header: 
'用户名',
            dataIndex: 
'UserName',
            width: 
50
        }, {
            id: 
"Email",
            header: 
"电子邮件",
            dataIndex: 
'Email',
            width: 
150
        }, {
            id: 
"PasswordQuestion",
            header: 
"密码问题",
            dataIndex: 
'PasswordQuestion',
            width: 
100
        }, {
            header: 
'创建时间',
            dataIndex: 
'CreationDate',
            width: 
100,
            renderer: XDS.Platform.Help.renderDate
        }, chkIsApproved, chkIsLockedOut, {
            header: 
"最后登陆时间",
            width: 
100,
            dataIndex: 
"LastLoginDate",
            renderer: XDS.Platform.Help.renderDate
        }, {
            header: 
"最后活动时间",
            width: 
100,
            dataIndex: 
"LastActivityDate",
            renderer: XDS.Platform.Help.renderDate
        }, {
            header: 
"最后更改密码时间",
            width: 
110,
            dataIndex: 
"LastPasswordChangedDate",
            renderer: XDS.Platform.Help.renderDate
        }, {
            header: 
"最后锁定时间",
            width: 
100,
            dataIndex: 
'LastLockoutDate',
            renderer: XDS.Platform.Help.renderDate
        }, {
            header: 
"注释",
            width: 
100,
            dataIndex: 
'Comment',
            editor: 
new Ext.form.TextField({
                allowBlank: 
true
            })
}]);
            
this.cm.defaultSortable = true;


            Ext.menu.RangeMenu.prototype.icons 
= {
                gt: 
'images/greater_then.png',
                lt: 
'images/less_then.png',
                eq: 
'images/equals.png'
            };
            Ext.grid.filter.StringFilter.prototype.icon 
= 'images/find.png';
            Ext.grid.filter.BooleanFilter.prototype.displayText 
= {
                yes: 
'',
                no: 
''
            };
            Ext.grid.filter.DateFilter.prototype.displayText 
= {
                before: 
'',
                after: 
'',
                on: 
''
            };
            
var filters = new Ext.grid.GridFilters({
                filters: [
                { type: 
'numeric', dataIndex: 'ProductID' },
                { type: 
'string', dataIndex: 'UserName' },
                { type: 
'string', dataIndex: 'Email' },
                { type: 
'string', dataIndex: 'PasswordQuestion' },
                { type: 
'date', dataIndex: 'CreateDate' },
                { type: 
'date', dataIndex: 'LastLoginDate' },
                { type: 
'date', dataIndex: 'LastActivityDate' },
                { type: 
'date', dataIndex: 'LastPasswordChangedDate' },
                { type: 
'date', dataIndex: 'LastLockoutDate' },
                { type: 
"boolean", dataIndex: 'IsApproved' },
                { type: 
"boolean", dataIndex: 'IsLockedOut' },
                { type: 
'string', dataIndex: 'Comment' }
            ]
            });

            
var data = [
            [
'0''谁是你最爱的儿'],
            [
'1''谁是你的另一半'],
            [
'2''你的爱好是什么'],
            [
'3''我最喜欢的歌']
        ];
            
this.addPanel = new Ext.FormPanel({
                labelAlign: 
'right',
                windowTitle: 
'注册新用户',
                frame: 
true,
                labelWidth: 
60,
                width: 
300,
                height: 
200,
                bodyStyle: 
'padding:5px 5px 0',
                defaultType: 
'textfield',
                defaults: { width: 
180, anchor: '95%' },
                collapsed: 
false,
                items: [{
                    fieldLabel: 
'用户名',
                    name: 
'UserName',
                    allowBlank: 
false
                }, {
                    fieldLabel: 
'密码',
                    name: 
'Password',
                    inputType: 
'password',
                    allowBlank: 
false
                }, {
                    fieldLabel: 
'确认密码',
                    inputType: 
'password',
                    vtype: 
'password',
                    initialPassField: 
'reg_Password',
                    allowBlank: 
false
                }, {
                    fieldLabel: 
'电子邮件',
                    name: 
'Email',
                    vtype: 
'email'
                }, {
                    fieldLabel: 
'安全问题',
                    xtype: 
'combo',
                    allowBlank: 
false,
                    store: data,
                    emptyText: 
'请选择安全问题基于SOA架构采用Extjs展现的权限系统之架构层级探讨',
                    name: 
'Question'
                }, {
                    fieldLabel: 
'安全答案',
                    name: 
'Answer',
                    allowBlank: 
false
}]
                });
                
this.plugins = [chkIsApproved, chkIsLockedOut, filters];
                XDS.Security.User.superclass.constructor.call(
this);

            }
        });

 

 

相关文章: