【WebApi】C#创建WebApi学习

1、创建WebApi项目

Prgram.cs代码保留如下

var builder = WebApplication.CreateBuilder(args); // Add services to the container. var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.Run(); 

2、Minmal APIs最小API使用

Prgram.cs中进行最小API使用

var builder = WebApplication.CreateBuilder(args); // Add services to the container. var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); //获取所有衬衫数据列表 app.MapGet("/shirts", () => { return "获取所有衬衫数据列表"; }); //获取指定ID的衬衫数据 app.MapGet("/shirts/{id}", (int id) => { return $"获取ID为 {id} 的衬衫数据"; }); //创建一件新的衬衫 app.MapPost("/shirts", () => { return "创建一件新的衬衫"; }); //更新指定ID的衬衫数据 app.MapPut("/shirts/{id}", (int id) => { return $"更新ID为 {id} 的衬衫数据"; }); //删除指定ID的衬衫数据 app.MapDelete("/shirts/{id}", (int id) => { return $"删除ID为 {id} 的衬衫数据"; }); app.Run(); 

3、ASP.NET Core中间件管道

app中的Use开头的方法都是中间件组件使用方法

4、Web API控制器实现Web API

方法1:将路由写在方法前面并指定操作动词

using Microsoft.AspNetCore.Mvc; namespace WebApiTest.Controllers { [ApiController] public class ShirtsController : ControllerBase { //获取所有衬衫数据列表 [HttpGet] [Route("api/shirts")] public string GetShirts() { return "获取所有衬衫数据列表"; } //获取指定ID的衬衫数据 [HttpGet] [Route("api/shirts/{id}")] public string GetShirtById(int id) { return $"获取ID为 {id} 的衬衫数据"; } //创建一件新的衬衫 [HttpPost] [Route("api/shirts")] public string CreateShirt() { return "创建一件新的衬衫"; } //更新指定ID的衬衫数据 [HttpPut] [Route("api/shirts/{id}")] public string UpdateShirt(int id) { return $"更新ID为 {id} 的衬衫数据"; } //删除指定ID的衬衫数据 [HttpDelete] [Route("api/shirts/{id}")] public string DeleteShirt(int id) { return $"删除ID为 {id} 的衬衫数据"; } } } 

方法2:将路由写在类前面,再在方法前面指定操作动词

using Microsoft.AspNetCore.Mvc; namespace WebApiTest.Controllers { [ApiController] [Route("/api/[controller]")] public class ShirtsController : ControllerBase { //获取所有衬衫数据列表 [HttpGet] public string GetShirts() { return "获取所有衬衫数据列表"; } //获取指定ID的衬衫数据 [HttpGet("{id}")] public string GetShirtById(int id) { return $"获取ID为 {id} 的衬衫数据"; } //创建一件新的衬衫 [HttpPost] public string CreateShirt() { return "创建一件新的衬衫"; } //更新指定ID的衬衫数据 [HttpPut("{id}")] public string UpdateShirt(int id) { return $"更新ID为 {id} 的衬衫数据"; } //删除指定ID的衬衫数据 [HttpDelete("{id}")] public string DeleteShirt(int id) { return $"删除ID为 {id} 的衬衫数据"; } } } 

5、基于控制器的Web API的路由

使用注解[Route("/shirts")]设置Web API的URL,可以在方法前使用,也可以在类前使用

方法前

类前

6、模型绑定,将Http请求中的数据映射到操作方法的参数

6.1 从路由绑定,在路由Route("/shirts/{id}")或在操作动词HttpGet("{id}")设置,在方法参数前设置[FromRoute]也可以省略

 [HttpGet("{id}")] public string GetShirtById([FromRoute]int id) { return $"获取ID为 {id} 的衬衫数据"; }

6.2 从查询字符串中绑定,方法参数前使用注解[FromQuery]

http://localhost:5186/api/shirts/1?color=红色

 [HttpGet("{id}")] public string GetShirtById([FromRoute]int id, [FromQuery]string color) { return $"获取ID为 {id} 的衬衫数据"; }

6.3 从请求头Header中绑定,方法参数前使用注解[FromHeader]

 [HttpGet("{id}")] public string GetShirtById([FromRoute]int id, [FromQuery]string color, [FromHeader]int size) { return $"获取ID为 {id} 的衬衫数据,衬衫颜色为{color},大小为{size}"; }

6.4 从请求体Body JSON格式中绑定,方法参数前使用注解[FromBody]

 [HttpPost] public string CreateShirt([FromBody]Shirt shirt) { return $"创建一件新的衬衫,{shirt.Id}, {shirt.Name}, {shirt.Color}, {shirt.Gender}, {shirt.Price}"; }

6.5 从请求体Body 表单中绑定,方法参数前使用注解[FromForm]

 [HttpPost] public string CreateShirt([FromForm]Shirt shirt) { return $"创建一件新的衬衫,{shirt.Id}, {shirt.Name}, {shirt.Color}, {shirt.Gender}, {shirt.Price}"; }

7、数据注解模型验证

8、ValidationAtteibute模型验证,继承ValidationAttribute

创建脚本Shirt_EnsureCorrectSizingAttribute.cs

using System.ComponentModel.DataAnnotations; using WebApiDemo.Models; namespace WebApiTest.Models.Validations { public class Shirt_EnsureCorrectSizingAttribute : ValidationAttribute { protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { var shirt = validationContext.ObjectInstance as Shirt; if(shirt != null && !string.IsNullOrEmpty(shirt.Gender)) { if(shirt.Gender.Equals("men", StringComparison.OrdinalIgnoreCase) && shirt.Size < 8) { return new ValidationResult("男性衬衫的尺码必须大于或等于8。"); } else if (shirt.Gender.Equals("women", StringComparison.OrdinalIgnoreCase) && shirt.Size < 6) { return new ValidationResult("女性衬衫的尺码必须大于或等于6。"); } } return ValidationResult.Success; } } } 

在属性前添加注解

9、Web API返回类型

返回类型使用IActionResult

正确返回使用  Ok(返回数据)

未找到使用     NotFound()

错误响应使用  BadRequest()

 [HttpGet("{id}")] public IActionResult GetShirtById([FromRoute]int id, [FromQuery]string color, [FromHeader]int size) { if(id <= 0) { //错误响应 return BadRequest(); } else if(id > 10) { //未找到 return NotFound(); } //正确响应 return Ok($"获取ID为 {id} 的衬衫数据,衬衫颜色为{color},大小为{size}"); }

10、操作过滤器进行模型验证,继承ActionFilterAttribute

用户输入传递的id可能不符合规范,可以通过操作过滤器进行模型验证对id进行验证

创建脚本Shirt_ValidateShirtIdFilterAttribute

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace WebApiTest.Filters.ActionFilters { public class Shirt_ValidateShirtIdFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { base.OnActionExecuting(context); var id = context.ActionArguments["id"] as int?; if (id.HasValue) { if(id.Value <= 0) { context.ModelState.AddModelError("Id", "衬衫ID必须大于0。"); var problemDetails = new Microsoft.AspNetCore.Mvc.ValidationProblemDetails(context.ModelState) { Status = 400, Title = "请求参数错误", }; context.Result = new BadRequestObjectResult(problemDetails); } } } } } 

需要使用验证的方法前添加注解

11、异常过滤器实现异常处理

更新衬衫之前可能其他请求把该衬衫已经删掉,更新时可能会报错,模拟该情景

创建脚本Shirt_HandleUpdateExceptionFilterAttribute

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace WebApiTest.Filters.ExceptionFilters { public class Shirt_HandleUpdateExceptionFilterAttribute : ExceptionFilterAttribute { public int?[] shirtsId = new int?[] { 1, 2, 3, 4, 5 }; public override void OnException(ExceptionContext context) { base.OnException(context); //判断衬衫ID是否存在 暂时假设shirtsId为数据库中已有的衬衫ID列表 var strShirtId = context.RouteData.Values["id"] as string; if (int.TryParse(strShirtId, out int shirtId)) { if (shirtsId.FirstOrDefault(x => x == shirtId) == null) { context.ModelState.AddModelError("Id", $"衬衫已经不存在"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = StatusCodes.Status404NotFound, }; context.Result = new NotFoundObjectResult(problemDetails); } } } } } 

在需要异常处理的方法前使用

12、Web API操作数据库

案例使用SqlServer数据库

12.1 下载安装Sql Server Developer Edition和SQL Server Management Studio

Sql Server Developer Edition

SQL Server Management Studio

打开SQL Server Management Studio连接本地数据库

12.2 安装需要使用的包

  • EntityFrameworkCore
  • EntityFrameworkCore.Design
  • EntityFrameworkCore.Tools
  • EntityFrameworkCore.SqlServer

1)打开 管理NuGet程序包

2)搜索安装指定的包

3)双击查看是否安装成功

12.3 创建数据库上下文

1)创建脚本ApplicationDbContext

using Microsoft.EntityFrameworkCore; using WebApiDemo.Models; namespace WebApiTest.Data { public class ApplicationDbContext : DbContext { public DbSet<Shirt> Shirts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //数据播种 modelBuilder.Entity<Shirt>().HasData( new Shirt { Id = 1, Name = "衬衫1", Color = "red", Gender = "men", Size = 10, Price = 100 }, new Shirt { Id = 2, Name = "衬衫2", Color = "blue", Gender = "men", Size = 12, Price = 140 }, new Shirt { Id = 3, Name = "衬衫3", Color = "黑色", Gender = "wemen", Size = 11, Price = 132 }, new Shirt { Id = 4, Name = "衬衫4", Color = "白色", Gender = "wemen", Size = 7, Price = 151 } ); } } } 

12.4 执行数据库迁移

1)添加连接字符串

2)获取连接字符串,视图->服务器资源管理器->数据连接

//需要将master替换为需要创建的数据库名称 Data Source=(local);Initial Catalog=master;Integrated Security=True;Trust Server Certificate=True

3)数据库上下文中创建构造函数指定连接数据库位置

using Microsoft.EntityFrameworkCore; using WebApiDemo.Models; namespace WebApiTest.Data { public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } public DbSet<Shirt> Shirts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //数据播种 modelBuilder.Entity<Shirt>().HasData( new Shirt { Id = 1, Name = "衬衫1", Color = "red", Gender = "men", Size = 10, Price = 100 }, new Shirt { Id = 2, Name = "衬衫2", Color = "blue", Gender = "men", Size = 12, Price = 140 }, new Shirt { Id = 3, Name = "衬衫3", Color = "黑色", Gender = "wemen", Size = 11, Price = 132 }, new Shirt { Id = 4, Name = "衬衫4", Color = "白色", Gender = "wemen", Size = 7, Price = 151 } ); } } }

4)在Progam.cs添加运行EntityFrameworkCore所需的服务

builder.Services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("ShirtStoreManagement")); });

