用户实体类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>
?
?
?