国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

解讀ASP.NET 5 & MVC6系列(8):Session與Caching

2019-11-17 02:06:36
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

解讀asp.net 5 & MVC6系列(8):session與Caching

2015-05-21 09:08 by 湯姆大叔, ... 閱讀, ... 評(píng)論, 收藏, 編輯

在之前的版本中,Session存在于System.Web中,新版ASP.NET 5中由于不在依賴于System.Web.dll庫(kù)了,所以相應(yīng)的,Session也就成了ASP.NET 5中一個(gè)可配置的模塊(middleware)了。

配置啟用Session

ASP.NET 5中的Session模塊存在于Microsoft.AspNet.Session類庫(kù)中,要啟用Session,首先需要在PRoject.json中的dependencies節(jié)點(diǎn)中添加如下內(nèi)容:

"Microsoft.AspNet.Session": "1.0.0-beta3"

然后在ConfigureServices中添加Session的引用(并進(jìn)行配置):

services.AddCaching();  // 這兩個(gè)必須同時(shí)添加,因?yàn)镾ession依賴于Cachingservices.AddSession();//services.ConfigureSession(null); 可以在這里配置,也可以再后面進(jìn)行配置

最后在Configure方法中,開(kāi)啟使用Session的模式,如果在上面已經(jīng)配置過(guò)了,則可以不再傳入配置信息,否則還是要像上面的配置信息一樣,傳入Session的配置信息,代碼如下:

app.UseInMemorySession(configure:s => { s.IdleTimeout = TimeSpan.FromMinutes(30); });//app.UseSession(o => { o.IdleTimeout = TimeSpan.FromSeconds(30); });//app.UseInMemorySession(null, null);   //開(kāi)啟內(nèi)存Session//app.UseDistributedSession(null, null);//開(kāi)啟分布式Session,也即持久化Session//app.UseDistributedSession(new RedisCache(new RedisCacheOptions() { Configuration = "localhost" }));

對(duì)于UseInMemorySession方法,接收2個(gè)可選參數(shù),分別是:IMemoryCache可用于修改Session數(shù)據(jù)的默認(rèn)保存地址;Action<SessionOptions>委托則可以讓你修改默認(rèn)選項(xiàng),比如Session cookie的路徑、默認(rèn)的過(guò)期時(shí)間等。本例中,我們修改默認(rèn)過(guò)期時(shí)間為30分鐘。

注意:該方法必須在app.UseMvc之前調(diào)用,否則在Mvc里獲取不到Session,而且會(huì)出錯(cuò)。

獲取和設(shè)置Session

獲取和設(shè)置Session對(duì)象,一般是在Controller的action里通過(guò)this.Context.Session來(lái)獲取的,其獲取的是一個(gè)基于接口ISessionCollection的實(shí)例。該接口可以通過(guò)索引、Set、TryGetValue等方法進(jìn)行Session值的獲取和設(shè)置,但我們發(fā)現(xiàn)在獲取和設(shè)置Session的時(shí)候,我們只能使用byte[]類型,而不能像之前版本的Session一樣可以設(shè)置任意類型的數(shù)據(jù)。原因是因?yàn)椋掳姹镜腟ession要支持在遠(yuǎn)程服務(wù)器上存儲(chǔ),就需要支持序列化,所以才強(qiáng)制要求保存為byte[]類型。所以我們?cè)诒4鍿ession的時(shí)候,需要將其轉(zhuǎn)換為byte[]才能進(jìn)行保存,并且獲取以后要再次將byte[]轉(zhuǎn)換為自己的原有的類型才行。這種形式太麻煩了,好在微軟在Microsoft.AspNet.Http命名空間(所屬Microsoft.AspNet.Http.Extensions.dll中)下,為我們添加了幾個(gè)擴(kuò)展方法,分別用于設(shè)置和保存byte[]類型、int類型、以及string類型,代碼如下:

public static byte[] Get(this ISessionCollection session, string key);public static int? GetInt(this ISessionCollection session, string key);public static string GetString(this ISessionCollection session, string key);public static void Set(this ISessionCollection session, string key, byte[] value);public static void SetInt(this ISessionCollection session, string key, int value);public static void SetString(this ISessionCollection session, string key, string value);

所以,在Controller里引用Microsoft.AspNet.Http命名空間以后,我們就可以通過(guò)如下代碼進(jìn)行Session的設(shè)置和獲取了:

Context.Session.SetString("Name", "Mike");Context.Session.SetInt("Age", 21);ViewBag.Name = Context.Session.GetString("Name");ViewBag.Age = Context.Session.GetInt("Age");

自定義類型的Session設(shè)置和獲取

前面我們說(shuō)了,要保存自定義類型的Session,需要將其類型轉(zhuǎn)換成byte[]數(shù)組才行,在本例中,我們對(duì)bool類型的Session數(shù)據(jù)進(jìn)行設(shè)置和獲取的代碼,示例如下:

public static class SessionExtensions{    public static bool? GetBoolean(this ISessionCollection session, string key)    {        var data = session.Get(key);        if (data == null)        {            return null;        }        return BitConverter.ToBoolean(data, 0);    }     public static void SetBoolean(this ISessionCollection session, string key, bool value)    {        session.Set(key, BitConverter.GetBytes(value));    }}

