>  기사  >  백엔드 개발  >  asp.net 코어 mvc는 의사 정적 기능을 구현합니다.

asp.net 코어 mvc는 의사 정적 기능을 구현합니다.

高洛峰
高洛峰원래의
2017-02-20 17:00:221401검색

이 글은 pseudo-static 기능을 구현하기 위한 asp.net core mvc 관련 정보를 주로 소개합니다. 관심 있는 친구들이 참고할 수 있습니다.

대규모 웹사이트 시스템에서 시스템 액세스 성능을 향상시키기 위해 쇼핑몰의 제품 세부 정보 페이지 및 뉴스 세부 정보 페이지와 같은 일부 간헐적 콘텐츠가 정적 페이지로 게시되는 경우가 많습니다. 이 정보가 게시되면 계속 사용하는 경우 변경 빈도가 그리 높지 않습니다. 동적 출력을 통해 처리하게 되면 서버에 막대한 자원 낭비가 발생하게 됩니다. 하지만 이러한 콘텐츠에 대한 정적 페이지를 독립적으로 만들 수는 없으므로 시스템에서 의사 정적 처리를 사용할 수 있습니다. 의사 정적이 무엇인지는 Baidu에서 검색할 수 있습니다. asp.net core mvc에서 pseudo-static을 구현하는 방법을 소개하겠습니다.

MVC 프레임워크에서 view는 뷰를 나타내며, 그 실행 결과는 최종적으로 클라이언트 브라우저에 출력되는 html, css, js 등의 콘텐츠입니다. 정적화를 구현하려면 뷰 실행 결과를 정적 파일로 저장하고 디스크, 분산 캐시 등 지정된 위치에 저장해야 다음 번에 저장된 내용을 직접 읽을 수 있습니다. 액세스하면 비즈니스 로직을 다시 실행할 필요가 없습니다. 그렇다면 이러한 기능을 달성하려면 asp.net core mvc가 무엇을 해야 할까요? 대답은 필터를 사용하는 것입니다. MVC 프레임워크에서는 여러 필터 유형이 제공됩니다. 여기서는 작업 필터를 사용하겠습니다. 작업 필터는 작업이 실행되기 전과 작업이 실행된 후의 두 가지 시점을 제공합니다. 작업이 실행되기 전에 먼저 정적 페이지가 생성되었는지 확인할 수 있습니다. 생성된 경우 파일 내용을 직접 읽고 출력할 수 있으며 후속 논리는 건너뜁니다. 프로덕션이 없으면 계속해서 아래로 내려가 액션이 실행된 후 이 단계에서 결과를 캡처한 다음 결과에 의해 생성된 정적 콘텐츠를 저장합니다.

그런 다음 특정 구현 코드를 살펴보겠습니다. 먼저 StaticFileHandlerFilterAttribute를 호출하는 필터 유형을 정의합니다. 이 클래스는 프레임워크에 제공된 ActionFilterAttribute에서 파생되며 기본 클래스에서 제공하는 두 가지 메서드를 재정의합니다. 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] 속성을 추가합니다. 다른 키를 구성하려면 [StaticFileHandlerFilter(Key="set value")]

를 사용할 수 있습니다. 정적화가 구현되었지만 여전히 업데이트를 고려해야 합니다. 기사가 백그라운드에서 업데이트되면 정적 페이지를 업데이트해야 합니다. 하나는 콘텐츠가 업데이트될 때 해당 정적 페이지를 동기적으로 삭제하는 것입니다. 백그라운드에서. 여기서는 또 다른 예약 업데이트를 소개합니다. 이는 정적 페이지에 특정 유효 기간이 있으며 이 유효 기간이 지나면 자동으로 업데이트된다는 의미입니다. 이 로직을 구현하려면 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;
    }
  }
}

이 시점에서 pseudo-static이 달성됩니다. 현재의 처리 방식은 접속 성능을 어느 정도 향상시킬 수 있지만 대규모 포털 시스템에서는 충분하지 않을 수 있습니다. 위에서 소개한 방법에 따르면 다른 기능 확장이 가능하다. 예를 들어 정적 페이지를 생성한 후 CDN에 게시하거나 별도의 콘텐츠 서버에 게시하는 등의 작업을 수행할 수 있다. 방법이 무엇이든 구현 아이디어는 동일합니다.

위 내용은 이 글의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다.

의사 정적 기능을 구현하는 asp.net 코어 mvc와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.