您的位置:首页 > 娱乐 > 八卦 > 网站建设网址_手机制作图片_信息流广告案例_seo快排

网站建设网址_手机制作图片_信息流广告案例_seo快排

2024/12/24 8:11:50 来源:https://blog.csdn.net/houbincarson/article/details/144021575  浏览:    关键词:网站建设网址_手机制作图片_信息流广告案例_seo快排
网站建设网址_手机制作图片_信息流广告案例_seo快排

前言

在 WebAPI 开发中,缓存是一种常用的优化手段。Redis 是广泛使用的缓存解决方案,但在某些场景下,我们可能不希望引入第三方依赖,而是希望使用轻量级的方式实现一个支持持久化的缓存组件,满足以下需求:

  • 缓存持久化:重启后缓存可以恢复。
  • 过期删除:支持设置缓存过期时间。
  • 基本操作:支持常见的增、删、查操作。

本文将指导如何设计和实现一个符合上述需求的缓存组件。

需求分析与设计思路

要实现这样的缓存组件,我们需要解决以下几个关键问题:

  1. 数据存储
    选择适合持久化的数据存储方式。SQLite 是一个很好的选择,因为它内置于 .NET,性能良好,且无需额外安装服务。

  2. 过期管理
    需要定期清理过期缓存,可以通过后台定时任务扫描和清理。

  3. 高效的操作接口
    提供易用的 SetGetRemove 等接口,并封装为服务供 API 使用。

实现步骤

1. 定义缓存模型

定义缓存的基本结构,包含键、值、过期时间等信息。

public class CacheItem
{public string Key { get; set; } = null!;public string Value { get; set; } = null!;public DateTime Expiration { get; set; }
}

2. 创建 SQLite 数据存储

在项目中配置 SQLite 数据库,用于存储缓存数据。

配置 SQLite 数据库
 <Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.11" /><PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" /><PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" /><PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" /><PackageReference Include="SQLitePCLRaw.core" Version="2.1.10" /><PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.10" /><PackageReference Include="SQLitePCLRaw.provider.e_sqlite3" Version="2.1.10" /></ItemGroup></Project>
初始化数据库

创建一个帮助类用于初始化和操作 SQLite 数据库。

using Microsoft.Data.Sqlite;
using SQLitePCL;namespace SqliteCache
{public class CacheDbContext{private readonly string _connectionString = "Data Source=cache.db";public CacheDbContext(){Batteries.Init();using var connection = new SqliteConnection(_connectionString);connection.Open();var command = connection.CreateCommand();command.CommandText = @"CREATE TABLE IF NOT EXISTS Cache (Key TEXT PRIMARY KEY,Value TEXT NOT NULL,Expiration TEXT NOT NULL);";command.ExecuteNonQuery();}public void AddOrUpdate(CacheItem item){using var connection = new SqliteConnection(_connectionString);connection.Open();var command = connection.CreateCommand();command.CommandText = @"INSERT INTO Cache (Key, Value, Expiration)VALUES (@Key, @Value, @Expiration)ON CONFLICT(Key) DO UPDATE SETValue = excluded.Value,Expiration = excluded.Expiration;";command.Parameters.AddWithValue("@Key", item.Key);command.Parameters.AddWithValue("@Value", item.Value);command.Parameters.AddWithValue("@Expiration", item.Expiration.ToString("o"));command.ExecuteNonQuery();}public CacheItem? Get(string key){using var connection = new SqliteConnection(_connectionString);connection.Open();var command = connection.CreateCommand();command.CommandText = "SELECT Key, Value, Expiration FROM Cache WHERE Key = @Key";command.Parameters.AddWithValue("@Key", key);using var reader = command.ExecuteReader();if (reader.Read()){return new CacheItem{Key = reader.GetString(0),Value = reader.GetString(1),Expiration = DateTime.Parse(reader.GetString(2))};}return null;}public void Remove(string key){using var connection = new SqliteConnection(_connectionString);connection.Open();var command = connection.CreateCommand();command.CommandText = "DELETE FROM Cache WHERE Key = @Key";command.Parameters.AddWithValue("@Key", key);command.ExecuteNonQuery();}public void ClearExpired(){using var connection = new SqliteConnection(_connectionString);connection.Open();var command = connection.CreateCommand();command.CommandText = "DELETE FROM Cache WHERE Expiration < @Now";command.Parameters.AddWithValue("@Now", DateTime.UtcNow.ToString("o"));command.ExecuteNonQuery();}}
}

