Spring.NET学习笔记19——整合NHibernate和ASP.NET MVC(基础篇) Level 300

ASP.NET MVC Framework是微软官方提供的MVC模式编写ASP.NET Web应用程序的一个框架。MVC(Model-View-Controller)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller)。

  今天带给大家的就是期待以久的ASP.NET MVCSpring.NETNHibernate的组合,视图打造.NET版的SSH(Spring-Struts-Hibernate)。是不是听到名字都很兴奋?我认为目前的ASP.NET MVC比Struts在某些功能上要好用的多,而且代码量要少,这就是我一直热衷于ASP.NET MVC的原因。

  我们接着昨天的例子学习。昨天我们成功测试了带事务的业务层。接下来就是将业务层的对象注入到Controller中。我们先在Controller中写好要注入的属性。


    public class HomeController : Controller
    {
        
public ICompanyManager CompanyManager { getset; }

        
public IUserManager UserManager { getset; }

        
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为例,增加一些方法。

 

HomeController

 

 

Controllers.xml

 

  这里的HomeController我们部署了非singleton模式。

 

  最后我们配置Web.config。我总结了一下,有两个要注意的地方:

  1.需要在appSettings节点处配置SessionFactoryid
  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支持的很好,减少了我们的代码量和增加了扩增性,这就是为什么NhibernateSpring.NET能成为一对很好组合的原因。  

 

  代码下载

 

posted @ 2012-02-19 10:21  张良  阅读(252)  评论(0编辑  收藏  举报