.net企业级架构实战之7——Spring.net整合Asp.net mvc

出处:http://www.cnblogs.com/moye/archive/2008/11/30/1344369.html

既然提到mvc,就不得不说说微软在asp.net上的一个重要创造——postback机制。
但凡用asp.net做web开发的人,都和这个机制打过交道吧。asp.net页面aspx是其于这种自回发机制运转的。
我们平时用到的web控件,诸如TextBox、Button等,无一不是基于postback进行封装,在最终生成的html页中,它们还是会被转化成为<input type='text'>或者<input type='submit'>。
然后我们可以查看一下页面的源文件代码,会发现.net framework为我们写了不少东西:比如__doPostBack()这个js方法,用于提交窗体;WebForm_OnSubmit()方法会进行窗体的验证;一个长长的__VIEWSTATE隐藏字段保存窗体上控件的状态信息等(令人发指)……等等。(详述请参见种玉堂的《再认识asp.net的postback机制:探索__doPostBack的来龙去脉 》)。
多么让人又爱又恨的发明! postback确实方便了开发者,尤其是小型应用,手到擒来;但性能呢?不敢恭维!尤其那一长串__VIEWSTATE,每每看到,都觉得揪心。

所以,在项目中的前端表现界面,决定启用mvc实现。
原来使用monoRail,感觉很好,但一直没有解决与Spring.net整合问题;而后来干脆听说,monoRail已经停止维护这个项目,只得作罢。幸好,此时还有一个选择——asp.net Mvc。
经过一段时间的尝试,终于把它与Spring.net整合在了一起,这意味着,mvc能共享到Spring.net中的所有对象,无缝集成。

由于Asp.net Mvc是ASP.NET 3.5 Extensions Preview 的一个部分,能不能在IIS6+Asp.net 2.0 framework下良好运行,也一度让人担忧,可喜的是,网上很多人都这么干,并且成功了。也就是说,如果决定在.net 2.0下使用asp.net mvc(本实例使用的版本为asp.net mvc Preview 4),除引用mvc的dll外(Microsoft.Web.Mvc.dll、System.Web.Mvc.dll等),还需额外的引用一个.net 3.5的dll(System.core.dll),此处提供这个包的下载:

Asp.net mvc preview 4 和 System.core.dll(v3.5):/Files/moye/Asp.Net_MVC_4.rar

简单说,.net mvc将视图(View)与控制器(Controller)进行了分离,表现与逻辑的关注点不再纠缠于一团。而Model的传递,微软提供了一套DataDictionary(ViewDataDictionary、TempDataDictionary等)。同时,像monoRail一样,.net mvc在页面中也可以其于模板书写表达式,比如:你可以在Controller中传递一个IList<T>过来,这边接收到对象拆箱后,循环迭代输出一个行数等同的<Table>。
关于asp.net mvc的详尽原理,此处不累述,有兴趣可参阅 乱世重典的《Asp.net Mvc Framework 系列》。

欧克,回到重点,说说整合的事:

以上图示的结构:
将Controller单拿出来,做一个层,用以响应Web/Views中视图的请求。整合的目标就是:让这些Controller能够被注入,运行于Spring.net容器中。

通过学习Fredrik Normén的经验:《ASP.Net MVC Framework - Create your own IControllerFactory and use Spring.Net for DI 》,我们能知道,要创建自己的ControllerFactory,必须实现System.Web.Mvc的IControllerFactory接口。原型如(.net mvc Preview 4,版本不同接口也可能不一样):

using System;
using System.Web.Routing;

namespace System.Web.Mvc
{
   
public   interface IControllerFactory
    {
        IController CreateController(RequestContext context,
string controllerName);
       
void DisposeController(IController controller);
    }
}


在实现的CreateController方法中,将负责对不同的Views派发对应的Controller。这里做一个假设,/Views目录中有一个叫User的目录,那框架就认为,这是一个User视图集合(具体表现在url上,如/User/home、/User/login等),应该有一个叫UserController的控制器对此目录中的所有页面进行响应。