3. 创建缓存服务

封装数据库操作,提供易用的缓存接口。

namespace SqliteCache
{public class PersistentCacheService{private readonly CacheDbContext _dbContext;public PersistentCacheService(){_dbContext = new CacheDbContext();}public void Set(string key, string value, TimeSpan expiration){var cacheItem = new CacheItem{Key = key,Value = value,Expiration = DateTime.UtcNow.Add(expiration)};_dbContext.AddOrUpdate(cacheItem);}public string? Get(string key){var item = _dbContext.Get(key);if (item == null || item.Expiration <= DateTime.UtcNow){_dbContext.Remove(key); // 自动删除过期项return null;}return item.Value;}public void Remove(string key){_dbContext.Remove(key);}}
}

4. 定期清理过期缓存

利用 ASP.NET Core 的后台任务机制清理过期缓存。

配置后台服务
using Microsoft.Extensions.Hosting;namespace SqliteCache
{public class CacheCleanupService : BackgroundService{private readonly CacheDbContext _dbContext = new();protected override async Task ExecuteAsync(CancellationToken stoppingToken){while (!stoppingToken.IsCancellationRequested){_dbContext.ClearExpired();await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);}}}
}
注册服务

SqliteCacheServiceCollectionExtensions.cs 中注册缓存服务和后台任务。

using SqliteCache;
namespace Microsoft.Extensions.DependencyInjection
{public static class SqliteCacheServiceCollectionExtensions{public static IServiceCollection AddSqliteCache(this IServiceCollection services){services.AddSingleton<PersistentCacheService>();services.AddHostedService<CacheCleanupService>();return services;}}
}

5. 使用缓存服务

新增一个asp.net core webapi项目 CacheProject,添加项目引用SqliteCache。在Main函数中添加服务引用。

namespace CacheProject
{public class Program{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);builder.Services.AddControllers();builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();//引入Sqlitecache缓存组件builder.Services.AddSqliteCache();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();app.Run();}}
}

在控制器中注入并使用缓存服务。

[ApiController]
[Route("api/[controller]")]
public class CacheController : ControllerBase
{private readonly PersistentCacheService _cacheService;public CacheController(PersistentCacheService cacheService){_cacheService = cacheService;}[HttpPost("set")]public IActionResult Set(string key, string value, int expirationMinutes){_cacheService.Set(key, value, TimeSpan.FromMinutes(expirationMinutes));return Ok("Cached successfully.");}[HttpGet("get")]public IActionResult Get(string key){var value = _cacheService.Get(key);if (value == null)return NotFound("Key not found or expired.");return Ok(value);}[HttpDelete("remove")]public IActionResult Remove(string key){_cacheService.Remove(key);return Ok("Removed successfully.");}
}

6.运行

启动WebApi项目

info: Microsoft.Hosting.Lifetime[14]Now listening on: https://localhost:7193
info: Microsoft.Hosting.Lifetime[14]Now listening on: http://localhost:5217
info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]Content root path: E:\F\Projects\CSharp\CacheProject\CacheProject
  1. 浏览器查看
    在这里插入图片描述
  2. 写入缓存
    在这里插入图片描述
  3. 读缓存和重启程序
    在这里插入图片描述
  4. 缓存已过期
    在这里插入图片描述

总结

本文展示了如何在 ASP.NET Core WebAPI 中,使用 SQLite 构建一个支持持久化和过期管理的缓存组件。通过以上步骤,我们实现了一个轻量级、易扩展的缓存系统,无需引入 Redis 等第三方工具,同时满足了性能和持久化的需求。

扩展思路

  • 使用 JSON 或 Protobuf 对值进行序列化,支持更复杂的数据类型。
  • 提供缓存命中率统计等高级功能。
  • 增加分布式缓存支持。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com