English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في النظامين الكبيرين للواقع الافتراضي، لتحسين أداء الوصول إلى النظام، غالباً ما يتم نشر المحتويات التي تتغير بشكل غير مستقر كصفحات ثابتة، مثل صفحات تفاصيل المنتجات في المتجر، صفحات تفاصيل الأخبار، هذه المعلومات لا تتغير بعد نشرها، وعدة مرات لا تكون معدلات التغيير مرتفعة، إذا استمررنا في استخدام الطريقة الديناميكية للمعالجة، سيؤدي ذلك إلى إهدار كبير لموارد الخادم. ولكن لا يمكننا إنتاج صفحات ثابتة مستقلة لهذه المحتويات جميعها، لذا يمكننا استخدام طريقة الديناميكية المزيفة في النظام، وما هو الديناميكية المزيفة، يمكن البحث عنها في Baidu. سنتحدث هنا عن كيفية تحقيق الديناميكية المزيفة في asp.net core mvc.
في إطار MVC، يمثل view العرض، ويكون نتيجة تنفيذها هي المحتوى النهائي الذي يتم إرساله إلى متصفح المستخدم، ويشمل html،css،js وما إلى ذلك. إذا أردنا تحقيق التبسيط، نحتاج إلى حفظ نتيجة تنفيذ view كملف ثابت، والحفظ في موقع محدد، مثل القرص، أو التخزين الموزع وما إلى ذلك، عند زيارة مرة أخرى يمكن قراءة المحتوى المحفوظ مباشرة دون الحاجة إلى تنفيذ منطق العملية مرة أخرى. لذا كيف يمكن لـ asp.net core mvc تحقيق هذا النوع من الوظائف؟ الإجابة هي استخدام المرشح، في إطار MVC، يتم تقديم أنواع متعددة من المرشحات، ونحن سنستخدم هنا مرشح العملية، يقدم مرشح العملية وقتين: قبل تنفيذ العملية، وبعد تنفيذ العملية. يمكننا التحقق من إنشاء صفحة ثابتة قبل تنفيذ العملية، إذا كانت موجودة، يمكن قراءة محتوى الملف مباشرة وإرساله، وبعد ذلك يمكن تجاوز اللógica التالية. إذا لم يتم إنشاؤها، يمكننا مواصلة تنفيذ العملية، في هذه المرحلة بعد تنفيذ العملية يتم التقاطع النتيجة، ويتم حفظ المحتوى الثابت المُنتج.
نحن الآن سنقوم بتحقيق الكود بشكل محدد، أولاً نحدد نوع المُرشح، ونُدعوه 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، يجب التحقق مما إذا تم توليد المحتوى الثابت أم لا، وإذا تم توليده مباشرة يتم إخراج المحتوى، وتحقيق هذا الlogic كما يلي
//يتم توليد اسم ملف الصفحة الثابتة وفقًا لقواعد معينة، هنا يتم توليد الاسم وفقًا لـ 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، وإلى StringBuiler يوضع محتوى html الناتج 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(); // this line must be called, otherwise the content will be empty writer.Flush(); } // according to the rule to generate the static file name 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; }
المفتاح المذكور أعلاه، نضيف له الخاصية الم对应的
public string Key { get;set; }
بهذا يمكننا استخدام هذا المُنضم، الطريقة الاستخدام: إضافة ميزة [StaticFileHandlerFilter] إلى المُتحكم أو طريقة المُتحكم، إذا كنت ترغب في تكوين مفتاح مختلف يمكنك استخدام [StaticFileHandlerFilter(Key = "القيمة المحددة")]
تم تحقيق التجميد، لذا يجب أن نأخذ في الاعتبار التحديث، إذا قام النظام بتحديث مقالة، يجب أن يتم تحديث الصفحة الثابتة أيضًا، هناك العديد من الحلول: واحد هو إزالة الصفحة الثابتة الم对应的 أثناء تحديث المحتوى في النظام. نقدم هنا طريقة أخرى، وهي التحديث الموقوت، حيث يتم منح الصفحة الثابتة فترة صلاحية معينة، وتجدد تلقائيًا بعد انتهاء هذه الفترة. لإتمام هذه المنطقية، يجب أن نحصل على وقت إنشاء الصفحة الثابتة في طريقة OnActionExecuting، ونقارنها بالوقت الحالي، لنرى إذا كانت قد انتهت الصلاحية، إذا لم تنتهي الصلاحية نقوم بإخراج المحتوى مباشرة، وإذا انتهت الصلاحية نستمر في تنفيذ المنطق التالي. يتمثل الشيفرة المحددة فيما يلي:
// الحصول على كائن معلومات_الملف FileInfo fileInfo = new FileInfo(filePath); // فترة_الاستحقاق، إذا كانت أقل أو تساوي دقيقتين، فتقوم بالإخراج، بالطبع يمكن تعديل القواعد هنا وقت_الزمني 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، أو نشرها على خادم محتوى واحد، وما إلى ذلك. بغض النظر عن الطريقة، فإن طريقة التنفيذ هي نفسها.
هذا هو نهاية محتوى هذا المقال، نأمل أن يكون قد ساعدكم في التعلم، ونأمل أن تدعموا تعليمات الصراخ بشكل كبير.
البيان: محتوى هذا المقال تم جمعه من الإنترنت، ويتمتع المالك الحقيقي بالحقوق، تم جمع المحتوى من قبل المستخدمين على الإنترنت الذين قدموا المساهمات بشكل متعاوني وتم تحميله بشكل مستقل، ويتمتع هذا الموقع بلا حقوق ملكية، ويتمتع بلا تحرير يدوي، ولا يتحمل أي مسؤولية قانونية. إذا كنت قد وجدت محتوى يشتبه في حقوق النسخ، فالرجاء إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال '#' بـ '@') لإبلاغنا، وقدم الأدلة ذات الصلة، وإذا تم التحقق من ذلك، سيتم حذف المحتوى المزعوم بشكل فوري.