欧克,实践一把:

◆在Web的/Views创建一个web.config文件,并这样配置(它的作用:接管对.aspx页的请求流程):

web.config


◆在/Views中创建一个叫User的目录,并在其下添加一个Home.aspx页。当然这样是不能用的,需要修改一下页面和.cs:

Home.aspx
Home.aspx.cs


◆此时,还需要一个Controller来负责响应User视图中的请求,如前结构图所示,在woodigg.controllers层中,创建一个UserController类,担当控制器角色:

UserControllers.cs


◆在控制器中,有一个Home方法,它刚好与Home.aspx同名,所以它就是负责响应Home页请求的方法。Home方法有一个整型的参数,说明这个请求也是传递参数的,形如http://localhost/User/Home/1(在.net 2.0 url没这么完美,它形如http://localhost/User.mvc/Home/1),那么1就是这个id参数,然后就去查数据库吧,1号用户的数据将它展示出来,当然这个示例没有取任何东西,只是传递了一个ViewData数据。
而我们也注意到,这里还进行了注入,欧克,开始整合Spring.net和.net mvc控制器工厂吧

◆做一个spring.net配置文件,controllers.xml,还放在web的/config目录中:

controllers.xml


◆然后,为实现IControllerFactory,在bll层中创建一个SpringControllerFactory类(一旦此bll程序集被引用,所有Views请求都将视这个实现类为Handler,控制器由它派发,这是.net mvc一个很妙的设计):

 

 

using  System;
using  System.Collections.Generic;
using  System.Text;
using  Spring.Core.IO;
using  Spring.Objects.Factory;
using  Spring.Objects.Factory.Xml;
using  System.Web.Mvc;
using  System.Web.Routing;
using  System.IO;
using  woodigg.DAO.Tool;
using  Spring.Context;
using  Spring.Context.Support;

namespace  woodigg.bll.Handler
{
    
/// <summary>
    
/// 控制器工厂
    
/// </summary>

    public class SpringControllerFactory : IControllerFactory
    
{
        
/// <summary>
        
/// 实现接口 
        
/// </summary>
        
/// <param name="context"></param>
        
/// <param name="controllerType"></param>
        
/// <returns></returns>

        public IController CreateController(RequestContext context, string name)
        
{           
            
if (File.Exists(ParameterFactory.CfgControllersFilePath))
            
{
                
//配置上下文
                IApplicationContext configContext = new XmlApplicationContext(
                    ParameterFactory.CfgFilePath,
                    ParameterFactory.CfgBusinessFilePath,
                    ParameterFactory.CfgControllersFilePath,
                    ParameterFactory.CfgBusinessMediaFilePath
                    );                
                
//首字母大写的控制器名字
                string controllName = GetFirstUpcaseName(name) + "Controller";
                
//返回对应的对象:IOC                
                if(configContext.ContainsObject(controllName))
                    
return (IController)configContext.GetObject(controllName);
                
else
                    
return null;
            }

            
else
            
{
                IControllerFactory fa 
= ControllerBuilder.Current.GetControllerFactory();
                
return fa.CreateController(context, name);
            }

            
        }


        
public void DisposeController(IController controller)
        
{
            
        }


        
//首字母大写
        private string GetFirstUpcaseName(string name)
        
{
            
string temp = name.Replace(".mvc","").ToLower();
            
string first = temp[0].ToString();
            
return temp.Replace(first, first.ToUpper());
        }

    }

}

◆这里需要说明的是ParameterFactory:一个静态参数工厂。它将当前站点的SERVER端物理目录存在static string类型的变量中,此处用到的三个变量CfgFilePath、CfgBusinessFilePath、CfgControllersFilePath,分别为三个spring.net xml配置文件所在的物理路径。
显然,当Views/User/Home.aspx发出请求时,它会在/config/controllers.xml中找到UserController控制器,并不算完——UserController请求注入UserMainDaoSpring对象,它又会在/config/business.xml中找到这个对象的定义。完了吗?那得看UserMainDaoSpring是否也有注入别的对象了。
这种情况会乱吗?一点也不,即使你不用spring.net 整合它们,也一样会用到这些对象,只是使用的流程会有一些不同罢了。那么,在这个工厂中,只要捋清楚,你会用到哪些配置就行了(对这些配置xml文件,还是按用途分类比较好,如页面一个,访问层一个,web services一个……然后,去管理它们!)。

