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

news2024/10/1 7:28:43

作者: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.coloradmin.cn/o/919688.html

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

相关文章

【Modbus通信实验三】数据切片问题

在做两个串口相互通信的实验中&#xff0c;当发送频率快一点时偶尔会遇到以下情景&#xff0c;即一次send中把原数据拆成两份发送&#xff0c;就会导致CRC校验错误。下图中6字节数据拆成42是把SetRThreshold()阈值设为2&#xff0c;当设为1的情况下则会拆成51。 一开始以为是缓…

一款轻量级开发者工具,提高开发效率

Devkits Devkits 是一款轻量级桌面端应用&#xff0c;提供了一系列开发者工具&#xff0c;提高开发效率。 离线。类似的在线工具已经不少了&#xff0c;但是大多数都是在线的&#xff0c;网络不好的时候就很难用了。Devkits 提供了离线使用的功能&#xff0c;可以在没有网络的…

16、Flink 的table api与sql之连接外部系统: 读写外部系统的连接器和格式以及JDBC示例(4)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

使用NXP GUI GUIDER生成的GUI移植到雅特力MCU平台过程详解(ST/GD/国民/极海通用)

好记性不如烂笔头&#xff0c;既然不够聪明&#xff0c;就乖乖的做笔记&#xff0c;温故而知新。 本文档用于本人对知识点的梳理和记录 一、前言 上一篇我们有介绍NXP GUI Guider工具如何制作和调试GUI&#xff0c;GUI神器 NXP GUI GUIDER开发工具入门教程https://blog.csdn.n…

【云计算】Docker特别版——前端一篇学会

docker学习 文章目录 一、下载安装docker&#xff08;一&#xff09;Windows桌面应用安装&#xff08;二&#xff09;Linux命令安装 二、windows注册登录docker三、Docker的常规操作(一)、基本的 Docker 命令(二)、镜像操作(三)、容器的配置(四)、登录远程仓库 四、镜像管理(一…

视频转音频mp3怎么弄?

视频转音频mp3怎么弄&#xff1f;在很多人看来&#xff0c;音频就是视频中的一部分&#xff0c;其实这时是一定道理的&#xff0c;视频是一种包含图像和有声音的多媒体文件&#xff0c;没有声音的视频是不完美的。时代发展到现在&#xff0c;短视频已经融入了我们生活的方方面面…

ElementUI中的日历组件加载无效的问题

在ElementUI中提供了一个日历组件。在某些场景下还是比较有用的。只是在使用的时候会有些下坑&#xff0c;大家要注意下。   官网提供的信息比较简介。我们在引入到项目中使用的时候可以能会出现下面的错误提示。 Unknown custom element: <el-calendar> - did you …

【Spring】Spring循环依赖

目录 什么是循环依赖问题 循环依赖具体是怎么解决的 具体的解决步骤&#xff1a; 通俗实例&#xff1a; 严谨的循环依赖解决图例 为什么使用的是三级缓存&#xff0c;二级缓存不够用吗&#xff1f; 什么是循环依赖问题 Spring的循环依赖是指在Bean之间存在相互依赖关…

【教程】手把手教你Termius去除登录并解除限制,非常简单!

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 如果不想关注我&#xff0c;但还想看本文&#xff0c;就去这里吧&#xff0c;无限制&#xff1a;【教程】手把手教你Termius去除登录并解除限制&#xff0c;非常简单&#xff01; - 小锋学长生活大爆炸 这里以Mac…

C语言:整型提升

一、什么是整型提升 C语言的整型算术运算至少是以缺省整型类型的精度来进行的。 为了达到这个精度&#xff0c;算术运算表达式中的 字符型char 和 短整型short 需要被转换为普通整型&#xff0c;这种转换成为整型提升。 二、整型提升的意义 表达式的整型运算需要在CPU相应的运算…

基于Jenkins自动打包并部署docker环境

目录 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.200.111 git git服务器 CentOS7.5 192.168.200.112 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168…

SpringSecurity5.7.10整合Mybatisplus3.5.3.2自定义用户登录逻辑

1、SpringSecurity5.7.0案例功能概述 本案例中采用的是最新版本的springSecurity5.7.10,在就的版本中丢弃了WebSecurityConfigurerAdapter的使用,在使用上发生了很多的变化,本案例中参数变化及具体的使用方式,希望对你有所帮助。 本案例使用springboot2.7.14整合springSe…

【C++】虚函数

2023年8月23日&#xff0c;周三上午 目录 虚函数在派生类中重写虚函数纯虚函数 示例程序 虚函数 在函数返回值前面加上关键字virtual虚函数必须在类中声明&#xff0c;否则会报错“[Error] virtual outside class declaration” class Base { public:virtual void func(); /…

HDLBits-Verilog学习记录 | Verilog Language-Basics(2)

文章目录 9.Declaring wires | wire decl10. 7458 chip 9.Declaring wires | wire decl problem:Implement the following circuit. Create two intermediate wires (named anything you want) to connect the AND and OR gates together. Note that the wire that feeds the …

Easy Rules规则引擎(2-细节篇)

目录 一、序言二、规则引擎参数配置实例1、skipOnFirstAppliedRules示例(1) FizzRule(2) BuzzRule(3) FizzBuzzRule(4) onFizzBuzzRule(5) FizzBuzzRulesLauncher 2、skipOnFirstNonTriggeredRule示例3、skipOnFirstFailedRule示例 三、组合规则1、UnitRuleGroup组合规则2、Act…

Docker容器与虚拟化技术:Docker compose部署LNMP

目录 一、理论 1.LNMP架构 2.背景 3.Dockerfile部署LNMP 3.准备Nginx镜像 4.准备MySQL容器 5.准备PHP镜像 6.上传wordpress软件包 7.编写docker-compose.yml 8.构建与运行docker-compose 9.启动 wordpress 服务 10.浏览器访问 11.将运行中的 docker容器保存为 doc…

react +Antd Cascader级联选择使用接口数据渲染

1获取接口数据并将数据转换成树形数组 useEffect(() > {axios.get(/接口数据, {params: {“请求参数”},}).then((res) > {console.log(res);const getTreeData (treeData, pid) > {// 把数据转化为树型结构let tree [];let currentParentId pid || 0;for (let i …

并发式编程的相关知识--notify和wait、CompletableFuture

1.notify和wait方法的使用 1.1快递到站通知 说明&#xff1a;快递的地点在上海&#xff0c;离快递发货地相聚500km&#xff0c;每次进行改变&#xff0c;快递将会前进100km,当快递前进100km时&#xff0c;需要通知快递当前的位置&#xff0c;当快递到达目的地时&#xff0c;需…

【学习FreeRTOS】第15章——FreeRTOS队列集

1.队列集简介 一个队列只允许任务间传递的消息为同一种数据类型&#xff0c;如果需要在任务间传递不同数据类型的消息时&#xff0c;那么就可以使用队列集&#xff0c;作用&#xff1a;用于对多个队列或信号量进行“监听”&#xff0c;其中不管哪一个消息到来&#xff0c;都可…

Docker拉取并配置Grafana

Linux下安装Docker请参考&#xff1a;Linux安装Docker 安装准备 新建挂载目录 /opt/grafana/data目录&#xff0c;准备用来挂载放置grafana的数据 /opt/grafana/plugins目录&#xff0c;准备用来放置grafana的插件 /opt/grafana/config目录&#xff0c;准备用来挂载放置graf…