还记得上面提到的问题吗?如何把用户的状态信息保存起来,共享给这三台服务器?下面通过代码,给大家介绍ASP.Net MVC 4中如何使用Memcached,开始吧!
项目结构:
项目中需要引用Memcached的dll,如下:
1、首先准备好工具类:
MemcacheHelper:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using Memcached.ClientLibrary; 6 7 namespace WebDemo.Models 8 { 9 public static class MemcacheHelper 10 { 11 private static MemcachedClient mc; 12 13 static MemcacheHelper() 14 { 15 //通过客户端来进行memcached的集群配置,在插入数据的时候,使用一致性哈希算法,将对应的value值存入Memcached 16 String[] serverlist = { "127.0.0.1:11211" }; 17 18 // 初始化Memcached的服务池 19 SockIOPool pool = SockIOPool.GetInstance("test"); 20 //设置服务器列表 21 pool.SetServers(serverlist); 22 //各服务器之间负载均衡的设置比例 23 pool.SetWeights(new int[] { 1 }); 24 pool.Initialize(); 25 //创建一个Memcached的客户端对象 26 mc = new MemcachedClient(); 27 mc.PoolName = "test"; 28 //是否启用压缩数据:如果启用了压缩,数据压缩长于门槛的数据将被储存在压缩的形式 29 mc.EnableCompression = false; 30 31 } 32 /// <summary> 33 /// 插入值 34 /// </summary> 35 /// <param name="key">建</param> 36 /// <param name="value">值</param> 37 /// <param name="expiry">过期时间</param> 38 /// <returns></returns> 39 public static bool Set(string key, object value,DateTime expiry){ 40 return mc.Set(key, value, expiry); 41 } 42 /// <summary> 43 /// 获取值 44 /// </summary> 45 /// <param name="key"></param> 46 /// <returns></returns> 47 public static object Get(string key) 48 { 49 return mc.Get(key); 50 } 51 } 52 }
BaseController:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using WebDemo.Models; namespace WebDemo.Controllers { public class BaseController : Controller { //用来保存当前的用户信息 public UserInfo LoginUser { get; set; } //通过过滤器来实现每个页面的检查 protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); //从cookie中获取咱们的 登录的sessionId string sessionId = Request["sessionId"]; //如果sessionid为空值,则跳转到登录页面 if (string.IsNullOrEmpty(sessionId)) { //return RedirectToAction("Login", "Logon"); Response.Redirect("/Logon/Index"); } object obj = MemcacheHelper.Get(sessionId); UserInfo user = obj as UserInfo; if (user == null) { Response.Redirect("/Logon/Index"); } LoginUser = user; //实现session的滑动机制 MemcacheHelper.Set(sessionId, user, DateTime.Now.AddMinutes(20)); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Memcached.ClientLibrary; namespace WebDemo.Controllers { public class MemcachedController : BaseController { // // GET: /Memcached/ public ActionResult Index() { //初始化memcached 服务器端集群列表。 String[] serverlist = { "127.0.0.1:11211"}; // initialize the pool for memcache servers SockIOPool pool = SockIOPool.GetInstance("test"); //设置怎么mem池连接点服务器端。 pool.SetServers(serverlist); pool.Initialize(); //创建了一个mem客户端的代理类。 var mc = new MemcachedClient(); mc.PoolName = "test"; mc.EnableCompression = false; //mc.Add("gz1", "我的女神宋智孝"); mc.Set("gz2", "hahaha", DateTime.Now.AddSeconds(15)); pool.Shutdown();//关闭连接池 return Content("ok"); } } }
2、models:
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web; namespace WebDemo.Models { public class SchoolDbContext :DbContext { //使用EF的code-first,如果数据库中没有数据名字为MySqlDemo,则调用CreateIfNotExists方法会创建数据库 public SchoolDbContext() : base("name=MySqlDemo") { this.Database.CreateIfNotExists(); } public virtual DbSet<Student> Student { get; set; } public virtual DbSet<UserInfo> UserInfo { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace WebDemo.Models { [Serializable] public class Student { [StringLength(32)] public virtual string SName { get; set; } [StringLength(32)] public virtual string Address { get; set; } [Key] public virtual int Id { get; set; } } }
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Web; namespace WebDemo.Models { [Serializable] public class UserInfo { public string UName { get; set; } [Required] [MaxLength(32)] public string UPwd { get; set; } [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } } }
3、接下来的代码是使用分布式缓存中最关键的一点:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using WebDemo.Models; namespace WebDemo.Controllers { public class LogonController : Controller { // // GET: /Logon/ public ActionResult Index() { return View(); } public ActionResult Login(UserInfo user) { //创建一个DbContext对象,这样写不是很合理,先留个问题。(使用EF的code-first时需要注意的点) SchoolDbContext dbContext =new SchoolDbContext(); var loginUser = dbContext.UserInfo.Where(u => u.UName.Equals(user.UName) && u.UPwd.Equals(user.UPwd)).FirstOrDefault(); if (loginUser == null) { return Content("用户名密码错误!"); } else { Guid sessionId = Guid.NewGuid();//申请了一个模拟的GUID:SessionId //把sessionid写到客户端浏览器里面去了(一定要把sessionid写到客户端,这样用户在访问其他web资源的时候,就会把cookie中的信息传给服务器,然后通过sessionid的key到Memcached中去取对应的值) Response.Cookies["sessionId"].Value = sessionId.ToString(); //再把用户的信息插入到Memcached中 MemcacheHelper.Set(sessionId.ToString(), loginUser, DateTime.Now.AddMinutes(20)); return Content("ok"); } } public ActionResult ValidateCode() { ValidateCodeHelper helper =new ValidateCodeHelper(); string strCode = helper.CreateValidateCode(4); Session["validateCode"] = strCode; var byteData = helper.CreateValidateGraphic(strCode); return File(byteData, "image/jpeg"); } } }