新建一个空的Web项目,命名CachingDemo
然后添加三个Nuget安装包
- Nancy
- Nancy.Hosting.Aspnet
- Nancy.ViewsEngines.Razor
然后往项目里面添加Models,Module,Views三个文件夹
再往Models文件夹里面添加CachingExtensions文件夹
然后往CachingExtensions文件夹里面添加ContextExtensions类
public static class ContextExtensions { public const string OUTPUT_CACHE_TIME_KEY = "OUTPUT_CACHE_TIME"; //启用此路由的输出缓存 public static void EnableOutputCache(this NancyContext context,int seconds) { context.Items[OUTPUT_CACHE_TIME_KEY]=seconds; } //禁用此路由的输出缓存 public static void DisableOutputCache(this NancyContext context) { context.Items.Remove(OUTPUT_CACHE_TIME_KEY); } }
再往Models文件夹里面添加CachedResponse类
//在缓存的响应中封装常规响应 //缓存的响应调用旧的响应并将其存储为字符串。 //显然, 这只适用于基于 ascii 文本的响应, 所以不要使用此 //在实际应用中:-) private readonly Response response; public CachedResponse(Response response) { this.response = response; this.ContentType = response.ContentType; this.Headers = response.Headers; this.Contents = this.GetContents(); } public override Task PreExecute(NancyContext context) { //return base.PreExecute(context); return this.response.PreExecute(context); } private Action<Stream> GetContents() { return stream => { using (var memoryStream = new MemoryStream()) { this.response.Contents.Invoke(memoryStream); var contents = Encoding.ASCII.GetString(memoryStream.GetBuffer()); var writer = new StreamWriter(stream) { AutoFlush = true }; writer.Write(contents); } }; }
然后往Module文件夹里面添加MainModule类
public MainModule() { Get("/",Lexan=> { return View["index.cshtml",DateTime.Now.ToString()]; }); Get("/cached",Lexan=> { this.Context.EnableOutputCache(30); return View["Payload.cshtml",DateTime.Now.ToString()]; }); Get("/uncached",Lexan=> { this.Context.DisableOutputCache(); return View["Payload.cshtml",DateTime.Now.ToString()]; }); }
继续往根目录添加Bootstrapper类
private const int CACHE_SECONDS = 30; private readonly Dictionary<string, Tuple<DateTime, Response, int>> cachedResponses = new Dictionary<string, Tuple<DateTime, Response, int>>(); protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) { base.ApplicationStartup(container, pipelines); pipelines.BeforeRequest += CheckCache; pipelines.AfterRequest += SetCache; } //检查我们是否有缓存条目-如果我们做了, 看看它是否已经过期, //如果没有返回, 否则返回 null; public Response CheckCache(NancyContext context) { Tuple<DateTime, Response, int> cacheEntry; if (this.cachedResponses.TryGetValue(context.Request.Path,out cacheEntry)) { if (cacheEntry.Item1.AddSeconds(cacheEntry.Item3)>DateTime.Now) { return cacheEntry.Item2; } } return null; } //如果需要, 将当前响应添加到缓存中 //仅按路径存储, 并将响应存储在字典中。 //不要将此作为实际缓存:-) public void SetCache(NancyContext contexts) { if (contexts.Response.StatusCode!=HttpStatusCode.OK) { return; } object cacheSecondsObject; if (!contexts.Items.TryGetValue(ContextExtensions.OUTPUT_CACHE_TIME_KEY,out cacheSecondsObject)) { return; } int cacheSeconds; if (!int.TryParse(cacheSecondsObject.ToString(),out cacheSeconds)) { return; } var cachedResponse = new CachedResponse(contexts.Response); this.cachedResponses[contexts.Request.Path]=new Tuple<DateTime, Response, int>(DateTime.Now,cachedResponse,cacheSeconds); contexts.Response = cachedResponse; }
然后往Views文件夹里面添加index,payload,两个视图
index页面
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首页</title> </head> <body> <div> <h1>缓存Demo</h1> <p><a href="/cached">Cached页面</a></p> <p><a href="/uncached">Uncached页面</a></p> </div> </body> </html>
Payload页面
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首页</title> </head> <body> <div> <h1>缓存Demo</h1> <p>此页是在: @Model</p> <p>这可能是或可能不会被缓存</p> <a href="/">主页</a> </div> </body> </html>
修改Web.config配置文件
<httpHandlers> <add verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" path="*" /> </httpHandlers> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true" /> <validation validateIntegratedModeConfiguration="false" /> <handlers> <add name="Nancy" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" path="*" /> </handlers> </system.webServer>
然后运行一下项目F5
谢谢你的欣赏,如有不对请多多指教!
时间: 2024-10-07 10:20:29