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.hqwc.cn/news/439695.html

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

相关文章

五粮液的“活窖之美”,探寻“大国浓香”的千年奥秘

执笔 | 尼 奥 编辑 | 扬 灵 “川酒甲天下&#xff0c;精华在宜宾。”酒都宜宾已有4000余年酿酒历史&#xff0c;璀璨的白酒文化孕育了有着“大国浓香、和美五粮、中国酒王”金字招牌的传世名酒五粮液。从盛唐“重碧酒”到宋代“姚子雪曲”&#xff0c;再到“五粮液”&…

外部实体注入漏洞

当允许引用外部实体时&#xff0c;会造成外部实体注入&#xff08;XXE&#xff09;漏洞。通过构造恶意 内容&#xff0c;就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站 等危害。本节介绍针对XXE漏洞的检测和防御方法。 5.2.1 简介 根据回显情况&#x…

[足式机器人]Part3 机构运动学与动力学分析与建模 Ch01-2 完整定常系统——杆组RRR

机械原理/机构简图/机构运动学推导/Kmtool.pkg 曲柄滑块机构运动学,五杆机构运动学,七杆机构运动学 本文仅供学习使用,总结很多本现有讲述运动学或动力学书籍后的总结,从矢量的角度进行分析,方法比较传统,但更易理解,并且现有的看似抽象方法,两者本质上并无不同。 2024…

ANAPF有源电力滤波器选型计算——安科瑞赵嘉敏

配电系统中谐波电流的计算涉及很多因素。对于改造项目&#xff0c;可使用专业电能质量分析仪测得所需谐波数据&#xff1b;对于新建项目&#xff0c;设计人员并不能直接获得供电系统的的谐波数据&#xff0c;因此&#xff0c;我司研发人员通过众多不同行业、不同类型的项目&…

图灵之旅--ArrayList顺序表LinkedList链表栈Stack队列Queue

目录 线性表顺序表ArrayList简介ArrayList使用ArrayList的构造ArrayList常见操作ArrayList的遍历ArrayList的扩容机制利用ArrayList洗牌ArrayList的优缺点 链表链表的实现双向链表的实现 LinkedListLinkedList引入LinkedList的使用LinkedList的构造LinkedList的常用方法介绍Lin…

Flink问题解决及性能调优-【Flink根据不同场景状态后端使用调优】

Flink 实时groupby聚合场景操作时&#xff0c;由于使用的是rocksdb状态后端&#xff0c;发现CPU的高负载卡在rocksdb的读写上&#xff0c;导致上游算子背压特别大。通过调优使用hashmap状态后端代替rocksdb状态后端&#xff0c;使吞吐量有了质的飞跃&#xff08;20倍的性能提升…

华为手表开发:WATCH 3 Pro(5)点击按钮弹窗

华为手表开发&#xff1a;WATCH 3 Pro&#xff08;5&#xff09;点击按钮弹窗 初环境与设备 创建项目认识目录结构 修改首页 -> 新建按钮 “ 按钮 ” 文件名&#xff1a;**index.hml** 引用包&#xff1a;‘system.prompt’点击结果 初 鸿蒙可穿戴开发 希望能写一些简…

Spring:JDBCTemplate 的源码分析

一&#xff1a;JdbcTemplate的简介 JdbcTemplate 是 Spring Template设置模式中的一员。类似的还有 TransactionTemplate、 MongoTemplate 等。通过 JdbcTemplate 我们可以使得 Spring 访问数据库的过程简单化。 二&#xff1a;执行SQL语句的方法 1&#xff1a;在JdbcTempla…

手把手教你使用Python打造绚丽的词云图

目录 一、引言 二、环境准备 三、基本流程 四、代码实现 五、进阶技巧与优化 六、总结 一、引言 在信息时代&#xff0c;数据可视化已经成为信息传递的重要手段。词云图作为数据可视化的一种形式&#xff0c;能够直观地展示文本数据中的关键词和重要信息。通过使用Pytho…

故障诊断 | 一文解决,LSTM长短期记忆神经网络故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断模型 | Maltab实现LSTM长短期记忆神经网络故障诊断 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

142. 环形链表 II(力扣LeetCode)

文章目录 142. 环形链表 II题目描述解题思路判断链表是否有环如果有环&#xff0c;如何找到这个环的入口 c代码 142. 环形链表 II 题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个…

Ubuntu 22.04.1 LTS 编译安装 nginx-1.22.1,Nginx动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化

1.Ubuntu 22.04.1 LTS 编译安装 nginx-1.22.1 1.1安装依赖 sudo apt install libgd-dev 1.2下载nginx wget http://nginx.org/download/nginx-1.22.1.tar.gz 1.3解压nginx tar -zvxf nginx-1.22.1.tar.gz 1.4编译安装 cd nginx-1.22.1 编译并指定安装位置&#xff0c;执行安装…