English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Dans les systèmes de sites web à grande échelle, pour améliorer les performances d'accès du système, il est souvent nécessaire de publier des contenus qui ne changent pas souvent sous forme de pages statiques, par exemple les pages de détails des produits du magasin, les pages de détails des nouvelles. Une fois publiés, la fréquence de changement de ces informations ne sera pas très élevée. Si nous utilisons encore la méthode de sortie dynamique pour traiter ces contenus, cela肯定会造成很大的资源浪费。Cependant, nous ne pouvons pas créer des pages statiques indépendantes pour tous ces contenus. Donc, nous pouvons utiliser la méthode de pseudo-statification dans le système. Quant à ce que c'est que la pseudo-statification, vous pouvez chercher sur Baidu. Ici, nous allons présenter la manière d'implémenter la pseudo-statification dans ASP.NET Core MVC.
Dans le cadre MVC, la vue représente le contenu de la vue, et le résultat de son exécution est le contenu final envoyé au navigateur client, y compris HTML, CSS, JS, etc. Si nous voulons réaliser la statification, nous devons sauvegarder le résultat de l'exécution de la vue sous forme de fichier statique, le sauvegarder à un emplacement spécifique, par exemple sur le disque, dans un cache distribué, etc. Lorsque nous accédons à nouveau, nous pouvons lire directement le contenu sauvegardé sans avoir à exécuter à nouveau la logique métier. Alors, comment ASP.NET Core MVC doit-il réaliser une telle fonction ? La réponse est d'utiliser un filtre. Dans le cadre MVC, plusieurs types de filtres sont fournis. Ici, nous utilisons le filtre d'action, qui fournit deux points dans le temps : avant et après l'exécution de l'action. Nous pouvons vérifier si une page statique a été générée avant l'exécution de l'action. Si elle a été générée, nous pouvons lire directement le contenu du fichier et l'envoyer. Le reste de la logique est ignoré. Si elle n'a pas été générée, nous continuons à avancer et capturons le résultat après l'exécution de l'action, puis sauvegardons le contenu statique généré.
Alors, nous allons réaliser le code spécifique. Premièrement, nous définissons un type de filtre, que nous appelons StaticFileHandlerFilterAttribute. Cette classe dérive de l'AttributeFilterAttribute fournie par le cadre. StaticFileHandlerFilterAttribute redéfinit deux méthodes fournies par la classe mère : OnActionExecuted (après l'exécution de l'action) et OnActionExecuting (avant l'exécution de l'action). Le code spécifique est le suivant :
[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){} }
Dans OnActionExecuting, il faut vérifier si le contenu statique a été généré, si cela est le cas, sortez directement le contenu, la logique d'implémentation est la suivante
//Générez le nom du fichier statique suivant une règle spécifique, ici suivant le domaine+"-"+controller+"-"+action+Règles de génération de clé string controllerName = context.RouteData.Values["controller"].ToString().ToLower(); string actionName = context.RouteData.Values["action"].ToString().ToLower(); string area = context.RouteData.Values["area"].ToString().ToLower(); //Ici, la clé par défaut est égale à id, bien sûr, nous pouvons configurer des noms de clé différents 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) &63; "" : ("-" + id)) + .html //Vérifiez si le fichier existe if (File.Exists(filePath)) { //Si il existe, lisez directement le fichier using (FileStream fs = File.Open(filePath, FileMode.Open)) { using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) { //Retournez le contenu du fichier via contentresult ContentResult contentresult = new ContentResult(); contentresult.Content = sr.ReadToEnd(); contentresult.ContentType = "text/html"; context.Result = contentresult; } } }
Dans OnActionExecuted, nous avons besoin du résultat de l'action, vérifiez le type du résultat de l'action, s'il s'agit d'un ViewResult, exécutez ce résultat par code, obtenez la sortie du résultat, selon les règles mentionnées ci-dessus, générer une page statique, l'implémentation spécifique est la suivante
//Obtenez le résultat IActionResult actionResult = context.Result; //Vérifiez si le résultat est un ViewResult if (actionResult is ViewResult) { ViewResult viewResult = actionResult as ViewResult; //Le code suivant exécute ce ViewResult et met le contenu HTML du résultat dans un objet StringBuilder 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(); //Cette ligne doit absolument être appelée, sinon le contenu sera vide writer.Flush(); } //générer le nom de fichier statique suivant les règles 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); } //Écrire dans le fichier string filePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", area, controllerName + "-" + actionName + (string.IsNullOrEmpty(id) &63; "" : ("-" + id)) + .html using (FileStream fs = File.Open(filePath, FileMode.Create)) { using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8)) { sw.Write(builder.ToString()); } } //Afficher le résultat actuel ContentResult contentresult = new ContentResult(); contentresult.Content = builder.ToString(); contentresult.ContentType = "text/html"; context.Result = contentresult; }
Pour la clé mentionnée précédemment, nous ajoutons directement l'attribut correspondant
public string Key { get;set; }
Nous pouvons utiliser ce filtre maintenant, la méthode d'utilisation : ajoutez l'attribut [StaticFileHandlerFilter] sur le contrôleur ou la méthode du contrôleur. Si vous souhaitez configurer une clé différente, utilisez [StaticFileHandlerFilter(Key = "valeur définie")]
La statification est déjà réalisée, nous devons également considérer la mise à jour, si le contenu d'un article est mis à jour en arrière-plan, nous devons également mettre à jour la page statique. Il y a de nombreuses solutions : l'une est de supprimer la page statique correspondante lors de la mise à jour du contenu en arrière-plan. Nous présentons ici une autre méthode, la mise à jour programmée, qui consiste à faire que la page statique ait une période de validité, et après cette période, elle est automatiquement mise à jour. Pour réaliser cette logique, nous devons obtenir le temps de création de la page statique dans la méthode OnActionExecuting, puis comparer avec le temps actuel pour déterminer si elle est expirée. Si elle n'est pas expirée, affichez directement le contenu. Si elle est expirée, continuez à exécuter la logique suivante. Le code spécifique est le suivant :
//Obtenir l'objet d'information de fichier FileInfo fileInfo = new FileInfo(filePath); //Intervalle de temps de règlement, si inférieur ou égal à deux minutes, il est directement affiché, bien sûr, les règles peuvent être modifiées 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; } } }
La mise en œuvre statique est terminée ici. La méthode actuelle ne peut améliorer les performances d'accès dans une certaine mesure, mais pour un grand système de portail, cela peut ne pas être suffisant. Selon la méthode décrite ci-dessus, d'autres fonctionnalités peuvent être étendues, par exemple, après la génération de pages statiques, elles peuvent être publiées sur un CDN, ou sur un serveur de contenu distinct, etc. Quelle que soit la méthode, l'approche d'implémentation est la même.
Voici la fin de l'article. J'espère que cela pourra aider à votre apprentissage, et j'espère que vous soutenirez également le tutoriel à crier.
Déclaration : le contenu de cet article est issu du réseau, la propriété intellectuelle appartient aux auteurs respectifs, le contenu est contribué et téléversé par les utilisateurs d'Internet, ce site ne détient pas de propriété intellectuelle, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un email à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un email pour signaler une violation, et fournir des preuves pertinentes. Une fois confirmée, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)