Spring.net + FluorineFx 项目搭建 之 二、后台功能编写

二、C#功能编写(模拟用户登陆功能)

2.1 需要编写的类

2.1.1需要编写的类文件列表为

用户实体类User
数据操作类UserDao。实现AdoDaoSupport接口。
SQL资源文件CommandSQL.resx
逻辑功能借口类 IGeneralService。
逻辑功能类 GeneralService,实现IUserService接口。

 

2.1.2三种代码注入类

InterceptorMethod,         实现IMethodInterceptor接口,          用于在方法执行前后,附加功能。
InterceptorThrow,           实现IThrowsAdvice接口,                  用于异常处理。
InterceptorTransaction,  实现IAfterReturningAdvice接口,       用于事物处理。


2.1.3一个标签类

GeneralAttribute继承System.Attribute。用户标记需要代码注入的方法。

 

2.2具体类的实现

2.2.1代码注入类写法

编写InterceptorMethod类,继承Attribute接口。可以在这个类中声明一些常量来标识,通过[InterceptorMethod (RequireUserLogon=true)] 来初始化标识。

使用时,在方法前添加标记[InterceptorMethod]
有四种代码注入形式:

 

接口名

注入方式

需要实现的方法

IMethodInterceptor

头尾注入

Invoke

IAfterReturningAdvice

结尾注入

AfterReturning

IThrowsAdvice

抛异常注入

AfterThrowing(不是接口方法)

IMethodBeforeAdvice

开始注入

 

 

下面写出三种常用代码注入。
⑴ InterceptorMethod.cs
执行方法前注入,一般用于方法执行前进行检查Session和记录日志等。

 

namespace Li.Aspects
{
    /// <summary>
    /// 代码注入,前后型
    /// </summary>
    public class InterceptorMethod : IMethodInterceptor
    {
        #region IMethodInterceptor 成员

        public object Invoke(IMethodInvocation invocation)
        {
            //得到当前实例化的ServiceMethodAttribute类的对象
            var attribute = (invocation.Method.GetCustomAttributes(typeof(GeneralAttribute), false).FirstOrDefault() as GeneralAttribute);

            User currentUser = (HttpContext.Current.Session["User"] as User);
            if (attribute != null && attribute.RequireUserLogon == true && currentUser == null)
            {
                throw new SessionTimeoutException();
            }
            return invocation.Proceed();
        }

        #endregion
    }
}

 

 

⑵ InterceptorThrow.cs,用于处理程序中的异常。

namespace Li.Aspects
{
    public class InterceptorThrow : IThrowsAdvice
    {
        public void AfterThrowing(MethodInfo method, object[] args, object target, Exception exception)
        {
            if (exception != null)
            {
                throw exception;
            }
        }
    }
}

 

 

 

⑶ InterceptorTransaction.cs,用于事务处理。

 

namespace Li.Aspects
{
    /// <summary>
    /// 方法后注入,用于进行事物管理
    /// </summary>
    public class InterceptorTransaction : IAfterReturningAdvice
    {
        #region IAfterReturningAdvice 成员

        public void AfterReturning(object returnValue, System.Reflection.MethodInfo method, object[] args, object target)
        {
            var attribute = (method.GetCustomAttributes(typeof(TransactionAttribute), false).FirstOrDefault() as TransactionAttribute);
            if (attribute != null && attribute.ReadOnly == false && 
                (method.ReturnType == typeof(bool) && bool.Equals(returnValue, false) || method.ReturnType == typeof(decimal) && decimal.Equals(returnValue, -1) || method.ReturnType == typeof(int) && int.Equals(returnValue, -1)))
            {
                TransactionInterceptor.CurrentTransactionStatus.SetRollbackOnly();
            }
        }

        #endregion
    }
}

 


2.2.2 普通代码注入标签类

用来标记,是否需要检查session。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Li.Attributes
{
    /// <summary>
    /// 标记类,用于标记代码注入
    /// </summary>
    public class GeneralAttribute : Attribute
    {
        public GeneralAttribute()
        {
            RequireUserLogon = true;
        }
        public Boolean RequireUserLogon
        {
            set;
            get;
        }
    }
}

 

 

 

2.2.3 事物处理标签的使用

使用Spring提供的类TransactionAttribute

 

1,在方法上添加标记

标记为ReadOnly = true,只读事物
标记为TransactionPropagation.Required,写操作事物。

 

2,事物处理类

每个方法执行完毕后,都会执行InterceptorTransaction类中的AfterReturning方法,通过方法的一些条件(如是否有

TransactionAttribute标签,返回值等)判断是否是否回滚。

 

一些判断条件:
a)        当attribute不为空
b)        当attribute不是只读事物
c)        当method.ReturnType类型是boo,值是false
d)        当method.ReturnType类型是数值类型,值是-1
则表示操作失败,进行回滚。

 

2.2.4 数据库调用功能(UserDao.cs)

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spring.Data.Generic;
using Timecard.Data.Domain;
using System.Data;
using Oracle.DataAccess.Client;
using Timecard.Data.Resources;

namespace Timecard.Data.Access
{
    /// <summary>
    /// 用户,数据操作类
    /// </summary>
    class UserDao : AdoDaoSupport
    {
        #region 构造方法
        public UserDao()
        {
        }
        #endregion

