将 Spring.NET 与 ASP.NET 网站集成






4.86/5 (48投票s)
本文介绍如何将 Spring.NET 企业框架与 ASP.NET 集成
引言
即使拥有良好的工具和技术,开发软件应用程序也足够困难。Spring.NET 开发人员说,Spring 提供了一种轻量级的解决方案来构建企业级应用程序。Spring 提供了一种一致且透明的方式来配置您的应用程序并将面向切面的编程 (AOP) 集成到您的软件中。Spring 功能的亮点是为您的中间层提供声明式事务管理以及一个功能齐全的 ASP.NET 框架。
据他们介绍,Spring.NET 是一个应用程序框架,为开发企业 .NET 应用程序提供全面的基础设施支持。它允许您消除使用基类库时的附带复杂性,从而使测试驱动开发等最佳实践变得容易。Spring.NET 由 SpringSource 创建、支持和维护。
环境设置
首先从 Sourceforge Spring.NET 下载页面下载 Spring.NET。撰写本文时,最新版本是 1.1。将其安装在默认位置。
ASP.NET 网站
要开始使用 Spring.NET,让我们创建一个新的网站。我们有一个Default.aspx页面。现在我们需要在Web.Config文件中创建节。
<configuration>
<configSections>
<!-- Spring -->
<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>
</configSections>
<!-- Spring -->
<spring>
<parsers>
</parsers>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net"
xmlns:db="http://www.springframework.net/database">
<!-- Pages -->
<object type="Default.aspx">
</object>
</objects>
</spring>
<sysyem.web>
<httpHandlers>
<!-- Spring Handler -->
<add verb="*" path="*.aspx"
type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
</httpHandlers>
<httpModules>
<add name="SpringModule"
type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
</httpModules>
</sysyem.web>
</configuration>
我们现在为*.aspx页面添加了一个新的 HTTP 处理程序,这是一个 Spring.NET 提供的处理程序。现在 Spring.NET 管理我们所有的 ASP.NET 页面。在此配置后,我们将能够为 ASP.NET 页面使用 Spring.NET 功能。
现在我们必须为站点添加引用。我们需要引用 Spring.NET 安装文件夹中的Spring.Core和Spring.Web程序集。我们现在可以运行应用程序来查看我们的页面。如果一切正常,我们将进入下一步。
依赖注入
DI 是一件非常有趣的事情。您可以使您的设计与具体实现完全解耦。为了实现这一点,让我们在页面代码中创建一个名为Message
的新string
类型属性,带有一个私有变量message
。在Page_Load
方法中,添加以下行
Response.Write(message);
这里我们不设置message
变量的值。我们将通过Web.Config文件设置它。现在我们更改Default.aspx的object
定义
<object type="Default.aspx">
<property name="Message" value="Hello from Web.Config"/>
</object>
现在我们已经通过配置文件在页面外部提供了一个值。我们在这里设置了一个字符串类型的值。我们也可以设置一个对象类型的值。为此,让我们定义一个带有单个方法的Math
类
public class Math
{
public int add(int x, int y)
{
return x+y;
}
}
现在让我们像为message
一样,在Default.aspx代码文件中添加一个名为Math
的新属性。在Page_Load
方法中,我们添加代码
Response.Write(math.add(30, 50));
现在我们在Web.Config中为Default.aspx对象上方添加新的对象定义。因此,我们的 spring 部分将变为
<spring>
<parsers>
</parsers>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns=http://www.springframework.net
xmlns:db="http://www.springframework.net/database">
<object name="MyMathObj" type="Math, App_code" />
<!-- Pages -->
<object type="Default.aspx">
<property name="Message" value="Hello from Web.Config"/>
<property name="Math" ref="MyMathObj"/>
</object>
</objects>
</spring>
处理数据
现在我们要处理数据。为了处理数据,Spring.NET 原生提供了 NHibernate 和 ADO.NET 支持。这里我们使用 NHibernate - 因为它处理了关于数据库的所有繁琐的事情,并让我们只在对象世界中工作。在 Spring.NET 安装文件夹的/bin和/lib目录中,我们有所需的 NHibernate 二进制文件。这里我使用 NHibernate 1.2 程序集。对于 hibernate,我们在数据库中定义一个名为person
的表,创建一个名为Person
的新类和一个 NHibernate 映射文件 (Person.hbm.xml)
Person 表
Column | 类型 | 修饰符 |
ID | 数字 | 非空,主键 |
VersionNumber | 数字 | - |
名称 | nvarchar(16) | 非空 |
Person 类
public class Person
{
private long id;
private string name;
private int versionNumber;
//These methods should be virtual for NHibernate Mapping
public virtual long Id
{
get { return id; }
set { id = value; }
}
public virtual int VersionNumber
{
get { return versionNumber; }
set { versionNumber = value; }
}
public virtual string Name
{
get { return name; }
set { name = value; }
}
}
NHibernate 映射文件
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="CodeProject.DAO" assembly=""CodeProject.DAO">
<class name="Person" table="Person">
<id name="Id">
<column name="Id" not-null="true"/>
<generator class="increment"/>
</id>
<version column="VersionNumber" name="VersionNumber" />
<property name="Name">
<column name="Name" length="16" not-null="true" />
</property>
</class>
</hibernate-mapping>
请注意,映射文件应具有.hbm.xml扩展名,并且应将其 Build Action 属性设置为 Embedded Resource。
BaseDAO 类
我们想要一个实现数据库基本功能的基类,如LoadALL
、SaveOrUpdate
等。我们定义一个接口并为我们的使用实现它
public interface IBaseDAO<EntityT, idT>
{
IList LoadAll();
EntityT LoadByID(idT id);
IList Load(string hsqlQuery, object[] values);
void Save(EntityT fine);
void SaveOrUpdate(EntityT fine);
NHibernate.ISessionFactory SessionFactory { set; }
}
public abstract class BaseDAO<EntityT, idT>: IBaseDAO<EntityT, idT>
{
protected HibernateTemplate hibernateTemplate;
public ISessionFactory SessionFactory
{
set
{
hibernateTemplate = new HibernateTemplate(value);
hibernateTemplate.TemplateFlushMode = TemplateFlushMode.Auto;
}
}
public BaseDAO()
{
}
public virtual EntityT LoadByID(idT id)
{
EntityT entity = (EntityT)hibernateTemplate.Load(typeof(EntityT), id);
return entity;
}
public virtual IList LoadAll()
{
return hibernateTemplate.LoadAll(typeof(EntityT));
}
public virtual IList Load(string hsqlQuery, object[] values)
{
return hibernateTemplate.Find(hsqlQuery, values);
}
public virtual void Save(EntityT fine)
{
hibernateTemplate.Save(fine);
}
public virtual void SaveOrUpdate(EntityT fine)
{
hibernateTemplate.SaveOrUpdate(fine);
}
}
PersonDAO 类
此类继承自BaseDAO
,负责Person
类的加载/保存操作
public interface IPersonDAO : IBaseDAO<Person, long>
{
}
public class PersonDAO : BaseDAO<Person, long>, IPersonDAO
{
}
请注意,这次我们将类定义为Object
类型的Person
类型,并将Id
类型定义为long
。
使用 PersonDAO 对象
现在我们在Default.aspx代码文件中添加一个名为personDAO
的新属性。请注意,您必须在此处使用DAO
类的接口。
IPersonDAO personDAO;
public IPersonDAO PersonDAO
{
get{return personDAO;}
set{personDAO=value;}
}
并在Page_Load
方法中添加以下行
Person p = new Person();
p.Name = "Maruf";
personDAO.Save(p);
Person p1 = personDAO.LoadByID(1);
您可以对您获得的Person
对象做任何您想做的事情。
NHibernate 的配置
现在我们需要在Web.Config文件中进行一些配置工作。
<?xml version="1.0"?>
<configuration>
<configSections>
<!-- Spring -->
<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>
</configSections>
<!-- Spring -->
<spring>
<parsers>
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data"/>
</parsers>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns=http://www.springframework.net
xmlns:db="http://www.springframework.net/database">
<db:provider id="DbProviderMySQL" provider="MySql"
connectionString="Server=localhost;....;"/>
<object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer,
Spring.Core">
<property name="ConfigSections" value="databaseSettings"/>
</object>
<object id="SessionFactory"
type="Spring.Data.NHibernate.LocalSessionFactoryObject,
Spring.Data.NHibernate12">
<property name="DbProvider" ref="DbProviderMySQL"/>
<property name="MappingAssemblies">
<list>
<value>CodeProject.DAO</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="hibernate.dialect"
value="NHibernate.Dialect.MySQLDialect"/>
<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.MySqlDataDriver"/>
</dictionary>
</property>
</object>
<object name="MyMathObj" type="Math, App_code" />
<object id="PersonDAO" type="CodeProject.DAO.PersonDAO, CodeProject.DAO">
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<!-- Pages -->
<object type="Default.aspx">
<property name="Message" value="Hello from Web.Config"/>
<property name="Math" ref="MyMathObj"/>
<property name="PersonDAO" ref="PersonDAO"/>
</object>
</objects>
</spring>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true"/>
<authentication mode="Windows"/>
<httpHandlers>
<!-- Spring Handler -->
<add verb="*" path="*.aspx"
type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
</httpHandlers>
<httpModules>
<add name="SpringModule"
type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
<!-- Required for managing NHibernate session between http requests-->
<add name="OpenSessionInView"
type="Spring.Data.NHibernate.Support.OpenSessionInViewModule,
Spring.Data.NHibernate12"/>
</httpModules>
</system.web>
</configuration>
声明式事务管理
它将事务管理排除在业务逻辑之外,并且在 Spring 中配置并不困难。我们希望我们的某些操作在事务中执行。我们不需要在代码中管理它。我们只需从Web.Config文件中配置它。假设我们希望PersonDAO
中的Save
、SaveOrUpdate
、Delete
、Query
等方法在原子数据库操作中执行,并在任何异常时回滚整个操作。我们在我们的config文件中创建PersonDAOTx
对象,并将其设置为Deafult.aspx页面的PersonDAO
属性。
<!-- TxManager -->
<object id="HibernateTransactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager,
Spring.Data.NHibernate12">
<property name="DbProvider" ref="DbProviderMySQL"/>
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<object id="PersonDAOTx"
type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>
<property name="Target" ref="PersonDAO"/>
<property name="TransactionAttributes">
<name-values>
<add key="Save*" value="PROPAGATION_REQUIRES_NEW"/>
<add key="SaveO*" value="PROPAGATION_REQUIRES_NEW"/>
<add key="Delete*" value="PROPAGATION_REQUIRED"/>
<add key="Update*" value="PROPAGATION_REQUIRED"/>
<add key="Query*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<!-- Pages -->
<object type="Default.aspx">
<property name="Message" value="Hello from Web.Config"/>
<property name="Math" ref="MyMathObj"/>
<property name="PersonDAO" ref="PersonDAOTx"/>
</object>
请注意,我们可以使用新事务或从调用者继承的事务。在使用继承事务时,如果调用者没有事务,则会自动创建一个新事务。
Web服务
Spring 引入了非常灵活的 Web 服务支持。它可以导出实现公共接口的任何类。根本不需要WebService
属性。让我们定义一个普通的接口并在一个普通的类中实现它
public interface IFirstService
{
string GetMessage();
}
public class FirstService : IFirstService
{
private string message;
public string Message
{
get { return message; }
set { message = value; }
}
public string GetMessage()
{
return message;
}
}
就是这样。我们现在可以通过在Web.Config文件中添加几行来导出此类。我们也可以从web.config注入它的依赖项(Message
属性)。请注意,用于处理handle.asmx页面的新httpHandlers
条目。
<object id="FirstServiceImpl" type="CodeProject.DAO.FirstService, CodeProject.DAO">
<property name="Message" value="Test Message" />
</object>
<!--Web Services-->
<object id="FirstService" type="Spring.Web.Services.WebServiceExporter, Spring.Web">
<property name="TargetName" value="FirstServiceImpl"/>
<property name="Namespace" value="http://myCompany/services"/>
<property name="Description" value="My First web service"/>
</object>
<system.web>
<httpHandlers>
<!-- Spring -->
<add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory,
Spring.Web"/>
<add verb="*" path="*.asmx" type="Spring.Web.Services.WebServiceHandlerFactory,
Spring.Web"/>
</httpHandlers>
</system.web>
就是这样。我们可以在/FirstService.asmx路径下访问该服务。
至此,我们可以创建 ASPX 页面,无需[WebService]
属性即可从几乎任何类创建 Web 服务,从配置文件注入依赖项——使应用程序高度可配置,处理数据库,并完全将事务管理与业务逻辑分开。我希望这将有助于快速入门使用 Spring.NET 并开发可扩展的应用程序。对于初学者来说,当您第一次使用 Spring.NET 时,您会惊讶于它通过减少大部分冗余工作来提供的帮助。请原谅语言 - 我的第一语言是孟加拉语。我很高兴收到您的来信。