.NET 8 Preview 7 中的 ASP.NET Core 更新

作者:Daniel Roth
排版:Alan Wang

.NET 8 Preview 7 现在已经发布,其中包括了对 ASP.NET Core 的许多重要更新。
以下是预览版本中新增功能的摘要:

  • 服务器和中间件
    • 防伪中间件
  • API 编写
    • 最小 API 的防伪集成
  • Native AOT
    • 请求委托生成器支持拦截器功能
    • Full TrimMode 用于启用修剪功能编译的 Web 项目
    • WebApplication.CreateEmptyBuilder
  • Blazor
    • 防伪集成
    • 服务器端表单处理改进
    • Auto 渲染模式
    • 注册 root-level 级联值
    • 改进了交互式组件与服务器端渲染的集成
    • Virtualize 的新参数 EmptyContent
  • Identity
    • 新的承载令牌身份验证处理程序
    • 新的 API 端点
  • 单页应用程序(SPA)
    • 新的 Visual Studio 模板

有关为 .NET 8的 ASP.NET Core 规划的更多详细信息,请参阅 GitHub 上的 .NET 8 的完整 ASP.NET Core 路线图。

入门

如果您想要在 .NET 8 Preview 7 中使用 ASP.NET Core,请安装 .NET 8 SDK。

如果您在 Windows 上使用 Visual Studio,我们建议您安装最新的 Visual Studio 2022 预览版。如果您使用的是 Visual Studio Code,那么可以尝试新的 C# 开发工具包。如果您使用的是 macOS,那么可以在“Preferences”中启用 .NET 8 的预览功能后使用 Visual Studio for Mac 17.6.1 进行开发。

升级现有项目

若要将现有 ASP.NET Core 应用程序从 .NET 8 Preview 6 升级到 .NET 8 Preview 7,请执行以下操作:

  • 将应用程序的目标框架更新为 .NET 8.0
  • 将所有 Microsoft.AspNetCore.* 包引用更新为 8.0.0-preview.7.*
  • 将所有 Microsoft.Extensions.* 包引用更新为 8.0.0-preview.7.*

具体信息请参阅 .NET 8 的 ASP.NET Core 重要更新的完整列表。

服务器和中间件

防伪中间件

此版本添加了一个用于验证防伪令牌以及减轻跨站点请求伪造攻击的中间件。当通过 AddAntiforgery 方法注册防伪服务时,防伪中间件会自动在目标应用程序中启用。

var builder = WebApplication.CreateBuilder();builder.Services.AddAntiforgery();var app = builder.Build();// 由 WebApplicationBuilder 隐式添加
// app.UseAntiforgery();app.Run();

防伪中间件本身不会中断请求流水线的执行。相反,该中间件会在当前请求的 HttpContext.Features 中设置 IAntiforgeryValidationFeature。中间件期望每个框架实现(最小 API、MVC、Blazor 等)都会对此功能做出反应并按预期中断执行。
只有在以下情况下才会验证防伪令牌:

  • 端点包含实现了 IAntiforgeryMetadata 接口的元数据,其中
    RequiresValidation=true
  • 与端点关联的 HTTP 方法是相关 HTTP 方法(不是 TRACE、OPTIONS、HEAD、GET)。
  • 请求与有效端点相关联。

请注意,为了避免在用户未经身份验证时无意中读取表单数据,防伪中间件必须在身份验证和授权中间件之后运行 。

API 编写

