在大型网站体系中,为了进步体系接见机能,每每会把一些不常常变得内容宣布成静态页,比方商城的产物详情页,消息详情页,这些信息一旦宣布后,变化的频次不会很高,假如还采纳动态输出的体式格局举行处置惩罚的话,一定会给服务器形成很大的资本糟蹋。然则我们又不能针对这些内容都自力制造静态页,所以我们可以在体系中应用伪静态的体式格局举行处置惩罚,至于什么是伪静态,人人可以百度下。我们这里就来引见一下,在asp.net core mvc中完成伪静态的体式格局。
mvc框架中,view代表的是视图,它实行的效果就是终究输出到客户端浏览器的内容,包括html,css,js等。假如我们想完成静态化,我们就须要把view实行的效果保留成一个静态文件,保留到指定的位置上,比方磁盘、分布式缓存等,下次再接见就可以直接读取保留的内容,而不必再实行一次营业逻辑。那asp.net core mvc要完成如许的功用,应当怎么做?答案是运用过滤器,在mvc框架中,供应了多种过滤器范例,这里我们要运用的是行动过滤器,行动过滤器供应了两个时候点:行动实行前,行动实行后。我们可以在行动实行前,先推断是不是已生成了静态页,假如已生成,直接读取文件内容输出即可,后续的逻辑就实行跳过。假如没有生产,就继承往下走,在行动实行后这个阶段捕捉效果,然后把效果生成的静态内容举行保留。
那我们就来详细的完成代码,起首我们定义一个过滤器范例,我们成为StaticFileHandlerFilterAttribute,这个类派生自框架中供应的ActionFilterAttribute,StaticFileHandlerFilterAttribute重写基类供应的两个要领:OnActionExecuted(行动实行后),OnActionExecuting(行动实行前),详细代码以下:
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public class StaticFileHandlerFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext context){} public override void OnActionExecuting(ActionExecutingContext context){} }
在OnActionExecuting中,须要推断下静态内容是不是已生成,假如已生成直接输出内容,逻辑完成以下:
//根据一定的划定规矩生成静态文件的称号,这里是根据area+"-"+controller+"-"+action+key划定规矩生成 string controllerName = context.RouteData.Values["controller"].ToString().ToLower(); string actionName = context.RouteData.Values["action"].ToString().ToLower(); string area = context.RouteData.Values["area"].ToString().ToLower(); //这里的Key默许即是id,固然我们可以设置差别的Key称号 string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : ""; if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key)) { id = context.HttpContext.Request.Query[Key]; } string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html"); //推断文件是不是存在 if (File.Exists(filePath)) { //假如存在,直接读取文件 using (FileStream fs = File.Open(filePath, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) { //经由过程contentresult返回文件内容 ContentResult contentresult = new ContentResult(); contentresult.Content = sr.ReadToEnd(); contentresult.ContentType = "text/html"; context.Result = contentresult; } } }
在OnActionExecuted中我们须要效果行动效果,推断行动效果范例是不是是一个ViewResult,假如是经由过程代码实行这个效果,猎取效果输出,根据上面一样的划定规矩,生成静态页,详细完成以下
//猎取效果 IActionResult actionResult = context.Result; //推断效果是不是是一个ViewResult if (actionResult is ViewResult) { ViewResult viewResult = actionResult as ViewResult; //下面的代码就是实行这个ViewResult,并把效果的html内容放到一个StringBuiler对象中 var services = context.HttpContext.RequestServices; var executor = services.GetRequiredService<ViewResultExecutor>(); var option = services.GetRequiredService<IOptions<MvcViewOptions>>(); var result = executor.FindView(context, viewResult); result.EnsureSuccessful(originalLocations: null); var view = result.View; StringBuilder builder = new StringBuilder(); using (var writer = new StringWriter(builder)) { var viewContext = new ViewContext( context, view, viewResult.ViewData, viewResult.TempData, writer, option.Value.HtmlHelperOptions); view.RenderAsync(viewContext).GetAwaiter().GetResult(); //这句一定要挪用,不然内容就会是空的 writer.Flush(); } //根据划定规矩生成静态文件称号 string area = context.RouteData.Values["area"].ToString().ToLower(); string controllerName = context.RouteData.Values["controller"].ToString().ToLower(); string actionName = context.RouteData.Values["action"].ToString().ToLower(); string id = context.RouteData.Values.ContainsKey(Key) ? context.RouteData.Values[Key].ToString() : ""; if (string.IsNullOrEmpty(id) && context.HttpContext.Request.Query.ContainsKey(Key)) { id = context.HttpContext.Request.Query[Key]; } string devicedir = Path.Combine(AppContext.BaseDirectory, "wwwroot", area); if (!Directory.Exists(devicedir)) { Directory.CreateDirectory(devicedir); } //写入文件 string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string.IsNullOrEmpty(id) ? "" : ("-" + id)) + ".html"); using (FileStream fs = File.Open(filePath, FileMode.Create)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8)) { sw.Write(builder.ToString()); } } //输出当前的效果 ContentResult contentresult = new ContentResult(); contentresult.Content = builder.ToString(); contentresult.ContentType = "text/html"; context.Result = contentresult; }
上面提到的Key,我们直接增添对应的属性
public string Key { get;set; }
如许我们就可以运用这个过滤器了,运用的要领:在控制器或许控制器要领上增添 [StaticFileHandlerFilter]特征,假如想设置差别的Key,可以运用 [StaticFileHandlerFilter(Key="设置的值")]
静态化已完成了,我们还须要斟酌更新的事,假如背景把一篇文章更新了,我们得把静态页也更新下,计划有许多:一种是在背景举行内容更新时,同步把对应的静态页删除即可。我们这里引见别的一种,定时更新,就是让静态页有一定的有效期,过了这个有效期自动更新。要完成这个逻辑,我们须要在OnActionExecuting要领中猎取静态页的建立时候,然后跟当前时候对照,推断是不是已逾期,假如未逾期直接输出内容,假如已逾期,继承实行背面的逻辑。详细代码以下:
//猎取文件信息对象 FileInfo fileInfo=new FileInfo(filePath); //结算时候距离,假如小于即是两分钟,就直接输出,固然这里的划定规矩可以改 TimeSpan ts = DateTime.Now - fileInfo.CreationTime; if(ts.TotalMinutes<=2) { using (FileStream fs = File.Open(filePath, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) { ContentResult contentresult = new ContentResult(); contentresult.Content = sr.ReadToEnd(); contentresult.ContentType = "text/html"; context.Result = contentresult; } } }
到此伪静态就完成好了。现在的处置惩罚要领,只能在一定程度上可以进步接见机能,然则针对大型的流派体系来讲,能够远远不够。根据上面引见的体式格局,可以再举行其他功用扩大,比方生成静态页后可以宣布到CDN上,也可以宣布到零丁的一个内容服务器,等等。不论是什么体式格局,完成思绪都是一样的。
以上就是本文的全部内容,愿望对人人的进修有所协助,也愿望人人多多支撑ki4网。
更多asp.net core mvc完成伪静态功用相干文章请关注ki4网!