5)创建迁移代码并进行迁移

控制台运行命令Add-Migration Init(Init可以替换为该次进行操作说明)

运行成功会创建在迁移文件夹下创建迁移代码

在控制台运行迁移代码,Update-Database Init(Init为迁移代码名称,不指定会执行最新的代码)

执行成功可以在查看数据库创建成功

12.5 使用EF Core实现Get端点

在ShirtsController构造函数中依赖注入Db上下文

 //获取所有衬衫数据列表 [HttpGet] public IActionResult GetShirts() { return Ok(db.Shirts.ToList()); }

12.6 使用EF Core实现Get by Id端点

修改Shirt_ValidateShirtIdFilterAttribute,实现验证ID在数据库是否存在

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiTest.Data; namespace WebApiTest.Filters.ActionFilters { public class Shirt_ValidateShirtIdFilterAttribute : ActionFilterAttribute { private readonly ApplicationDbContext db; public Shirt_ValidateShirtIdFilterAttribute(ApplicationDbContext db) { this.db = db; } public override void OnActionExecuting(ActionExecutingContext context) { base.OnActionExecuting(context); var id = context.ActionArguments["id"] as int?; if (id.HasValue) { if(id.Value <= 0) { context.ModelState.AddModelError("Id", "衬衫ID必须大于0。"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = 400, Title = "请求参数错误", }; context.Result = new BadRequestObjectResult(problemDetails); } else { var shirt = db.Shirts.Find(id.Value); if(shirt == null) { context.ModelState.AddModelError("Id", $"ID为{id.Value}的衬衫在数据库不存在"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = 400, Title = "衬衫ID不存在", }; context.Result = new NotFoundObjectResult(problemDetails); } else { context.HttpContext.Items["shirt"] = shirt; } } } } } } 