最小 API 的防伪集成
现在默认情况下,接受表单数据的最小 API 需要防伪令牌验证。
在下面的代码示例中:

  • 防伪服务在 DI 中注册,因此防伪中间件会自动启用。
  • 提供了两个端点用于显示表单:/antiforgery:会渲染一个带有隐藏防伪令牌字段的表单;/no-antiforgery:则渲染一个没有防伪令牌字段的表单。
  • /todo 端点处理表单中的 Todo 对象,并自动要求防伪令牌验证。
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Mvc;var builder = WebApplication.CreateBuilder();builder.Services.AddAntiforgery();var app = builder.Build();app.MapGet("/antiforgery", (HttpContext context, IAntiforgery antiforgery) =>
{var token = antiforgery.GetAndStoreTokens(context);var html = $"""<html><body><form action="/todo" method="POST" enctype="multipart/form-data"><input name="{token.FormFieldName}" type="hidden" value="{token.RequestToken}" /><input type="text" name="name" /><input type="date" name="dueDate" /><input type="checkbox" name="isCompleted" /><input type="submit" /></form></body></html>""";return Results.Content(html, "text/html");
});app.MapGet("/no-antiforgery", () =>
{var html = """<html><body><form action="/todo" method="POST" enctype="multipart/form-data"><input type="text" name="name" /><input type="date" name="dueDate" /><input type="checkbox" name="isCompleted" /><input type="submit" /></form></body></html>""";return Results.Content(html, "text/html");
});app.MapPost("/todo", ([FromForm] Todo todo) => Results.Ok(todo));app.Run();class Todo
{public string Name { get; set; }public bool IsCompleted { get; set; }public DateTime DueDate { get; set; }
}

/antiforgery 提交表单将会得到一个成功的响应。另一方面,在 /no-antiforgery 提交表单将在运行时产生异常,因为没有提供有效的防伪令牌。在 Production 环境中,这将生成一个日志而不是抛出异常:

Microsoft.AspNetCore.Http.BadHttpRequestException: Invalid antiforgery token found when reading parameter "Todo todo" from the request body as form.
An unhandled exception has occurred while executing the request.
Microsoft.AspNetCore.Http.BadHttpRequestException: Invalid antiforgery token found when reading parameter "Todo todo" from the request body as form.---> Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery request token was not provided in either form field "__RequestVerificationToken" or header value "RequestVerificationToken".at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)at Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)

Native AOT

请求委托生成器支持拦截器功能

.NET 8 Preview 3 中引入的请求委托生成器已更新为使用新的 C# 12 拦截器编译器功能,以支持在运行时使用静态生成的变体拦截对最小 API 的 Map 操作方法的调用。 由于这个变化,用户可以期望在启用 PublishAot 编译中看到应用程序的启动性能有所提高。
下表概述了启动时间的变化情况(即处理在应用程序中所有端点所需的时间)在三种情况下的变化:

  • 基线,端点的 RequestDelegates 通过反射和动态代码生成在运行时生成。在编译时没有拦截器功能生成的端点,是 Preview 3 到 Preview 6 中的默认设置。
  • 在编译时生成的端点,使用了拦截器功能 ,是 Preview 7 中的默认设置。
迭代基线(运行时生成的端点)请求委托生成器(无拦截器)请求委托生成器(带拦截器)
1716.2313毫秒372.5172毫秒31.5255毫秒
2747.279毫秒355.1435毫秒64.188毫秒
3730.975毫秒350.5353毫秒32.9315毫秒
4729.2775毫秒345.8684毫秒34.1169毫秒
5711.0555毫秒351.2683毫秒38.7152毫秒

在这里插入图片描述

Full TrimMode 用于启用修剪功能编译的 Web 项目

在此预览版中,我们引入了一项重大变更将影响通过 PublishTrimmed=true 启用了裁剪的 Web 项目。 在此版本之前,项目默认使用 partial 的 TrimMode。未来,所有面向 .NET 8 或更高版本的项目都将启用 TrimMode=full。有关此重大变更的更多信息,请参阅公告。

WebApplication.CreateEmptyBuilder

我们添加了一个新的 WebApplicationBuilder 工厂方法,用于构建仅包含必要功能的小型应用程序:WebApplication.CreateEmptyBuilder(WebApplicationOptions options)。此 WebApplicationBuilder 是没有内置行为的。您的应用程序将仅包含您配置的服务和中间件。

以下是使用此 API 创建小型 Web 应用程序的示例:

