还记得上面提到的问题吗?如何把用户的状态信息保存起来,共享给这三台服务器?下面通过代码,给大家介绍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");
        }
    }
}
复制代码