用户实体类User
数据操作类UserDao。实现AdoDaoSupport接口。
SQL资源文件CommandSQL.resx
逻辑功能借口类 IGeneralService。
逻辑功能类 GeneralService,实现IUserService接口。
?
InterceptorMethod,???????? 实现IMethodInterceptor接口,????????? 用于在方法执行前后,附加功能。
InterceptorThrow,?????????? 实现IThrowsAdvice接口,????????????????? 用于异常处理。
InterceptorTransaction,? 实现IAfterReturningAdvice接口,????? ?用于事物处理。
GeneralAttribute继承System.Attribute。用户标记需要代码注入的方法。
?
编写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
    }
}
?
用来标记,是否需要检查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;
        }
    }
}
?
?
?
使用Spring提供的类TransactionAttribute
?
1,在方法上添加标记
标记为ReadOnly = true,只读事物
标记为TransactionPropagation.Required,写操作事物。
?
2,事物处理类
每个方法执行完毕后,都会执行InterceptorTransaction类中的AfterReturning方法,通过方法的一些条件(如是否有
TransactionAttribute标签,返回值等)判断是否是否回滚。
?
一些判断条件:
a)??????? 当attribute不为空
b)??????? 当attribute不是只读事物
c)??????? 当method.ReturnType类型是boo,值是false
d)??????? 当method.ReturnType类型是数值类型,值是-1
则表示操作失败,进行回滚。
?
?
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();
        }
    }
}
 
?
?
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
?
IGeneralService.cs基本功能接口类:
namespace Timecard.Services.Interfaces
{
    /// <summary>
    /// 基本操作接口
    /// </summary>
    public interface IGeneralService
    {
        Object Logon(string userNameString, string passwordString);
        Boolean Logout();
    }
}
?
服务层,登陆功能类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
    }
}
?
文件属性,生成操作:嵌入资源。不改此项会报错。
①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>
?
?
?