zoukankan      html  css  js  c++  java
  • Spring.NET教程(十七)——整合NHibernate和ASP.NET MVC(基础篇)

     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中写好要注入的属性。

      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();
            }
         }

      我们知道,对Controller依赖注入需要新建一个ControllerFactory。我们实现System.Web.Mvc.IControllerFactory接口即可。实际上就是替换现有的ControllerFactory,让Spring.NET容器管理Controller。包含Spring.NET容器配置的Controller使用新建的ControllerFactory,没有包含Spring.NET容器配置的Controller使用原有的DefaultControllerFactory。

      SpringControllerFactory

     * 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类。

      Global.asax.cs

            protected void Application_Start()
            {
                log4net.Config.XmlConfigurator.Configure();
                ControllerBuilder.Current.SetControllerFactory(typeof(Controllers.SpringControllerFactory));
                RegisterRoutes(RouteTable.Routes);
            }

      然后我们以HomeController为例,增加一些方法。

      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();
            }

    Controllers.xml

    <?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。

      Web.config

    <?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教程(十九)——整合NHibernate和ASP.NET MVC(基础篇) Level 300

    Spring.NET教程(十九)——整合NHibernate和ASP.NET MVC(基础篇) Level 300

      我个人认为Spring.NET在SessionFactory和事务控制上对Nhibernate支持的很好,减少了我们的代码量和增加了扩增性,这就是为什么Nhibernate与Spring.NET能成为一对很好组合的原因。 

     

  • 相关阅读:
    Codeforces Round #401 (Div. 2)【A,B,C,D】
    HDU2874【LCA(模板)】
    ZOJ2898【折半搜索】
    zoj2901【DP·二进制优化】
    萌新笔记之鸽巢原理及其应用
    codeforces 547B【单调栈】
    Codeforces631C【栈维护+瞎搞】
    每天一节组合数学
    HDU 1506【单调栈】
    HDU 3410【单调栈】
  • 原文地址:https://www.cnblogs.com/millen/p/1635982.html
Copyright © 2011-2022 走看看