ASP.NET Core 过滤器 使用依赖项注入

        过滤器是 ASP.NET Core 中的特殊组件,允许我们在请求管道的特定阶段控制请求的执行。这些过滤器在中间件执行后以及 MVC 中间件匹配路由并调用特定操作时发挥作用。

        简而言之,过滤器提供了一种在操作级别自定义应用程序行为的方法。它们就像检查点,允许我们执行特定任务,例如异常处理、缓存或添加自定义响应标头。

        当请求到达某个操作时,过滤器可以收集有关已选择哪个操作以及关联的路由数据的信息。此信息可用于做出决策并执行特定于该特定操作或控制器的操作。

        通过使用过滤器,我们在处理请求时拥有更多的控制权和灵活性。我们可以根据我们的要求实现自定义逻辑并将特定行为应用于不同的操作或控制器。这有助于在 ASP.NET Core 应用程序中实现更加定制和高效的请求处理流程。

过滤器的类型

        ASP.NET Core 提供了一组预定义的过滤器类型,允许我们在操作或控制器的上下文中控制请求的执行。这些过滤器有不同的用途,可以根据我们的要求进行定制。

以下是 ASP.NET Core 中预定义过滤器的主要类型:

  1. AuthorizationFilter:此过滤器在路由执行开始时执行。它确定是否允许用户访问该路由或执行请求的操作。

  2. ResourceFilter:该过滤器在授权后运行,可用于绕过剩余管道的执行。如果预处理的响应可用,我们想要发送缓存的响应,从而跳过管道的其余部分,那么它非常有用。

  3. ActionFilter:动作过滤器在动作执行之前和之后运行。它提供了一种用自定义逻辑包围操作或在执行操作之前和之后执行其他任务的方法。

  4. ResultFilter:此过滤器在操作生成结果之前和之后执行。它允许我们用附加行为包围结果执行或根据结果执行某些操作。

  5. ExceptionFilter:每当操作或控制器中抛出未捕获的异常时,异常过滤器就会运行。它提供了一种处理异常并设计特定于操作或控制器的自定义错误响应的方法。

  6. ServiceFilter:此过滤器运行另一个过滤器,其类型在其自身内传递。当传递的过滤器类型注册为服务时使用它。它解决通过依赖项注入 (DI) 传递给过滤器类型的任何依赖项。

  7. TypeFilter:与服务过滤器类似,类型过滤器也运行未注册为服务的过滤器类型。它允许我们应用自定义过滤器而无需注册。

        这些预定义的过滤器类型使我们能够灵活地控制请求执行过程,并在 ASP.NET Core 应用程序的管道的不同阶段添加特定行为。

过滤器范围 

        ASP.NET Core 中过滤器的范围取决于它们附加到 MVC 管道的方式。这使我们能够控制过滤器执行的时间和地点。过滤器的主要范围分为三个:

  1. 特定于操作的范围:过滤器可以应用于控制器内的特定操作方法。通过使用过滤器属性修饰操作,过滤器将仅在选择该特定操作来处理传入请求时执行。

  2. 特定于控制器的范围:过滤器也可以应用于整个控制器类。当过滤器应用于控制器级别时,它将针对该控制器内的所有操作执行。

  3. 全局范围:全局过滤器应用于路由中间件匹配和拾取的每条路由。这些过滤器被注册为全局过滤器,并且无论特定操作或控制器如何都会被执行。但是,如果没有为请求选择端点,则不会执行任何过滤器。

        要将过滤器注册为全局过滤器,可以将其添加到 Startup 类中的 ConfigureServices() 方法内的过滤器数组中。这是一个例子:

services.AddControllers(options => {
    options.Filters.Add(typeof(ConsoleGlobalActionFilter));
});

        在此示例中,使用 Add(typeof(...)) 方法将 ConsoleGlobalActionFilter 注册为全局筛选器。这确保过滤器将应用于路由中间件匹配和处理的每个路由。

        通过控制过滤器的范围,我们可以精确地确定过滤器将在 ASP.NET Core 应用程序中应用的时间和位置,从而允许我们添加特定的行为并有效地控制请求执行过程。

如何创建简单的过滤器

