前言

Asp.net Core 改变了之前的封闭,现在开源且开放,下面我们来用Redis存储Session来做一个简单的测试,或者叫做中间件(middleware)。

对于Session来说褒贬不一,很多人直接说不要用,也有很多人在用,这个也没有绝对的这义,个人认为只要不影什么且又可以方便实现的东西是可以用的,现在不对可不可用做表态,我们只关心实现。

类库引用

这个相对于之前的.net是方便了不少,需要在project.json中的dependencies节点中添加如下内容:

  "StackExchange.Redis": "1.1.604-alpha",
  "Microsoft.AspNetCore.Session": "1.1.0-alpha1-21694"

Redis实现

这里并非我实现,而是借用不知道为什么之前还有这个类库,而现在NUGET止没有了,为了不影响日后升级我的命名空间也用 Microsoft.Extensions.Caching.Redis

可以看到微软这里有四个类,其实我们只需要三个,第四个拿过来反而会出错:

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using StackExchange.Redis;

namespace Microsoft.Extensions.Caching.Redis
{
  public class RedisCache : IDistributedCache, IDisposable
  {
    // 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)
    {
      if (optionsAccessor == null)
      {
        throw new ArgumentNullException(nameof(optionsAccessor));
      }

      _options = optionsAccessor.Value;

      // This allows partitioning a single backend cache for use with multiple apps/services.
      _instance = _options.InstanceName "The absolute expiration value must be in the future.");
      }
      var absoluteExpiration = options.AbsoluteExpiration;
      if (options.AbsoluteExpirationRelativeToNow.HasValue)
      {
        absoluteExpiration = creationTime + options.AbsoluteExpirationRelativeToNow;
      }

      return absoluteExpiration;
    }

    public void Dispose()
    {
      if (_connection != null)
      {
        _connection.Close();
      }
    }
  }
}

using Microsoft.Extensions.Options;

namespace Microsoft.Extensions.Caching.Redis
{
  /// <summary>
  /// Configuration options for <see cref="RedisCache"/>.
  /// </summary>
  public class RedisCacheOptions : IOptions<RedisCacheOptions>
  {
    /// <summary>
    /// The configuration used to connect to Redis.
    /// </summary>
    public string Configuration { get; set; }

    /// <summary>
    /// The Redis instance name.
    /// </summary>
    public string InstanceName { get; set; }

    RedisCacheOptions IOptions<RedisCacheOptions>.Value
    {
      get { return this; }
    }
  }
}

using System.Threading.Tasks;
using StackExchange.Redis;

namespace Microsoft.Extensions.Caching.Redis
{
  internal static class RedisExtensions
  {
    private const string HmGetScript = (@"return redis.call('HMGET', KEYS[1], unpack(ARGV))");

    internal static RedisValue[] HashMemberGet(this IDatabase cache, string key, params string[] members)
    {
      var result = cache.ScriptEvaluate(
        HmGetScript,
        new RedisKey[] { key },
        GetRedisMembers(members));

      // TODO: Error checking"htmlcode">
services.AddSingleton<IDistributedCache>(
        serviceProvider =>
          new RedisCache(new RedisCacheOptions
          {
            Configuration = "192.168.178.141:6379",
            InstanceName = "Sample:"
          }));
      services.AddSession();

在Startup中Configure增加

app.UseSession(new SessionOptions() { IdleTimeout = TimeSpan.FromMinutes(30) });

到此我们的配置完毕,可以测试一下是否写到了Redis中

验证结果

在Mvc项目中,我们来实现如下代码

if (string.IsNullOrEmpty(HttpContext.Session.GetString("D")))
      {
        var d = DateTime.Now.ToString();
        HttpContext.Session.SetString("D", d);
        HttpContext.Response.ContentType = "text/plain";
        await HttpContext.Response.WriteAsync("Hello First timer///" + d);
      }
      else
      {
        HttpContext.Response.ContentType = "text/plain";
        await HttpContext.Response.WriteAsync("Hello old timer///" + HttpContext.Session.GetString("D"));
      }

运行我们发现第一次出现了Hello First timer字样,刷新后出现了Hello old timer字样,证明Session成功,再查看一下Redis看一下,有值了,这样一个分布式的Session就成功实现了。

对于上面的实例我把源码放在了:demo下载

Tianwei.Microsoft.Extensions.Caching.Redis ,只是ID加了Tianwei 空间名还是Microsoft.Extensions.Caching.Redis

从上面的实例我们发现微软这次是真的开放了,这也意味着如果我们使用某些类不顺手或不合适时可以自已写自已扩展

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

标签:
asp.net,core,session, 使用redis存储session,asp.net,core,redis

免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
桃源资源网 Design By www.nqtax.com

评论“详解Asp.net Core 使用Redis存储Session”

暂无“详解Asp.net Core 使用Redis存储Session”评论...