1.如何获取redis管理的源码session
2.详解.NET Model ValidationAttributeç使ç¨
如何获取redis管理的session
0.什么是RedisRedis是一个开源的使用ANSI C语言编写、支持网络、源码可基于内存亦可持久化的源码日志型、Key-Value数据库,源码并提供多种语言的源码句子模板源码API---维基百科1.与其他用户状态保存方案比较一般开发中用户状态使用session或者cookie,两种方式各种利弊。源码爱站防洪源码Session:在InProc模式下容易丢失,源码并且引起并发问题。源码如果使用SQLServer或者SQLServer模式又消耗了性能Cookie则容易将一些用户信息暴露,源码加解密同样也消耗了性能。源码Redis采用这样的源码方案解决了几个问题,1.Redis存取速度快。源码2.用户数据不容易丢失。源码html首页界面源码3.用户多的源码情况下容易支持集群。4.能够查看在线用户。源码5.能够实现用户一处登录。(通过代码实现,html邮箱留言源码后续介绍)6.支持持久化。(当然可能没什么用)2.实现思路1.我们知道session其实是在cookie中保存了一个sessionid,用户每次访问都将sessionid发给服务器,服务器通过ID查找用户对应的html搜索页面源码状态数据。在这里我的处理方式也是在cookie中定义一个sessionid,程序需要取得用户状态时将sessionid做为key在Redis中查找。2.同时session支持用户在一定时间不访问将session回收。借用Redis中Keys支持过期时间的特性支持这个功能,但是在续期方面需要程序自行拦截请求调用这个方法(demo有例子)下面开始代码说明 3.Redis调用接口首先引用ServiceStack相关DLL。在web.config添加配置,这个配置用来设置Redis调用地址每台服务用,隔开。主机写在第一位 1 2 3 4 5 6 初始化配置static Managers() { string sessionRedis= ConfigurationManager.AppSettings["SessionRedis"]; string timeOut = ConfigurationManager.AppSettings["SessionRedisTimeOut"]; if (string.IsNullOrEmpty(sessionRedis)) { throw new Exception("web.config 缺少配置SessionRedis,每台Redis之间用,分割.第一个必须为主机"); } if (string.IsNullOrEmpty(timeOut)==false) { TimeOut = Convert.ToInt(timeOut); } var host = sessionRedis.Split(char.Parse(",")); var writeHost = new string[] { host[0] }; var readHosts = host.Skip(1).ToArray(); ClientManagers = new PooledRedisClientManager(writeHost, readHosts, new RedisClientManagerConfig { MaxWritePoolSize = writeReadCount,//“写”链接池链接数 MaxReadPoolSize = writeReadCount,//“读”链接池链接数 AutoStart = true }); }为了控制方便写了一个委托/// /// 写入 /// /// /// /// public F TryRedisWrite(Func doWrite) { PooledRedisClientManager prcm = new Managers().GetClientManagers(); IRedisClient client = null; try { using (client = prcm.GetClient()) { return doWrite(client); } } catch (RedisException) { throw new Exception("Redis写入异常.Host:" + client.Host + ",Port:" + client.Port); } finally { if (client != null) { client.Dispose(); } } } 一个调用的例子其他的具体看源码 /// /// 以Key/Value的形式存储对象到缓存中 /// /// 对象类别 /// 要写入的集合 public void KSet(Dictionary value) { Func fun = (IRedisClient client) => { client.SetAll(value); return true; }; TryRedisWrite(fun); }4.实现Session按上面说的给cookie写一个sessionid /// /// 用户状态管理 /// public class Session { /// /// 初始化 /// /// public Session(HttpContextBase _context) { var context = _context; var cookie = context.Request.Cookies.Get(SessionName); if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { SessionId = NewGuid(); context.Response.Cookies.Add(new HttpCookie(SessionName, SessionId)); context.Request.Cookies.Add(new HttpCookie(SessionName, SessionId)); } else { SessionId = cookie.Value; } } }去存取用户的方法 /// /// 获取当前用户信息 /// /// /// public object Get() where T:class,new() { return new RedisClient().KGet(SessionId); } /// /// 用户是否在线 /// /// public bool IsLogin() { return new RedisClient().KIsExist(SessionId); } /// /// 登录 /// /// /// public void Login(T obj) where T : class,new() { new RedisClient().KSet(SessionId, obj, new TimeSpan(0, Managers.TimeOut, 0)); }6.续期默认用户没访问超过分钟注销用户的登录状态,所以用户每次访问都要将用户的注销时间推迟分钟这需要调用Redis的续期方法 /// /// 延期 /// /// /// public void KSetEntryIn(string key, TimeSpan expiresTime) { Func fun = (IRedisClient client) => { client.ExpireEntryIn(key, expiresTime); return false; }; TryRedisWrite(fun); }封装以后/// /// 续期/// public void Postpone(){ new RedisClient().KSetEntryIn(SessionId, new TimeSpan(0, Managers.TimeOut, 0));}这里我利用了MVC3中的ActionFilter,拦截用户的所有请求namespace Test{ public class SessionFilterAttribute : ActionFilterAttribute { /// /// 每次请求都续期 /// /// public override void OnActionExecuting(ActionExecutingContext filterContext) { new Session(filterContext.HttpContext).Postpone(); } }}在Global.asax中要注册一下public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new SessionFilterAttribute()); } protected void Application_Start() { RegisterGlobalFilters(GlobalFilters.Filters); }5.调用方式为了方便调用借用4.0中的新特性,把Controller添加一个扩展属性 public static class ExtSessions{ public static Session SessionExt(this Controller controller) { return new Session(controller.HttpContext); }}调用方法 public class HomeController : Controller { public ActionResult Index() { this.SessionExt().IsLogin(); return View(); } }如何获取redis管理的session
详解.NET Model ValidationAttributeç使ç¨
ä¸ãç®ä»
ValidationAttribute éªè¯ç¹æ§ä¸è¬ç¨æ¥éªè¯æ°æ®çæ ¼å¼ï¼èå´ï¼æ¯å¦å¿ å¡«çï¼æ们éè¿å®çåç±»ç¹æ§ RangeãRequired çç¹æ§å¯ä»¥è½»æ¾å®ç°å¯¹æ°æ®çéªè¯ãä½æ¯å¯¹äºä¸äºç¹æ®éè¦çç¹æ§ï¼ç³»ç»èªå¸¦çç¹æ§å±éæ§å¾å¤§ï¼æ们ä¹å¯ä»¥èªå®ä¹æ©å±éè¦çç¹æ§ã ?
äºãASP.NET åºç¨ValidationAttribute åºç¨å¨ ASP.NET MVC ä¸æ¯å¸¸ç¨å¾ï¼ç¨äºå¯¹ HTPP Request åæ°å段å¾æ ¡éªï¼ä¸éè¿å¾ä¼è¿å æ示ç»è°ç¨æ¹ãæ¥ä¸éè¿ä¸ä¸ªç®åä¾åè¿è¡è¯´æä¸ä¸ï¼ä¾å使ç¨å¾æ¯ .NET Web API ã
2.1 Modelé¦å å®ä¹ä¸ä¸ª request model æ·»å ä¸äºå段ï¼å¦ Name æä¸ RequiredãMinLengthãMaxLength è¿æ ·çæ è®°è¿è¡éå¶
public?class?PersonalRequest{ public?int?Id?{ ?get;?set;?}[Required][MinLength(2),?MaxLength()]public?string?Name?{ ?get;?set;?}public?string?Sex?{ ?get;?set;?}[Required][MinLength(2),?MaxLength()]public?string?Address?{ ?get;?set;?}}2.2 Controllerå®ä¹å® request ?model åï¼å建ä¸ä¸ª ?API ï¼å°ä¸ä¸æ¥å®ä¹ç request model ä½ä¸ºåæ°ãæ¤æ¶å¨ request ?model å段ä¸æç ?RequiredãMinLengthãMaxLength æ è®°ï¼æ¯æ²¡æä»»ä½ä½ç¨çã
[HttpPost][Route("WebAPIApply")]public?IActionResult?WebAPIApply(PersonalRequest?request){ return?Ok();}2.4 Filter为äºè®© request ?model å段ä¸æç ?RequiredãMinLengthãMaxLength æ è®°çæï¼ MVC ä¸éè¦ä½¿ç¨å° Filter ã代ç å¦ä¸
public?class?ModelValidateFilter?:?IAsyncActionFilter{ public?async?Task?OnActionExecutionAsync(ActionExecutingContext?context,?ActionExecutionDelegate?next){ if?(!context.ModelState.IsValid){ var?allErrors?=?context.ModelState.Values.SelectMany(v?=>?v.Errors);var?message?=?string.Join("?|?",?allErrors.Select(e?=>?e.ErrorMessage));context.Result?=?new?JsonResult(new?{ ?results?=?allErrors?});}await?next();}}2.5 注åFilter å建å®æåï¼éè¦æ³¨åä¸ä¸ï¼è¿éæ们使ç¨å ¨å±æ¨¡å¼ãå¦ä¸
builder.Services.AddMvc(opt?=>{ opt.Filters.Add(new?ModelValidateFilter());});2.6 éªè¯ç¨åºå建å®æåï¼è°ç¨ API éªè¯ä¸ä¸ï¼å¦ä¸å¯¹ Name åå«èµå¼äº D Daã å¯ä»¥çå°å½æ¯ D çæ¶åï¼å段é¿åº¦ä¸º 1 ï¼filter 对 request ?model è¿è¡äºæ£ç¡®çæ ¡éª
ä¸ãç´æ¥éªè¯å®ä¾ç´æ¥éªè¯å®ä¾ï¼æ¯æå¯ä»¥å¯¹å®ä¹ model çå®ä¾ï¼èªå®ä¹ä»£ç 对é½è¿è¡æ ¡éªï¼è¿ç§ä½¿ç¨èµ·æ¥ç¸å¯¹çµæ´»ï¼ä½ä¹ä¸ç»å¸¸ä½¿ç¨ãæ¥ä¸éè¿ä¸ä¸ªç®åä¾åè¿è¡è¯´æä¸ä¸
3.1 Modelé¦å å®ä¹ä¸ä¸ª model æ·»å ä¸äºå段ï¼å¦ Name æä¸ RequiredãMinLengthãMaxLength è¿æ ·çæ è®°è¿è¡éå¶
public?class?Personal{ [Required]public?int?ID?{ ?get;?set;?}[Required][MinLength(2),?MaxLength(5)]public?string?Name?{ ?get;?set;?}}3.2 Validation Codeæ ¡éªä»£ç å¦ä¸ï¼å 对å®ä¹ç model è¿è¡äºå®ä¾åï¼ç¶åä½¿ç¨ Validator.TryValidateObject æ¹æ³è¿è¡æ ¡éªï¼å®é å·¥ä½ä¸éè¦èªå·±è¿è¡ä¸äºå°è£ ãå ³é®ä»£ç å¦ä¸ï¼
Personal?personal?=?new?Personal();//?personal.Name?=?"D";ValidationContext?validationContext?=?new?ValidationContext(personal);List<ValidationResult>?results?=?new?List<ValidationResult>();bool?isValid?=?Validator.TryValidateObject(personal,?validationContext,?results,?true);3.3 éªè¯ä»£ç åå®åï¼è°ç¨ API éªè¯ä¸ä¸ãé¦å ç´æ¥è°ç¨ï¼åºä¸ºä»£ç éé¢æ²¡æ对 Personal å®ä¾èµå¼ï¼æ£ç¡®çè¿è¡äº Required æ è®°çæ ¡éªå¯ä»¥ä¿®æ¹ä¸ä»£ç ?personal.Name = "Da"ï¼ç¶åå¯å¨ç¨åºï¼è°ç¨ä¸ä¸ API å¯ä»¥çå°æ ¡éªæ¯éè¿çå¯ä»¥ä¿®æ¹ä¸ä»£ç ?personal.Name = "D"ï¼ç¶åå¯å¨ç¨åºï¼è°ç¨ä¸ä¸ API å¯ä»¥çå°æ ¡éªæ¯ä¸éè¿çï¼å 为é¿åº¦ä¸º 1 没æ满足 MinLength(2)
åãèªå®ä¹ ValidationAttributeé¤äºå¯ä»¥ä½¿ç¨ Microsoft æä¾ç ValidationAttribute ï¼æ们è¿å¯ä»¥ä½¿ç¨èªå®ä¹ç ValidationAttribute ï¼å¾®è½¯è¿æ¹é¢æä¾äºå¯æ©å±æ§ãèªå®ä¹ç ValidationAttribute åªéç»§æ¿ ValidationAttributeï¼éå IsValid ãFormatErrorMessage å³å¯ã使ç¨æ¹é¢ä¸ Microsoft æä¾ç ValidationAttribute 使ç¨ä¸æ¨¡ä¸æ ·ãå¦ä¸ä»£ç
public?class?CanToIntAttribute?:?ValidationAttribute{ ///?<summary>///?IsValid?为?false?æ¶ï¼æ示å¾?error?ä¿¡æ¯///?</summary>///?<param?name="name"></param>///?<returns></returns>public?override?string?FormatErrorMessage(string?name){ return?$"{ name}?need?to?int";}///?<summary>///?éªè¯å½åå段å¾ç»æ///?</summary>///?<param?name="value"></param>///?<returns></returns>public?override?bool?IsValid(object?value){ int?num?=?0;return?int.TryParse(Convert.ToString(value),?out?num);}}public?class?PersonalRequest{ public?int?Id?{ ?get;?set;?}public?string?Name?{ ?get;?set;?}[CanToInt]public?string?Sex?{ ?get;?set;?}[Required][MinLength(2),?MaxLength()]public?string?Address?{ ?get;?set;?}}äºãæºç /post/