定義bool類型的擴(kuò)展方法以后,我們就可以像SetInt/GetInt那樣進(jìn)行使用了,示例如下:

Context.Session.SetBoolean("Liar", true);ViewBag.Liar = Context.Session.GetBoolean("Liar");

另外,ISessionCollection接口上還提供了Remove(string key)和Clear()兩個(gè)方法分別用于刪除某個(gè)Session值和清空所有的Session值的功能。但同時(shí)也需要注意,該接口并沒(méi)提供之前版本中的Abandon方法功能。

基于Redis的Session管理

使用分布式Session,其主要工作就是將Session保存的地方從原來(lái)的內(nèi)存換到分布式存儲(chǔ)上,本節(jié),我們以Redis存儲(chǔ)為例來(lái)講解分布式Session的處理。

先查看使用分布式Session的擴(kuò)展方法,示例如下,我們可以看到,其Session容器需要是一個(gè)支持IDistributedCache的接口示例。

public static IapplicationBuilder UseDistributedSession([NotNullAttribute]this IApplicationBuilder app, IDistributedCache cache, Action<SessionOptions> configure = null);

該接口是緩存Caching的通用接口,也就是說(shuō),只要我們實(shí)現(xiàn)了緩存接口,就可以將其用于Session的管理。進(jìn)一步查看該接口發(fā)現(xiàn),該接口中定義的Set方法還需要實(shí)現(xiàn)一個(gè)ICacheContext類型的緩存上下文(以便在調(diào)用的時(shí)候讓其它程序進(jìn)行委托調(diào)用),接口定義分別如下:

public interface IDistributedCache{    void Connect();    void Refresh(string key);    void Remove(string key);    Stream Set(string key, object state, Action<ICacheContext> create);    bool TryGetValue(string key, out Stream value);}public interface ICacheContext{    Stream Data { get; }    string Key { get; }    object State { get; }    void SetAbsoluteExpiration(TimeSpan relative);    void SetAbsoluteExpiration(DateTimeOffset absolute);    void SetSlidingExpiration(TimeSpan offset);}

接下來(lái),我們基于Redis來(lái)實(shí)現(xiàn)上述功能,創(chuàng)建RedisCache類,并繼承IDistributedCache,引用StackExchange.Redis程序集,然后實(shí)現(xiàn)IDistributedCache接口的所有方法和屬性,代碼如下:

using Microsoft.Framework.Cache.Distributed;using Microsoft.Framework.OptionsModel;using StackExchange.Redis;using System;using System.IO;namespace Microsoft.Framework.Caching.Redis{    public class RedisCache : IDistributedCache    {        // KEYS[1] = = key        // ARGV[1] = absolute-expiration - ticks as long (-1 for none)        // ARGV[2] = sliding-expiration - ticks as long (-1 for none)        // ARGV[3] = relative-expiration (long, in seconds, -1 for none) - Min(absolute-expiration - Now, sliding-expiration)        // ARGV[4] = data - byte[]        // this order should not change LUA script depends on it        private const string SetScript = (@"                redis.call('HMSET', KEYS[1], 'absexp', ARGV[1], 'sldexp', ARGV[2], 'data', ARGV[4])                if ARGV[3] ~= '-1' then                  redis.call('EXPIRE', KEYS[1], ARGV[3])                 end                return 1");        private const string AbsoluteExpirationKey = "absexp";        private const string SlidingExpirationKey = "sldexp";        private const string DataKey = "data";        private const long NotPresent = -1;        private ConnectionMultiplexer _connection;        private IDatabase _cache;        private readonly RedisCacheOptions _options;        private readonly string _instance;        public RedisCache(IOptions<RedisCacheOptions> optionsaccessor)        {            _options = optionsAccessor.Options;            // This allows partitioning a single backend cache for use with multiple apps/services.            _instance = _options.InstanceName ?? string.Empty;        }        public void Connect()        {            if (_connection == null)            {                _connection = ConnectionMultiplexer.Connect(_options.Configuration);                _cache = _connection.GetDatabase();            }        }        public Stream Set(string key, object state, Action<ICacheContext> create)        {            Connect();            var context = new CacheContext(key) { State = state };            create(context);            var value = context.GetBytes();            var result = _cache.ScriptEvaluate(SetScript, new RedisKey[] { _instance + key },                new RedisValue[]                {                    context.AbsoluteExpiration?.Ticks ?? NotPresent,                    context.SlidingExpiration?.Ticks ?? NotPresent,                    context.GetExpirationInSeconds() ?? NotPresent,                    value                });            // TODO: Error handling            return new MemoryStream(value, writable: false);        }        public bool TryGetValue(string key, out Stream value)        {            value = GetAndRefresh(key, getData: true);            return value != null;        }        public void Refresh(string key)        {
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 施秉县| 黑山县| 白山市| 张家口市| 灌云县| 平定县| 台南市| 临海市| 博白县| 南汇区| 鄢陵县| 繁昌县| 宽甸| 甘孜县| 饶河县| 靖安县| 陈巴尔虎旗| 延边| 遵义市| 綦江县| 和硕县| 乐都县| 宜春市| 阆中市| 卓资县| 宜昌市| 武山县| 原平市| 永丰县| 嘉鱼县| 洛宁县| 闵行区| 连云港市| 巴林左旗| 明光市| 习水县| 清涧县| 高密市| 慈利县| 英超| 蓬莱市|