◆最后,把它们联结起来,在web/下新建一个Global.asax全局程序文件:

 

void Application_Start( object sender, EventArgs e) 
{

       
// 控制器与spring整合
        System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory
            (
typeof (woodigg.bll.Handler.SpringControllerFactory));       
}

 

课程简介:  本项目课程是一门极具综合性和完整性的大型项目课程;课程项目的业务背景源自各类互联网公司对海量用户浏览行为数据和业务数据分析的需求及企业数据管理、数据运营需求。 本课程项目涵盖数据采集与预处理、数据仓库体系建设、用户画像系统建设、数据治理(元数据管理、数据质量管理)、任务调度系统、数据服务层建设、OLAP即席分析系统建设等大量模块,力求原汁原味重现一个完备的企业级大型数据运营系统。  拒绝demo,拒绝宏观抽象,拒绝只讲不练,本课程高度揉和理论与实战,并兼顾各层次的学员,真正从0开始,循序渐进,每一个步骤每一个环节,都会带领学员从需求分析开始,到逻辑设计,最后落实到每一行代码,所有流程都采用企业级解决方案,并手把手带领学员一一实现,拒绝复制粘贴,拒绝demo化的实现。并且会穿插大量的原创图解,来帮助学员理解复杂逻辑,掌握关键流程,熟悉核心架构。   跟随项目课程,历经接近100+小时的时间,从需求分析开始,到数据埋点采集,到预处理程序代码编写,到数仓体系搭建......逐渐展开整个项目的宏大视图,构建起整个项目的摩天大厦。  由于本课程不光讲解项目的实现,还会在实现过程中反复揉和各种技术细节,各种设计思想,各种最佳实践思维,学完本项目并勤于实践的话,学员的收获将远远超越一个项目的具体实现,更能对大型数据系统开发产生深刻体悟,对很多技术的应用将感觉豁然开朗,并带来融会贯通能力的巨大飞跃。当然,最直接的收获是,学完本课程,你将很容易就拿到大数据数仓建设或用户画像建设等岗位的OFFER课程模块: 1. 数据采集:涉及到埋点日志flume采集系统,sqoop业务数据抽取系统等; 2. 数据预处理:涉及到各类字典数据构建,复杂结构数据清洗解析,数据集成,数据修正,以及多渠道数据的用户身份标识打通:ID-MAPPING等;3. 数据仓库:涉及到hive数仓基础设施搭建,数仓分层体系设计,数仓分析主题设计,多维分析实现,ETL任务脚本开发,ETL任务调度,数据生命周期管理等;4. 数据治理:涉及数据资产查询管理,数据质量监控管理,atlas元数据管理系统,atlas数据血缘管理等;5. 用户画像系统:涉及画像标签体系设计,标签体系层级关系设计,各类标签计算实现,兴趣类标签的衰减合并,模型标签的机器学习算法应用及特征提取、模型训练等;6. OLAP即席分析平台:涉及OLAP平台的整体架构设计,技术选型,底层存储实现,Presto查询引擎搭建,数据服务接口开发等;7. 数据服务:涉及数据服务的整体设计理念,架构搭建,各类数据访问需求的restapi开发等;课程所涉及的技术: 整个项目课程中,将涉及到一个大型数据系统中所用到的几乎所有主要技术,具体来说,包含但不限于如下技术组件:l Hadoopl Hivel HBasel SparkCore /SparkSQL/ Spark GRAPHX / Spark Mllibl Sqoopl Azkabanl Flumel lasal Kafkal Zookeeperl Solrl Prestop
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值