在操作过滤器中查询数据库存在ID衬衫在context.HttpContext.Items中进行存在,然后在控制器中获取,避免重复进行数据库查询减少性能开销

控制器查询代码

 //获取指定ID的衬衫数据 [HttpGet("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] public IActionResult GetShirtById([FromRoute]int id) { //正确响应 return Ok(HttpContext.Items["shirt"]); }

12.7 使用EF Core实现Post端点

 //创建一件新的衬衫 [HttpPost] public IActionResult CreateShirt([FromBody]Shirt shirt) { this.db.Shirts.Add(shirt); this.db.SaveChanges(); return CreatedAtAction(nameof(GetShirtById), new { id = shirt.Id}, shirt); }

12.8 使用EF Core实现Put端点

修改代码Shirt_HandleUpdateExceptionFilterAttribute,实现验证当前ID数据是否还存在,可能存在当前操作之前数据被删除的可能

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiTest.Data; namespace WebApiTest.Filters.ExceptionFilters { public class Shirt_HandleUpdateExceptionFilterAttribute : ExceptionFilterAttribute { private readonly ApplicationDbContext db; public Shirt_HandleUpdateExceptionFilterAttribute(ApplicationDbContext db) { this.db = db; } public override void OnException(ExceptionContext context) { base.OnException(context); //判断衬衫ID是否存在 暂时假设shirtsId为数据库中已有的衬衫ID列表 var strShirtId = context.RouteData.Values["id"] as string; if (int.TryParse(strShirtId, out int shirtId)) { if (this.db.Shirts.FirstOrDefault(x => x.Id == shirtId) == null) { context.ModelState.AddModelError("Id", $"衬衫已经在数据库不存在,可能在此之前被删除了"); var problemDetails = new ValidationProblemDetails(context.ModelState) { Status = StatusCodes.Status404NotFound, }; context.Result = new NotFoundObjectResult(problemDetails); } } } } } 

控制器更新代码

 //更新指定ID的衬衫数据 [HttpPut("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] [TypeFilter(typeof(Shirt_HandleUpdateExceptionFilterAttribute))] public IActionResult UpdateShirt(int id, [FromBody]Shirt shirt) { var shirtToUpdate = HttpContext.Items["shirt"] as Shirt; shirtToUpdate.Name = shirt.Name; shirtToUpdate.Size = shirt.Size; shirtToUpdate.Color = shirt.Color; shirtToUpdate.Gender = shirt.Gender; shirtToUpdate.Price = shirt.Price; this.db.SaveChanges(); return Ok($"ID为{id}衬衫更新成功"); }

12.9 使用EF Core实现Delete端点

 //删除指定ID的衬衫数据 [HttpDelete("{id}")] [TypeFilter(typeof(Shirt_ValidateShirtIdFilterAttribute))] public IActionResult DeleteShirt(int id) { var shirtToDelete = HttpContext.Items["shirt"] as Shirt; this.db.Shirts.Remove(shirtToDelete); this.db.SaveChanges(); return Ok(shirtToDelete); }

13、Web Api安全机制,使用JWT生成令牌和验证令牌

1)创建应用程序信息类,Application.cs

namespace WebApiDemo.Authority { public class Application { public int ApplicationId { get; set; } public string? ApplicationName { get; set; } public string? ClientId { get; set; } public string? Secret { get; set; } public string? Scopes { get; set; } } } 

2)创建应用内容存储,AppPepository.cs,替代已存储数据库的应用程序注册信息

namespace WebApiDemo.Authority { public static class AppPepository { private static List<Application> _applications = new List<Application> { new Application { ApplicationId = 1, ApplicationName = "MVCWebApp", ClientId = "53D3C1E6-4587-4AD5-8C6E-A8E4BD59940E", Secret = "0673FC70-0514-4011-B4A3-DF9BC03201BC", Scopes = "read,write,delete" } }; public static Application? GetApplicationByClientId(string clientId) { return _applications.FirstOrDefault(app => app.ClientId == clientId); } } } 

3)创建应用凭证类,AppCredential.cs,用于接受认证请求参数