        /// <summary>
        /// 根据用户名,得到用户对象
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public User GetUserForUserName(string userName)
        {
            DataTable dataTable = AdoTemplate.Execute<DataTable>
                (
                    delegate(IDbDataAdapter dataAdapter)
                    {
                        if (dataAdapter is OracleDataAdapter)
                        {
                            OracleCommand commandToUse = (dataAdapter.SelectCommand as OracleCommand);
                            commandToUse.CommandText = CommandSQL.GetUserForUserName;
                            commandToUse.BindByName = true;

                            commandToUse.Parameters.Add(":USER_NAME", OracleDbType.NVarchar2, ParameterDirection.Input).Value = userName;

                            DataSet dataSet = new DataSet();
                            dataAdapter.Fill(dataSet);
                            return dataSet.Tables[0];
                        }
                        else
                        {
                            throw new Exception("Dao内部出现错误");
                        }
                    }
                );

            return (from dataRow in dataTable.AsEnumerable()
                    select new User
                    {
                        UserKey = dataRow.Field<decimal?>("USER_KEY"),
                        UserName = dataRow.Field<string>("USER_NAME"),
                        Password = dataRow.Field<string>("PASSWORD"),
                        RoleKey = dataRow.Field<decimal>("ROLE_KEY"),
                        Person = new Person
                        {
                            PersonKey = dataRow.Field<decimal?>("PERSON_KEY"),
                            PersonName = dataRow.Field<string>("PERSON_NAME").toNullString(),
                            PersonState = dataRow.Field<decimal?>("PERSON_STATE"),
                            PersonNickname = dataRow.Field<string>("PERSON_NICKNAME").toNullString(),
                            PersonPhoto = dataRow.Field<byte[]>("PERSON_PHOTO").Base64Encode(),
                            UnitKey = dataRow.Field<decimal?>("UNIT_KEY")
                            
                        }

                    }).FirstOrDefault();

        }
    }
}
 

 

 

2.2.5 SQL资源文件(CommandSQL.resx)

GetUserForUserName的SQL写法:

 

/* Formatted on 2010-5-27 9:24:29 (QP5 v5.114.809.3010) */
SELECT   U.USER_KEY,
         U.PERSON_KEY,
         U.USER_NAME,
         U.PASSWORD,
         U.ROLE_KEY,
         P.PERSON_NAME,
         P.PERSON_STATE,
         P.PERSON_NICKNAME,
         P.PERSON_PHOTO,
         P.UNIT_KEY
  FROM      UIMS.USER_TBL U
         LEFT JOIN
            UIMS.PERSON_TBL P
         ON U.PERSON_KEY = P.PERSON_KEY
 WHERE   U.USER_NAME = :USER_NAME

 

2.2.6 功能接口

IGeneralService.cs基本功能接口类:

namespace Timecard.Services.Interfaces
{
    /// <summary>
    /// 基本操作接口
    /// </summary>
    public interface IGeneralService
    {
        Object Logon(string userNameString, string passwordString);
        Boolean Logout();
    }
}

 

2.2.7 Service层功能实现类

服务层,登陆功能类GeneralService.cs:

namespace Timecard.Services
{
    class GeneralService : IGeneralService
    {
        private UserDao userDao;
        private PersonDao personDao;
        public string HashInstance{ get;set;}

        #region 构造方法     
        public GeneralService(UserDao userDao, PersonDao personDao)
        {
            this.userDao = userDao;
            this.personDao = personDao;
        }
        #endregion

        #region IGeneralService 成员

        /// <summary>
        /// 登录方法
        /// </summary>
        /// <param name="userNameString"></param>
        /// <param name="passwordString"></param>
        /// <returns></returns>
        [ServiceMethodAttribute(RequireUserLogon = false), TransactionAttribute(ReadOnly = true)]
        public Object Logon(string userNameString, string passwordString)
        {
            try
            {
                string userName = userNameString.TrimOrNull();
                User user = null;
                user = userDao.GetUserForUserName(userName);
                if (user == null)
                {
                    throw new NotHasUserException();
                }
                if (!Cryptographer.CompareHash(HashInstance, passwordString, user.Password))
                {
                    throw new InvalidPasswordException();
                }
                else
                {
                    HttpContext.Current.Session.Add("User", user);
                    return user;
                }
            }
            catch
            {
                throw new InvalidPasswordException();
            }
           
        }

        /// <summary>
        /// 注销
        /// </summary>
        [ServiceMethodAttribute(RequireUserLogon=false), TransactionAttribute(ReadOnly = true)]
        public Boolean Logout()
        {
            HttpContext.Current.Session.Clear();
            return true;
        }
        #endregion
    }
}

 

2.3将新加的类添加的对应的配置文件中

文件属性,生成操作:嵌入资源。不改此项会报错。
①Service类库配置文件

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
 
  <object id="generalService" type="Timecard.Services.GeneralService, Timecard.Services">
    <constructor-arg ref="personDao" />
    <constructor-arg ref="userDao" />
    <property name="HashInstance" value="HashProvider" />
  </object>

</objects>

  

 

②DataAccess类库配置文件

<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" xmlns:db="http://www.springframework.net/database">
  <object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
    <property name="ConfigSections" value="dbSettings" />
  </object>

  <db:provider id="dbProvider" provider="Oracle.DataAccess.Client" connectionString="DATA SOURCE=${db.source};PERSIST SECURITY INFO=True;USER ID=${db.user};PASSWORD=${db.password};MAX POOL SIZE=100" />

  <object id="adoTemplate" type="Spring.Data.Generic.AdoTemplate, Spring.Data">
    <property name="DbProvider" ref="dbProvider" />
    <property name="DataReaderWrapperType" value="Spring.Data.Support.NullMappingDataReader, Spring.Data" />
  </object>

  <object id="transactionManager" type="Spring.Data.Core.AdoPlatformTransactionManager, Spring.Data">
    <property name="DbProvider" ref="dbProvider" />
  </object>

  <object id="userDao" type="Timecard.Data.Access.UserDao, Timecard.DataAccess">
    <property name="AdoTemplate" ref="adoTemplate" />
  </object>
  
</objects>

 

 

 

你可能感兴趣的:(spring,oracle,.net,项目管理,LINQ)