有两种方法可以创建我们之前讨论的类型的过滤器。我们以创建ActionFilter为例:

  1. 实现接口:要创建根据操作执行进行操作的自定义操作过滤器,我们可以创建一个实现 IActionFilter 或 IAsyncActionFilter 接口的类。这些接口提供了我们可以重写以添加自定义逻辑的方法。通过实现这些接口,我们可以完全控制操作过滤器的行为。

  2. 扩展属性类:或者,我们可以创建一个扩展 ActionFilterAttribute 类的自定义操作过滤器类。ActionFilterAttribute 类已经实现了 IActionFilter 和 IAsyncActionFilter 接口。通过扩展此类,我们可以重写我们感兴趣的方法并添加自定义逻辑。这种方法提供了一种更方便的方法来创建操作过滤器,因为我们可以直接扩展基类并专注于实现必要的方法。

        同样,对于提到的其他类型的过滤器(如授权过滤器、资源过滤器、结果过滤器、异常过滤器),也有相应的可以实现的接口或可以扩展的属性类。

以下是上述过滤器的接口和属性类:

  • IAuthorizationFilter:可以通过AuthorizationFilterAttribute实现或扩展。

  • IResourceFilter:可以通过ResourceFilterAttribute实现或扩展。

  • IActionFilter:可以通过ActionFilterAttribute实现或扩展。

  • IResultFilter:可以通过ResultFilterAttribute实现或扩展。

  • IExceptionFilter:可以通过ExceptionFilterAttribute实现或扩展。

        其中一些过滤器附带有实现相应接口的属性类,使我们能够灵活地重写适合我们需要的特定方法。以下是一些过滤器的属性类:

  • ActionFilterAttribute:该属性类实现 IActionFilter 和 IAsyncActionFilter 接口。通过扩展这个类,我们可以直接继承这些接口的实现并重写我们感兴趣的方法。这使得我们可以根据我们的需求自定义动作过滤器的行为。

  • ExceptionFilterAttribute:该属性类实现 IExceptionFilter 接口。通过扩展此类并重写其方法,我们可以处理和自定义对操作或控制器中发生的异常的处理。这使我们能够控制异常的处理方式,并允许我们提供自定义错误响应。

  • ResultFilterAttribute:该属性类实现 IResultFilter 接口。通过扩展此类并重写其方法,我们可以在将操作生成的结果发送回客户端之前对其进行修改。这允许我们向结果添加额外的处理或转换。

  • FormatFilterAttribute:此属性类用于指定操作或控制器支持的响应格式。它有助于内容协商并根据客户的偏好选择适当的响应格式。

  • ServiceFilterAttribute:此属性类用于应用注册为服务的过滤器。它允许我们使用依赖项注入来解决过滤器所需的任何依赖项。当过滤器需要额外的服务或依赖项才能正常运行时,这会很有帮助。

  • TypeFilterAttribute:该属性类与ServiceFilterAttribute类似,但它允许我们应用未注册为服务的过滤器。我们可以直接指定过滤器类型及其依赖项。

            例如,ActionFilterAttribute类已经为我们实现了IActionFilter和IAsyncActionFilter接口,因此我们可以直接扩展ActionFilterAttribute类并重写我们感兴趣的方法。

using System; 
using System.Threading.Tasks; 
using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.Filters; 
using Newtonsoft.Json;  public class AddResponseHeaderFilter : ActionFilterAttribute 
{     // Async method which can surround the action execution// Invoked before and after the action executionpublic asyn coverride Task OnActionExecutionAsync(         ActionExecutingContext context, ActionExecutionDelegate next)     {         // Access the request         context.HttpContext.Response.Headers.Add(             "X-MyCustomHeader", Guid.NewGuid().ToString());                  var result = await next.Invoke();                  // Access the response         Console.WriteLine(JsonConvert.SerializeObject(result.Result));     } 
}  [Route("api/[controller]")] 
[ApiController] 
public class HomeController : ControllerBase 
{     [AddResponseHeaderFilter]     [Route("")]     [HttpGet]     public IActionResult Index()     {         return Ok(new { Message = "I'm Alive" });     } 
}

        在此示例中,我们通过扩展ActionFilterAttribute创建了自定义AddResponseHeaderFilter类。此过滤器在执行操作之前和之后向 HTTP 响应添加自定义响应标头。它重写OnActionExecutionAsync方法,该方法允许我们自定义操作执行周围的行为。

        然后,我们使用 [ AddResponseHeaderFilter ] 属性将AddResponseHeaderFilter过滤器应用到HomeController类的Index操作。这可确保针对该特定操作执行过滤器。

        调用该操作时,过滤器使用Response.Headers.Add方法将自定义标头添加到响应中。然后它调用 next.Invoke() 方法来继续执行操作。执行操作后,它会访问响应结果并使用JsonConvert.SerializeObject 将其写入控制台。

        通过利用ActionFilterAttribute并创建自定义过滤器类,我们可以扩展和自定义 ASP.NET Core 请求管道的行为,以添加其他功能并根据我们的要求修改响应。