namespace WebApiDemo.Authority { public class AppCredential { public string? ClientId { get; set; } = string.Empty; public string? Secret { get; set; } = string.Empty; } } 

4)创建应用认证控制器接口,AuthorityController.cs

using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using System.Text; using WebApiDemo.Authority; namespace WebApiDemo.Controllers { [ApiController] public class AuthorityController : ControllerBase { private readonly IConfiguration configuration; public AuthorityController(IConfiguration configuration) { this.configuration = configuration; } [HttpPost("auth")] public IActionResult Authenticate([FromBody] AppCredential credential) { if (Authenticator.Authenticate(credential.ClientId, credential.Secret)) { var expiresAt = DateTime.UtcNow.AddMinutes(10); return Ok(new { access_token = Authenticator.CreateToken(credential.ClientId, expiresAt, configuration["SecurityKey"] ?? string.Empty), expores_at = expiresAt }); } else { ModelState.AddModelError("Unanthorized", "未被授权"); var problemDetails = new ValidationProblemDetails(ModelState) { Status = StatusCodes.Status401Unauthorized, }; return new UnauthorizedObjectResult(problemDetails); } } } } 

5)设置密钥

6)创建应用认证身份验证逻辑类,Authenticator.cs

using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using System.Security.Claims; namespace WebApiDemo.Authority { public static class Authenticator { public static bool Authenticate(string clientId, string secret) { var app = AppPepository.GetApplicationByClientId(clientId); if (app == null) return false; return (app.ClientId == clientId && app.Secret == secret); } public static string CreateToken(string clientId, DateTime expiresAt, string strSecretKey) { //安全算法 //签名密钥 //负载(声明) //生成签名 //算法 var signingCredentials = new SigningCredentials( new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(strSecretKey)), SecurityAlgorithms.HmacSha256Signature); //负载(声明) var app = AppPepository.GetApplicationByClientId(clientId); var clamsDictionary = new Dictionary<string, object> { { "AppName", app?.ApplicationName??string.Empty }, //{ "Read", (app?.Scopes??string.Empty).Contains("read") ? "true" : "false" }, //{ "Write", (app?.Scopes??string.Empty).Contains("write") ? "true" : "false" } }; var scopes = app?.Scopes?.Split(',') ?? Array.Empty<string>(); if(scopes.Length > 0) { foreach(var scope in scopes) { clamsDictionary.Add(scope.Trim().ToLower(), "true"); } } var tokenDescriptor = new SecurityTokenDescriptor { SigningCredentials = signingCredentials, Claims = clamsDictionary, Expires = expiresAt, NotBefore = DateTime.UtcNow, }; var tokenHandler = new JsonWebTokenHandler(); return tokenHandler.CreateToken(tokenDescriptor); } public static async Task<IEnumerable<Claim>?> VerifyTokenAsync(string tokenString, string securityKey) { if(string.IsNullOrWhiteSpace(tokenString) || string.IsNullOrWhiteSpace(securityKey)) { return null; } var keyBytes = System.Text.Encoding.UTF8.GetBytes(securityKey); var tokenHandle = new JsonWebTokenHandler(); var validationParameters = new TokenValidationParameters { ValidateIssuer = false, IssuerSigningKey = new SymmetricSecurityKey(keyBytes), ValidateIssuerSigningKey = false, ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; try { var result = await tokenHandle.ValidateTokenAsync(tokenString, validationParameters); if(result.SecurityToken != null) { var tokenObject = tokenHandle.ReadJsonWebToken(tokenString); return tokenObject.Claims ?? Enumerable.Empty<Claim>(); } else { return null; } } catch (SecurityTokenMalformedException) { return null; } catch (SecurityTokenExpiredException) { return null; } catch (SecurityTokenInvalidSignatureException) { return null; } catch (Exception) { throw; } } } } 

7)通过过滤器方式实现JWT令牌验证

using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using WebApiDemo.Attributes; using WebApiDemo.Authority; namespace WebApiDemo.Filters.AuthFilters { public class JwtTokenAuthFilterAttribute : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { //1. 从请求头中获取授权标识 if (!context.HttpContext.Request.Headers.TryGetValue("Authorization", out var authHeader)) { context.Result = new UnauthorizedResult(); return; } string tokenString = authHeader.ToString(); //2. 去掉Bearer前缀 if (tokenString.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { tokenString = tokenString.Substring("Bearer ".Length).Trim(); } else { context.Result = new UnauthorizedResult(); return; } //3. 获取配置和安全密钥 var configuration = context.HttpContext.RequestServices.GetService<IConfiguration>(); var securityKey = configuration?["SecurityKey"] ?? string.Empty; //4. 验证令牌 并且 提取声明 //if(!await Authenticator.VerifyTokenAsync(tokenString, securityKey)) //{ // context.Result = new UnauthorizedResult(); //} var claims = await Authenticator.VerifyTokenAsync(tokenString, securityKey); if (claims == null) { context.Result = new UnauthorizedResult(); // 无效令牌 401 } else { //5. 获取声明需求 var requiredClaism = context.ActionDescriptor.EndpointMetadata .OfType<RequiredClaimAttribute>() .ToList(); if(requiredClaism != null && !requiredClaism.All(rc => claims.Any(c => c.Type.Equals(rc.ClaimType, StringComparison.OrdinalIgnoreCase) && c.Value.Equals(rc.ClaimValue, StringComparison.OrdinalIgnoreCase)))) { context.Result = new StatusCodeResult(403); // 权限不足 403 } } } } } 

8)授权、权限作用域校验类,RequiredClaimAttribute.cs

namespace WebApiDemo.Attributes { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple = true)] public class RequiredClaimAttribute : Attribute { public string ClaimType { get; } public string ClaimValue { get; } public RequiredClaimAttribute(string claimType, string claimValue) { this.ClaimType = claimType; this.ClaimValue = claimValue; } } } 

Read more

《Science》观点解读:AI无法创造真正的智能体(AI Agent)

《Science》观点解读:AI无法创造真正的智能体(AI Agent)

无论是想要学习人工智能当做主业营收,还是像我一样作为开发工程师但依然要运用这个颠覆开发的时代宠儿,都有必要了解、学习一下人工智能。         近期发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,入行门槛低,讲解极为丰富。          点击跳转:前言 – 人工智能教程 目录 《Science》观点解读:AI无法创造真正的智能体(AI Agent) 前言 一、大模型的"超能力"从何而来? 1、如何理解大模型的核心运作逻辑 2、大模型的文化技术本质 二、为何说"超级智能体"是个伪命题? 三、结语         作者:watermelo37         ZEEKLOG万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。         一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、

零基础学AI大模型之嵌入模型性能优化

零基础学AI大模型之嵌入模型性能优化

大家好,我是工藤学编程 🦉一个正在努力学习的小博主,期待你的关注实战代码系列最新文章😉C++实现图书管理系统(Qt C++ GUI界面版)SpringBoot实战系列🐷【SpringBoot实战系列】SpringBoot3.X 整合 MinIO 存储原生方案分库分表分库分表之实战-sharding-JDBC分库分表执行流程原理剖析消息队列深入浅出 RabbitMQ-RabbitMQ消息确认机制(ACK)AI大模型零基础学AI大模型之LangChain Embedding框架全解析 前情摘要 前情摘要 1、零基础学AI大模型之读懂AI大模型 2、零基础学AI大模型之从0到1调用大模型API 3、零基础学AI大模型之SpringAI 4、零基础学AI大模型之AI大模型常见概念 5、零基础学AI大模型之大模型私有化部署全指南 6、零基础学AI大模型之AI大模型可视化界面 7、零基础学AI大模型之LangChain 8、零基础学AI大模型之LangChain六大核心模块与大模型IO交互链路 9、零基础学AI大模型之Prompt提示词工程 10、零基础学AI大模型之Lan

软件测试中引入人工智能(AI)

在软件测试中引入人工智能(AI),能够解决传统测试的痛点(如重复劳动多、回归测试成本高、难以覆盖复杂场景、缺陷定位慢等),实现测试的自动化、智能化、高效化。以下是AI在软件测试中的核心应用场景、技术方案、工具及实施步骤,兼顾理论与实操。 一、 AI在软件测试中的核心价值 1. 替代重复手工劳动:自动生成测试用例、执行测试、回归验证,减少人力成本。 2. 覆盖复杂场景:模拟真实用户的随机操作、边界场景、异常流,提升测试覆盖率。 3. 提前发现潜在缺陷:通过数据分析预测高风险模块,精准定位缺陷根因。 4. 自适应动态测试:根据软件版本迭代,自动更新测试用例,适配界面/功能变化。 二、 AI在软件测试中的核心应用场景 1. 测试用例智能生成 传统测试用例需人工编写,耗时且易遗漏场景;AI可基于需求文档、代码、历史测试数据自动生成用例。 * 技术原理: * 自然语言处理(NLP)

用快马ai快速原型一个永久在线crm网站,验证你的产品思路

最近在验证一个CRM产品的市场可行性,需要快速搭建一个能永久在线的基础原型。传统开发流程从环境搭建到功能实现至少需要一周,而通过InsCode(快马)平台的AI辅助,我用不到半天就完成了核心功能验证。以下是具体实践过程: 1. 明确最小可行功能集 原型系统聚焦四个核心模块:客户信息管理(基础CRUD)、销售机会跟踪(状态流转)、数据仪表盘(关键指标可视化)、基础权限控制(管理员/用户视图)。这种设计能覆盖80%的CRM基础使用场景,避免陷入细节开发。 2. AI生成基础框架 在平台输入"React+Node.js的CRM系统,包含客户管理、跟进记录和仪表盘",AI在10秒内生成了包含路由配置、API接口定义和基础组件的脚手架代码。特别惊喜的是自动配置好了MongoDB连接模块,省去了手动安装驱动和写连接池代码的时间。 3. 客户模块快速迭代 * 客户信息表单通过AI生成的React Hook自动绑定数据 * 地址字段智能识别省市区三级联动需求,自动补全地区选择器组件 * 联系方式验证逻辑直接内置了手机号/邮箱的正则校验 4. 销售跟踪状