// 在program.cs中加入这句,加入缓存支持
builder.Services.AddMemoryCache();
public class Book
{
public int Id { get; init; }
public string Title { get; init; }
public Book(int id, string title)
{
Id = id;
Title = title;
}
public override string ToString()
{
return $"book:{Id}, {Title}";
}
}
public class BookDbContext
{
public Task<Book?> GetBookByIdAsync(int id)
{
Book? book = null;
switch (id)
{
case 1:
book = new Book(1, "book1");
break;
case 2:
book = new Book(2, "book2");
break;
case 3:
book = new Book(3, "book3");
break;
}
return Task.FromResult(book);
}
}
[ApiController]
[Route("api/[controller]")]
public class CacheTestController : ControllerBase
{
private IMemoryCache MemoryCache { get; init; }
private ILogger<CacheTestController> Logger { get; set; }
public CacheTestController(IMemoryCache memoryCache, ILogger<CacheTestController> logger)
{
MemoryCache = memoryCache;
Logger = logger;
}
[HttpGet("book")]
public async Task<ActionResult<Book?>> GetBookById(int id)
{
Logger.LogInformation($"enter GetBookById, id={id}");
// 尽量使用GetOrCreateAsync,而不是Get/Set。
// 因为GetOrCreateAsync可以把null也作为缓存值,这样就可以避免缓存穿透。
Book? book = await MemoryCache.GetOrCreateAsync($"book_{id}", (e) =>
{
Logger.LogInformation($"not found in cache, search in BookDbContext.");
// 混用SlidingExpiration和AbsoluteExpirationRelativeToNow,这样滑动超时或绝对超时后,缓存都会失效,
e.SlidingExpiration = TimeSpan.FromSeconds(5);
// 使用随机数作为超时值,避免缓存雪崩
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Random.Shared.Next(10, 50));
return new BookDbContext().GetBookByIdAsync(id);
});
Logger.LogInformation($"GetOrCreateAsync returns {book}");
if (book == null)
return NotFound($"cannot find bood with id:{id}");
return book;
}
[ResponseCache(Duration = 10)] // 浏览器缓存支持,在响应头里加入cache-control: public,max-age=10
[HttpGet("Now")]
public DateTime Now()
{
return DateTime.Now;
}
}
---------------------------
知道的更多,不知道的也更多
---------------------------