Spring.NET学习笔记19——整合NHibernate和ASP.NET MVC(基础篇)
2011-04-10 20:03
639 查看
ASP.NET MVC Framework是微软官方提供的MVC模式编写ASP.NET Web应用程序的一个框架。MVC(Model-View-Controller)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller)。
今天带给大家的就是期待以久的ASP.NET MVC与Spring.NET和NHibernate的组合,视图打造.NET版的SSH(Spring-Struts-Hibernate)。是不是听到名字都很兴奋?我认为目前的ASP.NET MVC比Struts在某些功能上要好用的多,而且代码量要少,这就是我一直热衷于ASP.NET MVC的原因。
我们接着昨天的例子学习。昨天我们成功测试了带事务的业务层。接下来就是将业务层的对象注入到Controller中。我们先在Controller中写好要注入的属性。
我们知道,对Controller依赖注入需要新建一个ControllerFactory。我们实现System.Web.Mvc.IControllerFactory接口即可。实际上就是替换现有的ControllerFactory,让Spring.NET容器管理Controller。包含Spring.NET容器配置的Controller使用新建的ControllerFactory,没有包含Spring.NET容器配置的Controller使用原有的DefaultControllerFactory。
在Global.asax.cs的Application_Start方法下增加一些代码,注册SpringControllerFactory类。
然后我们以HomeController为例,增加一些方法。
这里的HomeController我们部署了非singleton模式。
最后我们配置Web.config。我总结了一下,有两个要注意的地方:
1.需要在appSettings节点处配置SessionFactory的id
2.需要配置httpModules,因为这关系到SessionFactory的作用域,直接影响对象的“延迟加载”等一系列问题。实际上SessionFactory的开关有Spring.Data.NHibernate.LocalSessionFactoryObject来控制。实现原理是Spring.NET会在HttpApplication.BeginRequest的事件中注册打开SessionScope的动作,并在HttpApplication.EndRequest的事件中注册关闭SessionScope的动作。这就意味着SessionFactory完全由Spring.NET来管理,我们不需要使用using语句来强制关闭Session。
我们运行一下程序。
我个人认为Spring.NET在SessionFactory和事务控制上对Nhibernate支持的很好,减少了我们的代码量和增加了扩增性,这就是为什么Nhibernate与Spring.NET能成为一对很好组合的原因。
代码下载
今天带给大家的就是期待以久的ASP.NET MVC与Spring.NET和NHibernate的组合,视图打造.NET版的SSH(Spring-Struts-Hibernate)。是不是听到名字都很兴奋?我认为目前的ASP.NET MVC比Struts在某些功能上要好用的多,而且代码量要少,这就是我一直热衷于ASP.NET MVC的原因。
我们接着昨天的例子学习。昨天我们成功测试了带事务的业务层。接下来就是将业务层的对象注入到Controller中。我们先在Controller中写好要注入的属性。
public class HomeController : Controller { public ICompanyManager CompanyManager { get; set; } public IUserManager UserManager { get; set; } public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; ViewData["Company"] = CompanyManager.LoadAll(); return View(); } }
我们知道,对Controller依赖注入需要新建一个ControllerFactory。我们实现System.Web.Mvc.IControllerFactory接口即可。实际上就是替换现有的ControllerFactory,让Spring.NET容器管理Controller。包含Spring.NET容器配置的Controller使用新建的ControllerFactory,没有包含Spring.NET容器配置的Controller使用原有的DefaultControllerFactory。
/* * 刘冬 博客园 * www.cnblogs.com/GoodHelper */ using System; using System.Collections.Generic; using System.Linq; using System.Web; using Spring.Context; using Spring.Context.Support; using System.Web.Mvc; namespace Controllers { /// <summary> /// Spring.NET ControllerFacotry /// </summary> public class SpringControllerFactory : IControllerFactory { /// <summary> /// Default ControllerFactory /// </summary> private static DefaultControllerFactory defalutf = null; public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) { //get spring context WebApplicationContext ctx = ContextRegistry.GetContext() as WebApplicationContext; string controller = controllerName + "Controller"; //查找是否配置该Controller if (ctx.ContainsObject(controller)) { object controllerf = ctx.GetObject(controller); return (IController)controllerf; } else { if (defalutf == null) { defalutf = new DefaultControllerFactory(); } return defalutf.CreateController(requestContext, controllerName); } } public void ReleaseController(IController controller) { //get spring context IApplicationContext ctx = ContextRegistry.GetContext(); if (!ctx.ContainsObject(controller.GetType().Name)) { if (defalutf == null) { defalutf = new DefaultControllerFactory(); } defalutf.ReleaseController(controller); } } } }
在Global.asax.cs的Application_Start方法下增加一些代码,注册SpringControllerFactory类。
protected void Application_Start() { log4net.Config.XmlConfigurator.Configure(); ControllerBuilder.Current.SetControllerFactory(typeof(Controllers.SpringControllerFactory)); RegisterRoutes(RouteTable.Routes); }
然后我们以HomeController为例,增加一些方法。
public class HomeController : Controller { public ICompanyManager CompanyManager { get; set; } public IUserManager UserManager { get; set; } public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; ViewData["Company"] = CompanyManager.LoadAll(); return View(); } [AcceptVerbs(HttpVerbs.Post)] public ActionResult SaveUser(User user) { user.CurrentCompany = CompanyManager.Get(user.CurrentCompany.CompanyID); UserManager.Save(user); return RedirectToAction("GetCompany", "Home", new { id = user.CurrentCompany.CompanyID }); } [AcceptVerbs(HttpVerbs.Post)] public ActionResult SaveCompany(Company company) { CompanyManager.Save(company); return RedirectToAction("Index", "Home"); } public ActionResult GetCompany(int id) { ViewData["Company"] = CompanyManager.Get(id); return View(); } public ActionResult About() { return View(); }
<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net"> <object id="HomeController" type="Controllers.HomeController, Controllers" singleton="false"> <property name="CompanyManager" ref="CompanyManager"/> <property name="UserManager" ref="UserManager"/> </object> </objects>
这里的HomeController我们部署了非singleton模式。
最后我们配置Web.config。我总结了一下,有两个要注意的地方:
1.需要在appSettings节点处配置SessionFactory的id
2.需要配置httpModules,因为这关系到SessionFactory的作用域,直接影响对象的“延迟加载”等一系列问题。实际上SessionFactory的开关有Spring.Data.NHibernate.LocalSessionFactoryObject来控制。实现原理是Spring.NET会在HttpApplication.BeginRequest的事件中注册打开SessionScope的动作,并在HttpApplication.EndRequest的事件中注册关闭SessionScope的动作。这就意味着SessionFactory完全由Spring.NET来管理,我们不需要使用using语句来强制关闭Session。
<?xml version="1.0"?> <!-- Note: As an alternative to hand editing this file you can use the web admin tool to configure settings for your application. Use the Website->Asp.Net Configuration option in Visual Studio. A full list of settings and comments can be found in machine.config.comments usually located in /Windows/Microsoft.Net/Framework/v2.x/Config --> <configuration> <configSections> <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/> <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/> </sectionGroup> </sectionGroup> </sectionGroup> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> <sectionGroup name="common"> <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /> </sectionGroup> <sectionGroup name="spring"> <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" /> <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /> <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" /> </sectionGroup> <section name="databaseSettings" type="System.Configuration.NameValueSectionHandler"/> </configSections> <log4net debug="true"> <appender name="LogFileAppender" type="log4net.Appender.FileAppender"> <param name="File" value="Logs/Application.log.txt" /> <param name="datePattern" value="MM-dd HH:mm" /> <param name="AppendToFile" value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" /> </layout> </appender> <appender name="HttpTraceAppender" type="log4net.Appender.ASPNetTraceAppender"> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" /> </layout> </appender> <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender"> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" /> </layout> </appender> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="Logs/Log.txt" /> <param name="AppendToFile" value="true" /> <param name="MaxSizeRollBackups" value="10" /> <param name="MaximumFileSize" value="100K" /> <param name="RollingStyle" value="Size" /> <param name="StaticLogFileName" value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n" /> </layout> </appender> <root> <level value="ALL" /> <appender-ref ref="RollingLogFileAppender" /> </root> </log4net> <spring> <parsers> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> </parsers> <context> <resource uri="config://spring/objects" /> <resource uri="assembly://Repository/Repository/Repository.xml" /> <resource uri="assembly://Manager/Manager/Manager.xml" /> <resource uri="assembly://Controllers/Controllers/Controllers.xml"/> </context> <objects xmlns="http://www.springframework.net" /> </spring> <!--数据库连接字符串--> <databaseSettings> <add key="db.datasource" value="." /> <add key="db.user" value="sa" /> <add key="db.password" value="" /> <add key="db.database" value="SpringNet_Lesson18" /> </databaseSettings> <!--很重要--> <appSettings> <add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName" value="NHibernateSessionFactory" /> </appSettings> <connectionStrings/> <system.web> <!-- Set compilation debug="true" to insert debugging symbols into the compiled page. Because this affects performance, set this value to true only during development. --> <compilation debug="true"> <assemblies> <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="MvcContrib"/> </assemblies> </compilation> <!-- The <authentication> section enables configuration of the security authentication mode used by ASP.NET to identify an incoming user. --> <authentication mode="Forms"> <forms loginUrl="~/Account/LogOn" timeout="2880"/> </authentication> <membership> <providers> <clear/> <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/> </providers> </membership> <profile> <providers> <clear/> <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="/"/> </providers> </profile> <roleManager enabled="false"> <providers> <clear/> <add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> <add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> </providers> </roleManager> <!-- The <customErrors> section enables configuration of what to do if/when an unhandled error occurs during the execution of a request. Specifically, it enables developers to configure html error pages to be displayed in place of a error stack trace. <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm"> <error statusCode="403" redirect="NoAccess.htm" /> <error statusCode="404" redirect="FileNotFound.htm" /> </customErrors> --> <pages> <controls> <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> </controls> <namespaces> <add namespace="System.Web.Mvc"/> <add namespace="System.Web.Mvc.Ajax"/> <add namespace="System.Web.Mvc.Html"/> <add namespace="System.Web.Routing"/> <add namespace="System.Linq"/> <add namespace="System.Collections.Generic"/> <add namespace="MvcContrib.UI.Tags"/> <add namespace="MvcContrib.UI"/> <add namespace="MvcContrib.UI.Html"/> <add namespace="MvcContrib.UI.Html.Grid"/> <add namespace="MvcContrib"/> </namespaces> </pages> <httpHandlers> <remove verb="*" path="*.asmx"/> <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/> <add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> </httpHandlers> <httpModules> <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <!--很重要--> <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate21"/> <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web" /> </httpModules> </system.web> <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <providerOption name="CompilerVersion" value="v3.5"/> <providerOption name="WarnAsError" value="false"/> </compiler> <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <providerOption name="CompilerVersion" value="v3.5"/> <providerOption name="OptionInfer" value="true"/> <providerOption name="WarnAsError" value="false"/> </compiler> </compilers> </system.codedom> <system.web.extensions/> <!-- The system.webServer section is required for running ASP.NET AJAX under Internet Information Services 7.0. It is not necessary for previous version of IIS. --> <system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules runAllManagedModulesForAllRequests="true"> <remove name="ScriptModule"/> <remove name="UrlRoutingModule"/> <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> </modules> <handlers> <remove name="WebServiceHandlerFactory-Integrated"/> <remove name="ScriptHandlerFactory"/> <remove name="ScriptHandlerFactoryAppServices"/> <remove name="ScriptResource"/> <remove name="MvcHttpHandler"/> <remove name="UrlRoutingHandler"/> <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> </handlers> </system.webServer> </configuration>
我们运行一下程序。
我个人认为Spring.NET在SessionFactory和事务控制上对Nhibernate支持的很好,减少了我们的代码量和增加了扩增性,这就是为什么Nhibernate与Spring.NET能成为一对很好组合的原因。
代码下载
相关文章推荐
- Spring.NET学习笔记19——整合NHibernate和ASP.NET MVC(基础篇) Level 300
- Spring.NET教程(十七)——整合NHibernate和ASP.NET MVC(基础篇)
- ASP.NET MVC 1.0 + spring.net 1.2.0.20288 + NHibernate 2.0.1.4000整合笔记(三)——NHibernate配置
- ASP.NET MVC NHibernate 整合
- ASP.NET MVC Spring.NET NHibernate 整合
- [转]ASP.NET MVC Spring.NET NHibernate 整合
- Asp.Net MVC大型项目实践整合 NHibernate与Json序列化
- Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac(转)
- ASP.NET MVC+EasyUI+Entity FrameWork 整合开发
- 搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (二)创建你的项目
- ASP.NET MVC+Nhibernate+bootcss实现权限管理系列[完全免费和开源] 序
- asp.net MVC+NHibernate项目开发日志
- ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)
- Spring.NET企业架构实践之 Nhibernate + WCF + ASP.NET MVC + NVelocity 对PetShop4.0重构(一)——架构设计
- 搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (二)创建你的项目(转)
- 搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (五)测试你的成果
- ASP.NET MVC+Spring.net+Nhibernate+EasyUI+Jquery开发案例(2)
- DotNet企业级架构实战之7——Spring.net整合Asp.net mvc
- 搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (六)写在后面的话
- ASP.NET MVC+Spring.net+Nhibernate+EasyUI+Jquery开发案例(1)