var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrelCore();var app = builder.Build();app.Use(async (context, next) =>
{await context.Response.WriteAsync("Hello, World!");await next(context);
});Console.WriteLine("Running...");
app.Run();

在 linux-x64 计算机上使用 .NET 8 Preview 7 通过 Native AOT 发布此代码会生成约 8.5 MB 的自包含本机可执行文件。

Blazor

防伪集成

Blazor 端点现在默认需要防伪保护。您可以使用新的防伪中间件启用防伪支持,并使用 AntiforgeryToken 组件为渲染的表单生成令牌。EditForm 组件将自动为您添加防伪令牌。

在 Blazor 组件页面中使用 [RequireAntiforgeryToken] 属性来指示组件是否需要防伪投影。 例如,您可以像这样为页面禁用防伪要求(不建议!):

@using Microsoft.AspNetCore.Antiforgery;
@attribute [RequireAntiforgeryToken(required: false)]

服务器端表单处理改进

现在,您可以在使用服务器端渲染且不使用 EditForm 时在 Blazor 中构建标准 HTML 表单。只需使用普通 HTML form 标签创建表单,并指定 @onsubmit 处理程序来处理提交的表单请求。

<form method="post" @formname="contact" @onsubmit="AddContact"><div><label for="name">Name</label><InputText id="name" @bind-Value="NewContact.Name" /></div><div><label for="email">Email</label><InputText id="email" @bind-Value="NewContact.Email" /></div><div><InputCheckbox id="send-me-deals" @bind-Value="NewContact.SendMeDeals" /><label for="send-me-deals">Send me deals</label></div><button>Submit</button><AntiforgeryToken />
</form>@code {[SupplyParameterFromForm]public Contact NewContact { get; set; } = new();public class Contact{public string Name { get; set; }public string Email { get; set; }public bool SendMeDeals { get; set; }}private async Task AddContact(){// Add contact...NewContact = new();}
}

现在,所有服务器端渲染的表单都需要一个名称,该名称用于将提交的请求映射到相应的表单处理程序方法和模型绑定。 要指定普通 HTML 表单的名称,请使用新的 @formname 属性。 使用 EditForm 时,请使用 FormName 参数指定名称。

默认情况下,表单名称必须是唯一的,但您可以使用 FormMappingScope 组件定义表单名称的范围。

<FormMappingScope Name="parent-context"><ComponentWithFormBoundParameter />
</FormMappingScope>

基于 InputBase<TValue> 的输入将生成与 Blazor 用于模型绑定的名称相匹配的表单值名称。您可以使用 [SupplyParameterFromForm] 上的 Name 属性指定 Blazor 用于将表单数据绑定到模型的名称。您还可以使用 Handler 属性指定要绑定其数据的表单的名称(在早期预览中,Name 属性用于此目的)。

要将表单分解为多个子组件,请从 Editor<T> 派生子组件。这将确保您的子组件根据模型生成正确的表单字段名称。

Index.razor

<EditForm Model="Customer" method="post" OnSubmit="DisplayCustomer" FormName="customer"><div><label>Name</label><InputText @bind-Value="Customer.Name" /></div><AddressEditor @bind-Value="Customer.BillingAddress" /><button>Send</button>
</EditForm>@if (submitted)
{<!-- Display customer data --><h3>Customer</h3><p>Name: @Customer.Name</p><p>Street: @Customer.BillingAddress.Street</p><p>City: @Customer.BillingAddress.City</p><p>State: @Customer.BillingAddress.State</p><p>Zip: @Customer.BillingAddress.Zip</p>
}@code {public void DisplayCustomer(){submitted = true;}[SupplyParameterFromForm] Customer? Customer { get; set; }protected override void OnInitialized() => Customer ??= new();bool submitted = false;public void Submit() => submitted = true;
}

AddressEditor.razor

@inherits Editor<Address><div><label for="street">Street</label><InputText id="street" @bind-Value="Value.Street" />
</div>
<div><label for="state">State</label><InputText id="state" @bind-Value="Value.State" />
</div>
<div><label id="city">City</label><InputText for="city" @bind-Value="Value.City" />
</div>
<div><label for="zip">Zip</label><InputText id="zip" @bind-Value="Value.Zip" />
</div>

Blazor 中的模型绑定现在支持绑定到以下附加类型:

  • 递归类型
  • 带有构造函数的类型
  • 枚举

您现在还可以使用 [DataMember][IgnoreDataMember] 属性来自定义您正在编写的类型的模型绑定 。 您可以使用这些属性来重命名属性、忽略属性以及根据需要标记属性。 调用 AddRazorComponents 时,可以从 RazorComponentOptions 获得其他模型绑定选项。

Auto 渲染模式

Blazor Web 应用程序的新 Auto 交互式渲染模式将 ServerWebAssembly 渲染模式的优势结合到一个动态选项中。如果 .NET WebAssembly 运行时可以快速加载(100 毫秒内),则 Auto 渲染模式将使用基于 WebAssembly 的渲染。这种情况通常发生在当运行时之前已下载并缓存或使用高速网络时。否则,当 .NET WebAssembly 运行时在后台下载时,Auto 渲染模式会回退到使用 Server 渲染模式。

如果您要使用 Auto 渲染模式,请在组件实例上指定 @rendermode="@RenderMode.Auto" 属性,或在组件定义上指定 @attribute [RenderModeAuto]。请注意,该组件需要设置为从服务器和浏览器运行,因为它必须位于您的客户端项目中,并且它的实现不得与 ServerWebAssembly 绑定。请查看 Blazor Auto 渲染模式示例,了解如何正确设置。

注册 root-level 级联值

在 Blazor 中,级联值是一种便捷的方式,可以将状态提供给组件层次结构的子树。现在,您可以注册 root-level 级联值,以便整个组件层次结构都可以使用它们。

// 注册固定级联值
services.AddCascadingValue(sp => new MyCascadedThing { Value = 123 });// 按名称注册固定级联值
services.AddCascadingValue("thing", sp => new MyCascadedThing { Value = 123 });// 使用 CascadingValueSource<TValue> 注册级联值
services.AddCascadingValue(sp =>
{var thing = new MyCascadedThing { Value = 456 };var source = new CascadingValueSource<MyCascadedThing>(thing, isFixed: false);return source;
});

改进了交互式组件与服务器端渲染的集成

.NET 8 中的 Blazor 具有先进的服务器端渲染功能,例如增强的导航和表单处理。此预览版改进了交互式组件与服务器端渲染的集成。增强的导航、增强的表单处理和流式渲染现在可以添加和删除交互式组件并对其进行参数设置。

Virtualize 的新参数 EmptyContent

Virtualize 组件现在有一个 EmptyContent 属性,您可以使用该属性来定义在没有项目时或当 ItemsProvider 返回 TotalItemCount 为零时应显示的内容。

感谢 @etemi 的贡献!

Identity

之前在 .NET 8 Preview 4 中,我们添加了新的 Identity API 端点来注册和登录用户,以简化自托管身份管理,使得在单页应用程序 (SPA) 和 Blazor 应用程序中实现和自定义 identity 更加容易。默认体验是基于 cookie 的,因此它“仅适用于”单域应用程序。对于需要令牌的场景,例如从移动客户端访问您的 Web 应用程序,我们现在提供对“内置”令牌的支持。这些令牌是自包含的,并使用与 cookie 身份验证相同的技术来生成。值得注意的是,这些不是 JWT,而是自包含的,并且针对没有委托身份验证的第一方应用程序进行了优化。在多服务器环境中,您需要配置数据保护才能使用共享存储。

承载令牌身份验证处理程序

新的承载令牌身份验证处理程序与 ASP.NET Core 的内置身份验证系统无缝集成。 它可以独立使用(不依赖 ASP.NET Core Identity)。它支持发行和验证令牌。从 Preview 6 开始,它还支持刷新令牌。ASP.NET Core Identity 使用 AddBearerToken 扩展将 handler 与 identity 集成。

Identity API 端点

新的 .NET 8 identity API 端点提供基于 HTTP 的 API :

  • 在 identity 系统中注册新用户
  • 登录并交换经过验证的凭据以获取 cookie 或令牌
  • 使用刷新令牌刷新凭据,使用户保持登录状态,而无需重新输入其凭据
  • 在注册过程中确认电子邮件以进行额外验证
  • 如果未收到或已过期,请重新发送确认电子邮件
  • 重置密码以支持“忘记密码”功能

还有一些受保护的端点需要对用户进行身份验证:

  • 管理双因素身份验证(2FA)。
  • 检索或更新用户 identity 配置文件中的信息,包括声明。

入门

David Fowler 的 identity 端点示例展示了如何配置 identity 以使用新的 handler 和端点。 它还包含一个 .http 文件,用于测试 Visual Studio 内的新端点。

首先,启用新的 handler 并向应用添加身份验证和授权。

builder.Services.AddAuthentication().AddBearerToken(IdentityConstants.BearerScheme);
builder.Services.AddAuthorizationBuilder();

下一步:

  • 映射 identity 模型
  • 为 identity 存储指定 DbContext
  • 选择使用新端点
builder.Services.AddIdentityCore<MyUser>().AddEntityFrameworkStores<AppDbContext>().AddApiEndpoints();

调用 Build() 后,将 identity 端点映射到应用程序中的路由。

app.MapIdentityApi<MyUser>();

现在您可以将 API 配置为使用 identity。此端点访问 identity 以返回登录用户的名称,并且仅适用于经过身份验证的用户。

app.MapGet("/", (ClaimsPrincipal user) => $"Hello {user.Identity!.Name}").RequireAuthorization();

示例会话如下所示:

  1. POST/register 端点以注册用户。
{"user" : "test","password" : "@T35t!","email" : "test@notadomain.xyz"
}
  1. POST/login?cookieMode=false&persistCookies=false 端点以登录用户。
{"user" : "test","password" : "@T35t!"
}
  1. 接收 access_token、expiration 和 refresh_token
{"token_type": "Bearer","access_token": "CfDJ9NHobblyWobblyGobblyGoop...","expires_in": 3600,"refresh_token": "TokenBabbelYabbaDabbaDoo..."
}
  1. 通过将请求的 Authentication 标头设置为 Bearer xxx(其中 xxxaccess_token),使用令牌调用受保护的 API。
  2. 当用户的凭据过期或即将过期时,POST/refresh 端点并传递refresh_token
{"refreshToken": "TokenBabbelYabbaDabbaDoo..."
}
  1. 这将生成新的 access_token、expiration 和 refresh_token

这些新的构建模块可以更轻松地构建非委托验证的身份验证程序。

单页应用程序

新的 Visual Studio 模板

我们一直与 Visual Studio 团队密切合作,以确保 Visual Studio JavaScript 和 TypeScript 开发体验能给 ASP.NET Core 开发人员带来出色的体验。Visual Studio 包含适用于 Angular、React 和 Vue 的新项目模板,这些模板基于新的 JavaScript 项目系统 (.esproj) 构建,并与 ASP.NET Core 后端项目集成。
在这里插入图片描述
这些 Visual Studio 模板为 .NET 和 JavaScript 开发人员提供了丰富的功能:

  • 快速入门 JavaScript 前端和 ASP.NET Core 后端。
  • 及时了解最新的前端框架版本。
  • 与最新的前端框架命令行工具集成。
  • JavaScript 和 TypeScript 的模板。
  • 丰富的 JavaScript 和 TypeScript 代码编辑经验。
  • 清晰的前端和后端项目分离。
  • 将 JavaScript 构建工具与您的 .NET 构建集成。
  • npm 依赖管理 UI。
  • 与 Visual Studio Code 调试和启动配置兼容。
  • 使用您最喜欢的 JavaScript 测试框架在测试资源管理器中运行前端单元测试。

为了专注于为前端 JavaScript 框架与 ASP.NET Core 的使用提供最佳的开发体验,我们从 .NET 8 SDK 中删除了现有的 Angular 和 React 模板,转而采用新的 Visual Studio 模板。 我们正在与 Visual Studio 团队合作,进一步改进带有 ASP.NET Core 模板的新 Visual Studio JavaScript,以支持跨平台开发、与 ASP.NET Core 客户端 Web 资产集成、简化发布并面向所有受支持的 .NET 版本。

您可以通过安装最新的 Visual Studio 预览版,然后按照 Visual Studio 文档中的 Angular、React 和 Vue 教程中的任意一个来尝试新的 Visual Studio JavaScript 模板。 如果您对新模板有反馈,可以使用 Visual Studio 发送反馈工具与我们分享。

提供反馈

我们希望您喜欢 .NET 8 中的 ASP.NET Core 预览版。请在 GitHub 上提交问题,让我们知道您对这些新改进的看法。

感谢您使用 ASP.NET Core!

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

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

相关文章

2023国赛数学建模A题思路模型代码汇总 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

mybatis讲解(2)之动态SQL的运用

目录 经典面试题&#xff1a; 1.mybatis动态sql 2.模糊查询&#xff08;3种方式&#xff09; 3.查询返回结果集 总结&#xff1a; 前言&#xff1a;在我上篇已经学习了Mybatis简介以及如何去连接数据库&#xff0c;具有增删改查的方法。那么我们今天来学习Mybatis的第二节关…

SpringCloud入门实战(十四)Sentinel微服务流量防卫兵简介

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

GitLab与GitLab Runner安装(RPM与Docker方式),CI/CD初体验

背景 GitLab 是一个强大的版本控制系统和协作平台&#xff0c;记录一下在实际工作中关于 GitLab 的安装使用记录。 一开始使用 GitLab 时&#xff0c;是在 CentOS7 上直接以 rpm 包的方式进行安装&#xff0c;仅作为代码托管工具来使用&#xff0c;版本&#xff1a; 14.10.4 …

人机界面通过RJ45口无线连接多台PLC

人机界面是系统和用户之间进行交互和信息交换的媒介&#xff0c;它实现信息的内部形式与人类可以接受形式之间的转换。人机界面产品由硬件和软件两部分组成&#xff0c;硬件部分包括处理器、显示单元、输入单元、通讯接口、数据存贮单元等&#xff0c;HMI软件一般分为两部分&am…

React+Typescript 父子组件事件传值

好 之前我们将 state 状态管理简单过了一下 那么 本文 我们来研究一下事假处理 点击事件上文中我们已经用过了 这里 我们就不去讲了 主要来说说 父子之间的事件 我们直接来编写一个小dom 我们父组件 编写代码如下 import Hello from "./components/hello";functio…

opencv-dnn

# utils_words.txt 标签文件 import osimage_types (".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff")def list_images(basePath, containsNone):# return the set of files that are validreturn list_file…

iPhone卫星通信SOS功能如何在灾难中拯救生命

iPhone上的卫星紧急求救信号功能在从毛伊岛野火中拯救一家人方面发挥了至关重要的作用。这是越来越多的事件的一部分&#xff0c;在这些事件中&#xff0c;iPhone正在帮助人们摆脱危及生命的情况。 卫星提供商国际通信卫星组织负责移动的高级副总裁Mark Rasmussen在接受Lifewir…

WPS office 最新未公开 0Day漏洞警示

一、事件描述 近日&#xff0c;网传监测发现WPS Office for Windows版本 存在0day漏洞&#xff0c;攻击者可以利用该0day漏洞在受害者主机上执行任意恶意文件&#xff0c;高危级别&#xff0c;官方尚未对此发布修复漏洞&#xff0c;目前建议只能临时弃用wps或者不要点开未知文件…

flink checkpoint时exact-one模式和atleastone模式的区别

背景&#xff1a; flink在开启checkpoint的时候有两种模式可以选择&#xff0c;exact-one和atleastone模式&#xff0c;那么这两种模式有什么区别呢&#xff1f; exact-one和atleastone模式的区别 先说结论&#xff1a;exact-one可以完全做到状态的一致性&#xff0c;而atle…

Elasticsearch 入门安装

1.Elasticsearch 是什么 The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash&#xff08;也称为 ELK Stack&#xff09;。能够安全可靠地获取任何来源、任何格式的数据&#xff0c;然后实时地对数据进行搜索、分析和可视化。 Elaticsearch&#xff0c;简称为…

Fabric.js 元素选中状态的事件与样式

本文简介 带尬猴&#xff01; 你是否在使用 Fabric.js 时希望能在选中元素后自定义元素样式或选框&#xff08;控制角和辅助线&#xff09;的样式&#xff1f; 如果是的话&#xff0c;可以放心往下读。 本文将手把脚和你一起过一遍 Fabric.js 在对象元素选中后常用的样式设置…

无涯教程-PHP - sql_regcase()函数

sql_regcase() - 语法 string sql_regcase (string string) 可以将sql_regcase()函数视为实用程序函数&#xff0c;它将输入参数字符串中的每个字符转换为包含两个字符的带括号的表达式。 sql_regcase() - 返回值 返回带括号的表达式字符串以及转换后的字符。 sql_regcase…

微信小程序 车牌号输入组件

概述 一个小组件&#xff0c;用于方便用户输入车牌号码 详细 概述 有时候我们开发过程中会遇到需要用户输入车牌号的情况&#xff0c;让客户通过自带键盘输入&#xff0c;体验不好且容易出错&#xff0c;例如车牌号是不能输入O和I的&#xff0c;因此需要有一个自定义的键盘…

【VR】SteamVR2.0的示例场景在哪里

&#x1f4a6;本专栏是我关于VR开发的笔记 &#x1f236;本篇是——在哪里可以找到SteamVR2.0的示例场景 SteamVR2.0的示例场景在哪里 1. 逐步打开方式2. 快速打开方式 1. 逐步打开方式 Assets——SteamVR——InteractionSystem——Samples——>Interactions_Example 2. 快…

CDN、DNS、ADN、SCDN、DCDN、ECDN、PCDN、融合CDN傻傻分不清楚,一文全部搞懂

一、CDN是什么&#xff1f; CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输得更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之…

Wireshark数据抓包分析之传输层协议(TCP协议)

一、实验目的&#xff1a; 通过使用wireshark对TCP协议的数据包的抓取分析TCP协议的具体内容 二、预备知识: 1.需要了解TCP协议的三次握手过程 2.需要了解TCP协议的四次挥手的过程 三、网络拓扑 四、实验过程&#xff1a; part1&#xff1a;3次握手和4次挥手的数据包的获取 …

【ThingJS | 3D可视化】开发框架,一站式数字孪生

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; 数字孪生 | 3D可视化框架 开发工具&#xff1a;ThingJS在线开发工具 ThingJs 低代码开发 ThingJs 低代码开发注意点场景效果配置层级层级常用API实例化 Thing&#xff0c;加载场景load 加载函数ThingJs 层级关系图查找层…

睿思BI旗舰版V5.3正式发布

发布时间&#xff1a;2023-7-20 主要更新内容: 1.增加3D地图功能 2.增加水球图 3.增加扇形图&#xff0c;在数据大屏 - 自定义组件中定义。 4.增加指标引导线功能&#xff0c;在数据大屏 - 自定义组件中定义。 5.详情页增加回调函数功能。 6.大屏/仪表盘模版下载&#xff0c;…

排序算法:选择排序

选择排序的思想是&#xff1a;双重循环遍历数组&#xff0c;每经过一轮比较&#xff0c;找到最小元素的下标&#xff0c;将其交换至首位。 public static void selectionSort(int[] arr) {int minIndex;for (int i 0; i < arr.length - 1; i) {minIndex i;for (int j i …