动作过滤器的实现
示例 1:实现 IActionFilter 的同步操作过滤器 

using Microsoft.AspNetCore.Mvc.Filters;namespace ActionFilters.Filters
{public class ActionFilterExample : IActionFilter{public void OnActionExecuting(ActionExecutingContext context){// Code executed before the action method executes}public void OnActionExecuted(ActionExecutedContext context){// Code executed after the action method executes}}
}

        在此示例中,我们创建一个名为 ActionFilterExample 的类,该类实现 IActionFilter 接口。该接口要求我们实现两个方法:OnActionExecuting 和 OnActionExecuted。OnActionExecuting 方法包含将在操作方法之前执行的代码,而 OnActionExecuted 方法包含将在操作方法之后执行的代码。 

示例 2:实现 IAsyncActionFilter 的异步操作过滤器 

using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;namespace ActionFilters.Filters
{public class AsyncActionFilterExample : IAsyncActionFilter{public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){// Code executed before the action method executesvar result = await next();// Code executed after the action method executes}}
}

        在此示例中,我们创建一个名为 AsyncActionFilterExample 的类,该类实现 IAsyncActionFilter 接口。该接口要求我们实现 OnActionExecutionAsync 方法,该方法是动作过滤器的异步版本。该方法接收一个 ActionExecutingContext 和一个 ActionExecutionDelegate。ActionExecutionDelegate 代表管道中的下一个操作,我们可以等待它执行操作方法。通过这样做,我们可以在操作方法执行之前和之后运行代码。

        通过创建实现 IActionFilter 或 IAsyncActionFilter 的类,我们可以定义要在 ASP.NET Core 中的操作方法之前和之后执行的自定义逻辑。这些操作过滤器提供了一种向请求管道添加附加行为并根据需要修改请求或响应的方法。

 操作过滤器的范围
可以在不同范围级别添加操作过滤器:全局、操作和控制器。

1. 全局范围

要全局使用操作过滤器,您可以在ConfigureServices方法的AddControllers()方法中注册它:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers(config =>{config.Filters.Add(new GlobalFilterExample());});
}

在.NET 6及更高版本中,由于缺少 Startup 类,您可以使用 Program 类: 

builder.Services.AddControllers(config => 
{ config.Filters.Add( new GlobalFilterExample()); 
});

通过将过滤器添加到全局范围,它将应用于整个应用程序中的所有操作方法。

2. 操作和控制器范围

如果要在操作或控制器级别使用操作过滤器,则需要在ConfigureServices方法中将其注册为IoC容器中的服务:

services.AddScoped<ActionFilterExample>(); 
services.AddScoped<ControllerFilterExample>();

在 .NET 6 及更高版本中: 

builder.Services.AddScoped<ActionFilterExample>(); 
builder.Services.AddScoped<ControllerFilterExample>();

        通过将操作过滤器注册为服务,您可以通过使用相应的过滤器属性装饰它们,有选择地将其应用到特定的操作方法或控制器。

        最后,要使用在操作或控制器级别注册的过滤器,您需要使用ServiceFilter属性将其应用到相应的控制器或操作方法之上
namespace AspNetCore.Controllers
{[ServiceFilter(typeof(ControllerFilterExample))][Route("api/[controller]")][ApiController]public class TestController : ControllerBase{[HttpGet][ServiceFilter(typeof(ActionFilterExample))]public IEnumerable<string> Get(){return new string[] { "example", "data" };}}
}

        通过使用[ServiceFilter]属性并指定过滤器类型,您可以将注册的过滤器(ControllerFilterExample 和 ActionFilterExample)分别与控制器和操作方法关联起来。

        这允许将过滤器应用于指定的范围,控制执行流程并在执行操作方法之前和之后提供附加功能。
        以这种方式使用ServiceFilter属性可以帮助您利用依赖项注入的优势,并将所需的过滤器应用到 ASP.NET 应用程序中的特定控制器和操作方法。

调用顺序
我们的过滤器的执行顺序如下:

我们可以通过向ServiceFilter属性添加一个名为Order 的附加属性来更改多个过滤器的调用顺序 

namespace AspNetCore.Controllers
{[ServiceFilter(typeof(ControllerFilterExample), Order=2)][Route("api/[controller]")][ApiController]public class TestController : ControllerBase{[HttpGet][ServiceFilter(typeof(ActionFilterExample), Order=1)]public IEnumerable<string> Get(){return new string[] { "example", "data" };}}
}

        在本例中,ControllerFilterExample将在ActionFilterExample之前执行,因为它们的顺序值分别为 2 和 1。通过为过滤器分配不同的顺序值,您可以控制它们的执行顺序。

您还可以将多个过滤器应用于同一操作方法并定义它们的执行顺序:
[HttpGet] 
[ServiceFilter(typeof(ActionFilterExample), Order=2)] 
[ServiceFilter(typeof(ActionFilterExample2), Order=1)] 
public IEnumerable<string> Get() 
{ return new string[] { "example", "data ” }; 
}

         在这种情况下,ActionFilterExample2将根据其顺序值分别为 1 和 2,在ActionFilterExample之前执行。

        通过指定每个过滤器的顺序,您可以对执行顺序进行细粒度控制,并且可以应用具有不同优先级的多个过滤器以在 ASP.NET 应用程序中实现所需的行为。

使用操作过滤器改进代码
        为了使用操作过滤器改进代码,让我们重点关注存储库中AppStart文件夹中起始项目的Controllers文件夹中的MoveController类。该控制器包含所有 CRUD 操作的实现。

尽管我们的操作已经干净且可读,但由于全局异常处理,我们可以进一步增强它们。

需要注意的一件重要事情是我们的Movie模型继承自IEntity接口:

[Table("Movie")]
public class Movie: IEntity
{[Key]public Guid Id { get; set; }[Required(ErrorMessage = "Name is required")]public string Name { get; set; }[Required(ErrorMessage = "Genre is required")]public string Genre { get; set; }[Required(ErrorMessage = "Director is required")]public string Director { get; set; }
}

         现在,让我们关注POSTPUT操作的验证代码。通过将适当的操作过滤器应用于POSTPUT操作,我们可以消除这些操作中显式验证代码的需要,使它们更加简洁和可维护。

使用操作过滤器进行验证
        为了改进POST和PUT操作中的验证代码,我们可以使用操作过滤器。通过将验证逻辑提取到自定义操作过滤器中,我们可以使代码更具可重用性并保持操作更清晰。

        首先,我们在解决方案资源管理器中创建一个名为“ActionFilters”的新文件夹。在该文件夹中,创建一个名为ValidationFilterAttribute的新类:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Linq;namespace ActionFilters.ActionFilters
{public class ValidationFilterAttribute : IActionFilter{public void OnActionExecuting(ActionExecutingContext context){var param = context.ActionArguments.SingleOrDefault(p => p.Value is IEntity);if (param.Value == null){context.Result = new BadRequestObjectResult("Object is null");return;}if (!context.ModelState.IsValid){context.Result = new UnprocessableEntityObjectResult(context.ModelState);}}public void OnActionExecuted(ActionExecutedContext context){          }}
}

         在ValidationFilterAttribute类中,我们重写OnActionExecuting方法来执行验证逻辑。我们检查操作参数是否为 IEntity 类型,如果为 null,则返回BadRequestObjectResult。此外,如果 ModelState 无效,我们将返回UnprocessableEntityObjectResult

        接下来,让我们在ConfigureServices方法中将此操作过滤器注册为服务:

public void ConfigureServices(IServiceCollection services)
{services.AddDbContext<MovieContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("sqlConString")));services.AddScoped<ValidationFilterAttribute>();services.AddControllers();
}

对于.NET 6,我们需要在 Program 类中使用构建器变量: 

builder.Services.AddDbContext<MovieContext>(options => options.UseSqlServer(Configuration.GetConnectionString( "sqlConString" ))); builder.Services.AddScoped<ValidationFilterAttribute>(); builder.Services.AddControllers();

最后,从 POST 和 PUT 操作中删除验证代码,并将ValidationFilterAttribute作为服务应用:

[HttpPost]
[ServiceFilter(typeof(ValidationFilterAttribute))]
public IActionResult Post([FromBody] Movie movie)
{_context.Movies.Add(movie);_context.SaveChanges();return CreatedAtRoute("MovieById", new { id = movie.Id }, movie);
}[HttpPut("{id}")]
[ServiceFilter(typeof(ValidationFilterAttribute))]
public IActionResult Put(Guid id, [FromBody] Movie movie)
{var dbMovie = _context.Movies.SingleOrDefault(x => x.Id.Equals(id));if (dbMovie == null){return NotFound();}dbMovie.Map(movie);_context.Movies.Update(dbMovie);_context.SaveChanges();return NoContent();
}

        通过将 ValidationFilterAttribute 应用为服务过滤器,我们无需在操作中使用验证代码。代码现在更干净、更具可读性。此外,只要我们的模型类继承自 IEntity 接口,此验证逻辑就可以重用。

        为了确保操作过滤器的验证优先于 [ApiController] 属性的默认验证行为,我们需要禁止默认验证。在 Startup 类(或 .NET 6 的 Program 类)中,添加以下配置:
services.Configure<ApiBehaviorOptions>(options => 
{ options.SuppressModelStateInvalidFilter = true ; 
});

         此配置可确保返回操作过滤器的验证结果(例如,UnprocessableEntity),而不是返回验证错误的默认BadRequest结果。

        通过这些更改,我们的验证过滤器已准备好进行测试。

动作过滤器中的依赖注入
        为了消除通过 ID 从数据库中获取电影并在 GetById、DELETE 和 PUT 操作中检查其是否存在的代码重复,我们可以创建一个新的操作过滤器来执行此任务。我们还将使用依赖注入将 MovieContext 注入到动作过滤器中。

让我们在 ActionFilters 文件夹中创建一个名为 ValidateEntityExistsAttribute<T> 的新操作过滤器类:

using System; 
using System.Linq; 
using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.Filters;  namespace ActionFilters.ActionFilters 
{     public class ValidateEntityExistsAttribute<T> : IActionFilter where T : class, IEntity     {         private readonly MovieContext _context;          public ValidateEntityExistsAttribute(MovieContext context)         {             _context = context;         }          public void OnActionExecuting(ActionExecutingContext context)         {             Guid id = Guid.Empty;              if (context.ActionArguments.ContainsKey("id"))             {                 id = (Guid)context.ActionArguments["id"];             }             else             {                 context.Result = new BadRequestObjectResult("Bad id parameter");                 return;             }              var entity = _context.Set<T>().SingleOrDefault(x => x.Id.Equals(id));             if (entity == null)             {                 context.Result = new NotFoundResult();             }             else             {                 context.HttpContext.Items.Add("entity", entity);             }         }          public void OnActionExecuted(ActionExecutedContext context)         {         }     } 
} 

        在ValidateEntityExistsAttribute<T>类中,我们使用依赖注入通过构造函数注入MovieContext 。该类是通用的,以便它可以重用于我们项目中的任何模型。在OnActionExecuting方法中,我们从操作上下文中获取 ID 参数并检查该实体是否存在于数据库中。如果找到实体,我们会将其存储在HttpContext .Items 集合中,以便稍后在操作方法中使用。

        接下来,让我们在ConfigureServices方法中注册操作过滤器:

 services.AddScoped<ValidateEntityExistsAttribute<Movie>>();

        对于 .NET 6,我们在 Program 类中使用构建器变量: 

builder.Services.AddScoped<ValidateEntityExistsAttribute<Movie>>();

最后,修改我们的操作以将 ValidateEntityExistsAttribute 应用为服务过滤器:

[HttpGet("{id}", Name = "MovieById")] [ServiceFilter(typeof(ValidateEntityExistsAttribute<Movie>))] 
public IActionResult Get(Guid id) 
{     var dbMovie = HttpContext.Items["entity"] as Movie;      return Ok(dbMovie); 
}  [HttpPut("{id}")] 
[ServiceFilter(typeof(ValidationFilterAttribute))] 
[ServiceFilter(typeof(ValidateEntityExistsAttribute<Movie>))] 
public IActionResult Put(Guid id, [FromBody]Movie movie) 
{     var dbMovie = HttpContext.Items["entity"] as Movie;      dbMovie.Map(movie);      _context.Movies.Update(dbMovie);     _context.SaveChanges();      return NoContent(); 
}  [HttpDelete("{id}")] 
[ServiceFilter(typeof(ValidateEntityExistsAttribute<Movie>))] 
public IActionResult Delete(Guid id) 
{     var dbMovie = HttpContext.Items["entity"] as Movie;      _context.Movies.Remove(dbMovie);     _context.SaveChanges();      return NoContent(); 
} 

        通过应用ValidateEntityExistsAttribute<Movie>作为服务过滤器,我们确保从数据库中获取电影实体并通过HttpContext.Items在操作方法中可用。这消除了在获取实体并检查其存在时重复代码的需要。

        通过这些更改,我们的操作更加清晰、更具可读性,并且通过 ID 获取实体的代码现在可以重用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658059.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CCF CSP 202312-2因子化简

题目描述 样例 输入 3 2155895064 3 2 2 10000000000 10 输出 2238728 1 10000000000 基本思路 首先&#xff0c;要找出构成n的所有素因子&#xff0c;这些因子满足两个条件&#xff1a;是素数&#xff08;函数判断&#xff09;&#xff0c;且能被n或n的中间值整除&#xf…

【RT-DETR有效改进】CARAFE提高精度的上采样方法(助力细节长点)

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 本文给大家带来的CARAFE(Content-Aware ReAssembly of FEatures)是一种用于增强卷积神经网络特征图的上采样方法。其主要旨在改进传统的上采样方法(就是我们的Upsample)的性能。CARAFE的核心思想是:使用输…

ONLYOFFICE:兼顾协作与安全的开源办公套件

文章目录 前言ONLYOFFICE是什么&#xff1f;ONLYOFFICE的特点多人在线协同灵活集成安全可靠跨平台和设备扩展丰富 实操注册登录编写文档插件安装智谱CopilotDraw.io 新版强势功能显示协作者头像插件 UI 界面更新 总结 前言 随着数字化时代的到来&#xff0c;越来越多的文档处理…

操作系统-线程的实现方式和多线程模型(用户级线程 内核级线程 多线程模型的情况)和线程的状态,转换,组织,控制

文章目录 线程的实现方式和多线程模型总览线程的实现方式用户级线程内核级线程多线程模型一对一多对一多对多 小结 线程的状态,转换,组织,控制总览 线程的状态与转换线程的组织与控制 线程的实现方式和多线程模型 总览 线程的实现方式 用户级线程 程序自己通过自己设计的线程…

06 单目初始化器 Initializer

文章目录 06 单目初始化器 Initializer6.1 成员变量/函数6.2 初始化函数 Initialize()6.3 计算基础矩阵 F \boldsymbol{F} F 和单应矩阵 H \boldsymbol{H} H6.3.1 RANSAC 算法6.3.2 八点法计算 F \boldsymbol{F} F 矩阵: ComputeF21()6.3.3 计算基础矩阵 F \boldsymbol{F} …

怎么使用cmd命令来进行Vue脚手架的项目搭建

前言 使用vue搭建项目的时候&#xff0c;我们可以通过对应的cmd命令去打开脚手架&#xff0c;然后自己配置对应的功能插件 怎么打开 我们打开对应的cmd命令之后就开始进入对应的网站搭建 vue ui 然后我们就打开对应的项目管理器来进行配置----这里我们打开开始创建新的项目…

【VS Code+Verilog+Vivado使用】(2)基本设置

文章目录 2 基本设置2.1 字体大小2.2 Tab大小2.3 选中高亮2.4 文件编码 2 基本设置 2.1 字体大小 方法1&#xff1a;VS Code左下角 > 管理 > 设置&#xff0c;搜索"font size"&#xff0c;点击左侧"字体"&#xff0c;根据需要设置"editor.fon…

穷游网酒店数据采集与可视化分析与实现

摘 要 穷游网酒店数据采集与可视化分析大屏的背景是为了满足用户对酒店数据的需求以及提供数据洞察和决策支持。随着旅游业的快速发展&#xff0c;人们对酒店信息的需求日益增加&#xff0c;而穷游网作为一家专注于旅游信息的网站&#xff0c;拥有丰富的酒店数据资源。 这个大…

回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测

回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入…

Flink实战四_TableAPISQL

接上文&#xff1a;Flink实战三_时间语义 1、Table API和SQL是什么&#xff1f; 接下来理解下Flink的整个客户端API体系&#xff0c;Flink为流式/批量处理应用程序提供了不同级别的抽象&#xff1a; 这四层API是一个依次向上支撑的关系。 Flink API 最底层的抽象就是有状态实…

腾讯mini项目总结-指标监控服务重构

项目概述 本项目的背景是&#xff0c;当前企业内部使用的指标监控服务的方案的成本很高&#xff0c;无法符合用户的需求&#xff0c;于是需要调研并对比测试市面上比较热门的几款开源的监控方案&#xff08;选择了通用的OpenTelemetry协议&#xff1a;Signoz&#xff0c;otel-…

JVM学习

1.Java虚拟机内部有哪些线程共享&#xff0c;那些线程隔离 程序计数器&#xff1a; 通过改变这个计数器的值来选取下一条需要执行的字节码命令 Java虚拟机栈&#xff1a; 栈&#xff0c;每个方法被执行时&#xff0c;Java虚拟机都会同步的创建一个栈帧用于存储局部变量表&…

java 实现微信公众号关键字自动回复

接上一篇内容https://blog.csdn.net/YISHENGYOUNI95/article/details/134383219 因为设置了公众号的服务器配置&#xff0c;导致之前设置的公众号自动回复失效了 需要通过之前配置的接口实现自动回复 参考一下官方文档回复文本消息 | 微信开放文档 根据用户发送的消息&#…

中国的茶文化:历史、传统与生活

中国的茶文化&#xff1a;历史、传统与生活 一、引言 茶&#xff0c;这一神奇而古老的饮品&#xff0c;与中国的历史、文化和生活方式紧密相连。中国的茶文化&#xff0c;源远流长&#xff0c;博大精深&#xff0c;是中华文明的重要组成部分。它不仅是一种饮料&#xff0c;更是…

Jedis连接池究竟是何物?

一、前言 连接池的用途实际上有过开发经验的朋友都已经比较清楚了&#xff0c;当资源对象的创建/销毁比较耗时的场景下&#xff0c;可以通过"池化"技术&#xff0c;达到资源的复用&#xff0c;以此来减少系统的开销、增大系统吞吐量&#xff0c;比如数据库连接池、线…

雍禾植发:“地球生发计划”修复荒漠化土地超百万平方米

日前&#xff0c;雍禾植发宣布“毛发森林•地球生发计划”从正式发起到2023年11月19日秋季造林结束&#xff0c;已经在内蒙古自治区额济纳旗东风镇额很查干嘎查种下60000棵树&#xff0c;修复荒漠化土地超过102.01万平方米。 作为此次公益活动的“落脚地”,额济纳旗地处内蒙古…

Swift Vapor 教程(项目创建)

The future of web development. 在初次接触 Swift Vapor 时&#xff0c;感觉代码比较清爽&#xff0c;用起来逻辑比较清晰。 困难点&#xff1a; Swift Vapor 使用了JWT管理三方库&#xff0c;比较吃网络Swift Vapor 搭建环境比较复杂初次使用Swift Vapor 尽量不要使用MySql。…

Linux内存常用命令指标详解

1. free rootnode02:~# free -m total used free shared buff/cache available Mem: 3919 1194 1738 1 986 2446 Swap: 0 0 0free 输出的是一个表格&#xff0c;其中…

网页版idea、pycharm搭建

官网教程提供了两种方法&#xff1a;1、有给应用版idea或pycharm安装插件来开放网页服务&#xff1b;2、使用docker创建容器开放网页服务。这边推荐并介绍第二种步骤。 基本过程为&#xff1a;拉取相关镜像&#xff1b;开启服务&#xff1b;使用网页版 &#xff08;细节和注意点…

3D数据转换器HOOPS Exchange如何获取模型的几何数据? 干货预警!

一、概述 前面讲解过模型在内存中的结构&#xff0c;现在回顾一下&#xff0c;当模型导入成功后&#xff0c;整个模型数据会以原生结构的 PRC 组装树形式存放到内存中。&#xff08;申请 HOOPS Exchange 试用&#xff09; PRC结构的主要类型包含四种&#xff0c;分别是…