解锁C#数据校验:从基础到实战的进阶之路
一、引言:数据校验为何如此重要?
在软件开发的广袤领域中,数据校验宛如一座坚固的堡垒,守护着系统的稳定与安全。它是确保数据质量的关键防线,能有效避免错误数据的流入,进而提升系统的整体性能和可靠性。无论是在金融交易、医疗记录管理,还是电商平台的订单处理等场景中,数据校验都扮演着不可或缺的角色。
想象一下,在一个在线银行系统中,如果没有严格的数据校验机制,用户可能会输入错误的账号信息,导致资金转账错误;或者恶意用户可能会尝试篡改交易数据,引发严重的安全漏洞。这些错误数据不仅会给用户带来直接的经济损失,还会严重损害银行的信誉和声誉。
再比如,在电商平台上,订单数据的准确性至关重要。如果商品数量、价格等信息在传输或存储过程中出现错误,可能会导致商家发货错误,引发客户投诉,甚至影响整个供应链的正常运转。
由此可见,数据校验是保障系统稳定运行、保护用户权益、维护企业信誉的重要手段。在 C# 开发中,我们有多种强大的工具和技术来实现数据校验,接下来就让我们一同深入探索其中的奥秘。
二、C# 特性的基础知识:特性是什么?
在 C# 的编程世界里,特性(Attribute)是一种特殊的类,它派生自System.Attribute基类 。特性就像是代码的 “注释精灵”,不过它可不只是给人看的简单说明,而是实实在在参与到程序运行中的重要角色。通过特性,我们可以为代码元素(如类、方法、属性、字段等)添加额外的元数据信息,这些信息能够在运行时通过反射机制被访问和利用,从而实现各种强大的功能。
比如,[Obsolete]特性就是一个非常实用的例子。假设我们有一个旧的方法OldMethod,随着程序的更新迭代,这个方法已经不再推荐使用,我们希望开发者在使用它的时候能够得到提醒,转而使用新的方法。这时候,[Obsolete]特性就派上用场了。我们可以这样标记它:
[Obsolete("This method is deprecated. Use NewMethod instead.")]
public void OldMethod()
{// 方法实现
}
当其他开发者在代码中调用OldMethod时,编译器会发出警告,提示该方法已过时,并建议使用NewMethod。这样一来,就有效地避免了开发者继续使用旧方法,保证了代码的一致性和可维护性。
除了[Obsolete]特性,C# 还提供了许多其他内置特性,如[Serializable]特性用于指示一个类可以被序列化,以便在不同的应用程序域或进程之间传输对象;[DllImport]特性用于调用非托管代码,允许我们在 C# 程序中使用 C、C++ 等编写的动态链接库(DLL)中的函数。这些内置特性为我们的开发工作提供了极大的便利,让我们能够更加高效地实现各种功能。
三、数据校验的常规武器:System.ComponentModel.DataAnnotations
(一)常用校验特性介绍
在 C# 的世界里,System.ComponentModel.DataAnnotations命名空间为我们提供了一系列强大的校验特性,它们就像是一群训练有素的 “数据卫士”,时刻守护着数据的准确性和完整性。接下来,让我们逐一认识这些 “卫士”。
- **[Required]**特性:这个特性就像是一位严厉的教官,它要求被标记的属性值必须存在,绝不允许为空。在用户注册场景中,用户名和密码是必填项,我们可以这样使用[Required]特性:
public class UserRegistrationModel
{[Required(ErrorMessage = "用户名不能为空")]public string Username { get; set; }[Required(ErrorMessage = "密码不能为空")]public string Password { get; set; }
}
当用户提交注册信息时,如果用户名或密码为空,系统会立即捕获这个错误,并显示相应的错误提示信息,有效避免了因空值导致的后续问题。
- **[StringLength]**特性:它如同一位严格的尺寸管理员,主要用于限制字符串类型属性的长度。假设我们在设计一个商品名称字段,要求名称长度不能超过 50 个字符,就可以使用[StringLength]特性:
public class Product
{[StringLength(50, ErrorMessage = "商品名称长度不能超过50个字符")]public string ProductName { get; set; }
}
这样一来,当用户输入的商品名称超过 50 个字符时,系统会进行拦截并提示错误,确保了数据的规范性。
- **[EmailAddress]**特性:它是专门用于验证电子邮件地址格式的 “邮件专家”。在处理用户的邮箱信息时,我们可以借助它来确保用户输入的邮箱格式正确无误:
public class ContactInfo
{[EmailAddress(ErrorMessage = "请输入有效的电子邮件地址")]public string Email { get; set; }
}
如果用户输入的邮箱格式不符合标准,如 “abc.com”,系统会及时给出错误提示,避免因邮箱格式错误导致的邮件发送失败等问题。
- **[Range]**特性:这是一个负责数值范围管理的 “范围卫士”,它可以限制数值类型属性的取值范围。在一个年龄字段中,我们通常希望用户输入的年龄在合理范围内,比如 18 到 120 岁之间,这时就可以使用[Range]特性:
public class UserProfile
{[Range(18, 120, ErrorMessage = "年龄需在18到120之间")]public int Age { get; set; }
}
通过这种方式,有效防止了用户输入不合理的年龄值,保证了数据的真实性和有效性。
(二)在实际项目中的应用场景
这些校验特性在实际项目中有着广泛的应用场景,它们就像坚固的防线,为项目的稳定运行提供了有力保障。
- 表单验证:在 Web 应用程序中,用户注册、登录、提交订单等表单操作是非常常见的。我们可以在表单对应的模型类中使用上述校验特性,实现对用户输入数据的实时验证。在ASP.NET Core MVC 项目中,我们创建一个用户注册表单的模型类:
public class RegisterViewModel
{[Required(ErrorMessage = "用户名不能为空")]public string Username { get; set; }[Required(ErrorMessage = "密码不能为空")][StringLength(100, ErrorMessage = "密码长度至少为6位", MinimumLength = 6)]public string Password { get; set; }[Required(ErrorMessage = "确认密码不能为空")][Compare("Password", ErrorMessage = "两次输入的密码不一致")]public string ConfirmPassword { get; set; }[Required(ErrorMessage = "邮箱不能为空")][EmailAddress(ErrorMessage = "请输入有效的邮箱地址")]public string Email { get; set; }
}
然后在控制器中,当用户提交注册表单时,框架会自动根据这些特性对用户输入的数据进行验证。如果数据不符合要求,会返回相应的错误信息给用户,提示用户修改,大大提高了用户体验和数据的准确性。
- 数据模型验证:在企业级应用开发中,数据模型是整个系统的核心。确保数据模型中的数据质量至关重要。在一个基于 Entity Framework Core 的数据访问层项目中,我们定义一个用户数据模型类:
public class User
{public int Id { get; set; }[Required(ErrorMessage = "用户名不能为空")]public string Username { get; set; }[Required(ErrorMessage = "邮箱不能为空")][EmailAddress(ErrorMessage = "请输入有效的邮箱地址")]public string Email { get; set; }[Range(0, 10000, ErrorMessage = "积分范围在0到10000之间")]public int Points { get; set; }
}
当我们从数据库中读取数据或向数据库中插入、更新数据时,这些校验特性可以帮助我们在数据进入数据库之前进行严格的验证,防止错误数据进入数据库,保证了数据库中数据的一致性和可靠性。
- API 输入验证:随着微服务架构的普及,API 的重要性日益凸显。为了确保 API 接收到的数据符合要求,我们可以在 API 的参数模型中使用校验特性。在一个基于ASP.NET Core Web API 的项目中,定义一个接收订单信息的 API 参数模型:
public class OrderRequest
{[Required(ErrorMessage = "订单编号不能为空")]public string OrderId { get; set; }[Required(ErrorMessage = "商品数量不能为空")][Range(1, 100, ErrorMessage = "商品数量需在1到100之间")]public int Quantity { get; set; }[Required(ErrorMessage = "商品价格不能为空")][Range(0.01, 100000.00, ErrorMessage = "商品价格需在0.01到100000.00之间")]public decimal Price { get; set; }
}
当客户端调用这个 API 并传递参数时,API 框架会自动根据这些特性对参数进行验证。如果参数不符合要求,API 会返回错误响应给客户端,避免了因错误参数导致的业务逻辑错误和系统异常,提高了 API 的稳定性和安全性。
综上所述,System.ComponentModel.DataAnnotations命名空间中的校验特性在实际项目中的应用场景非常广泛,它们能够帮助我们在不同的层面有效地验证数据,提高项目的质量和可靠性。
四、进阶玩法:自定义特性
(一)为什么需要自定义特性
尽管System.ComponentModel.DataAnnotations命名空间提供的内置校验特性已经非常强大且实用,但在实际的项目开发中,我们常常会遇到一些特殊的校验需求,这些需求是内置特性无法直接满足的。这就好比我们拥有一套功能齐全的通用工具,但在面对一些特殊的工作任务时,还是需要定制专门的工具来高效地完成工作。
例如,在一个电商系统中,我们可能需要对商品的 SKU(库存保有单位)进行特殊的校验。SKU 不仅仅是一个简单的字符串或数字,它可能有特定的格式要求,如必须以特定的字母开头,后面跟随一定规则的数字和字母组合,并且长度也有严格的限制。这种复杂的校验规则,[Required]、[StringLength]等内置特性显然无法直接实现。
再比如,在一个金融系统中,对于用户输入的银行卡号,除了基本的非空和格式校验外,可能还需要根据银行的特定规则进行校验,如校验银行卡号的校验位是否正确,不同银行的卡号长度和规则也有所不同。这种与业务紧密相关的特殊校验逻辑,内置特性往往难以胜任。
此外,在一些企业级应用中,可能会有独特的业务规则和数据标准。在一个医疗信息管理系统中,对于患者的病历编号,可能需要满足医院内部的编码规则,这个规则可能涉及到科室编号、年份、流水号等多个部分的组合,并且不同科室的病历编号规则也可能不同。对于这样复杂的业务规则,内置校验特性就显得力不从心了。
因此,为了满足这些特殊的校验需求,我们需要创建自定义特性,它就像是为我们量身定制的工具,能够根据具体的业务逻辑进行灵活的校验,确保系统的数据质量和业务规则的正确执行。
(二)如何创建和使用自定义特性
接下来,我们将以CustomValidationAttribute为例,详细展示如何创建和使用自定义特性。创建自定义特性主要包含以下几个关键步骤:
- 继承ValidationAttribute类:自定义特性类需要继承自System.ComponentModel.DataAnnotations.ValidationAttribute类,这是创建自定义校验特性的基础。通过继承这个类,我们可以获得校验特性所需的基本功能和行为。
using System.ComponentModel.DataAnnotations;[AttributeUsage(AttributeTargets.Property)]
public class CustomValidationAttribute : ValidationAttribute
{// 后续步骤中的代码将在此类中逐步添加
}
在这段代码中,我们定义了一个名为CustomValidationAttribute的自定义特性类,并使用AttributeUsage特性来指定它可以应用于属性上。AttributeUsage特性就像是一个使用说明,它告诉编译器这个自定义特性可以被放置在哪些程序元素上。在这里,我们将其限制在属性上,以确保它的正确使用范围。
- 重写IsValid方法:IsValid方法是自定义特性的核心部分,我们需要在这个方法中实现具体的校验逻辑。在这个方法中,我们可以根据业务需求对属性值进行各种检查和验证。
using System.ComponentModel.DataAnnotations;[AttributeUsage(AttributeTargets.Property)]
public class CustomValidationAttribute : ValidationAttribute
{private readonly string _validationMessage;public CustomValidationAttribute(string validationMessage){_validationMessage = validationMessage;}protected override ValidationResult IsValid(object value, ValidationContext validationContext){if (value is string str && str.StartsWith("Z")){return new ValidationResult(_validationMessage);}return ValidationResult.Success;}
}
在这个例子中,我们在CustomValidationAttribute类中添加了一个构造函数,用于接收一个错误提示信息_validationMessage。然后,重写了IsValid方法。在IsValid方法中,首先判断属性值是否为字符串类型,并且是否以字母 “Z” 开头。如果满足这个条件,说明校验失败,返回一个包含错误提示信息的ValidationResult对象;如果不满足条件,说明校验成功,返回ValidationResult.Success。
- 在模型类中应用自定义特性:创建好自定义特性后,就可以在模型类的属性上应用它了,就像使用内置校验特性一样简单。
public class CustomUser
{[CustomValidationAttribute("用户名必须以Z开头")]public string Username { get; set; }
}
在CustomUser类中,我们在Username属性上应用了CustomValidationAttribute自定义特性,并传入了错误提示信息 “用户名必须以 Z 开头”。这样,当对CustomUser类的实例进行数据校验时,就会自动触发CustomValidationAttribute的校验逻辑。
通过以上步骤,我们就完成了自定义特性的创建和使用。这种自定义特性为我们提供了极大的灵活性,能够满足各种复杂的业务校验需求,使我们在数据校验方面拥有更强的掌控力。
五、实战演练:验证数据
(一)利用 Validator 类进行数据验证
在 C# 中,System.ComponentModel.DataAnnotations命名空间不仅为我们提供了丰富的校验特性,还贴心地配备了Validator类,它就像是一位智能的 “数据审查官”,能够帮助我们在任意时刻对对象的属性进行高效验证。接下来,我们通过一个具体的代码示例,来深入了解Validator类的强大功能和使用方法。
假设我们已经定义了一个User类,其中包含了Username、Email和Age等属性,并使用了System.ComponentModel.DataAnnotations命名空间中的校验特性对这些属性进行了约束,如下所示:
using System.ComponentModel.DataAnnotations;public class User
{[Required(ErrorMessage = "用户名不能为空")][StringLength(50, ErrorMessage = "用户名长度需在0到50之间")]public string Username { get; set; }[EmailAddress(ErrorMessage = "请输入有效的电子邮件地址")]public string Email { get; set; }[Range(18, 120, ErrorMessage = "年龄需在18到120之间")]public int Age { get; set; }
}
现在,我们需要创建一个User类的实例,并使用Validator类对其属性进行验证。示例代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;class Program
{static void Main(){// 创建一个User类的实例,并设置一些不符合校验规则的值var user = new User{Username = "",Email = "notAnEmail",Age = 17};// 创建一个用于存储验证结果的列表var results = new List<ValidationResult>();// 使用Validator类的TryValidateObject方法尝试验证User实例// 第一个参数是要验证的对象// 第二个参数是验证上下文,用于提供验证所需的上下文信息// 第三个参数是用于存储验证结果的列表// 第四个参数表示是否验证所有属性,这里设置为truevar isValid = Validator.TryValidateObject(user, new ValidationContext(user), results, true);// 判断验证是否成功if (!isValid){// 如果验证失败,遍历验证结果列表,并打印每个验证失败的错误信息foreach (var validationResult in results){Console.WriteLine(validationResult.ErrorMessage);}}else{Console.WriteLine("数据验证成功!");}}
}
在上述代码中,我们首先创建了一个User类的实例user,并故意设置了一些不符合校验规则的值。然后,我们创建了一个List类型的results列表,用于存储验证结果。接着,使用Validator.TryValidateObject方法对user实例进行验证。该方法会根据User类中定义的校验特性,对user的属性进行逐一检查,并将验证结果存储在results列表中。如果验证失败,isValid变量将为false,我们通过遍历results列表,打印出每个验证失败的错误信息,这些错误信息正是我们在定义校验特性时设置的,能够清晰地提示用户哪些数据不符合要求。如果验证成功,isValid变量将为true,并打印出 “数据验证成功!” 的提示信息。
通过这个示例,我们可以看到Validator类的使用非常简单直观,它能够帮助我们快速准确地验证对象的属性,确保数据的质量和合法性,为我们的程序提供了可靠的数据保障。
(二)实际项目中的完整验证流程
在实际项目中,数据验证是一个贯穿始终的重要环节,它涉及到从接收数据到验证数据,再到处理验证结果的一系列复杂流程。接下来,我们将以一个基于ASP.NET Core 的 Web 应用程序为例,深入探讨在实际项目中数据验证的完整流程以及其在框架中的应用。
- 接收数据:在ASP.NET Core 应用程序中,通常通过控制器来接收客户端发送的数据。这些数据可能来自用户在前端页面填写的表单,也可能是通过 API 调用传递过来的参数。在一个用户注册的场景中,前端页面会将用户输入的用户名、密码、邮箱等信息封装成一个 HTTP 请求发送到服务器。在ASP.NET Core 中,我们可以创建一个AccountController来处理这个请求,示例代码如下:
using Microsoft.AspNetCore.Mvc;[ApiController]
[Route("[controller]")]
public class AccountController : ControllerBase
{[HttpPost("register")]public IActionResult Register([FromBody] UserRegisterModel model){// 这里接收到了客户端发送的UserRegisterModel模型数据// 后续将对该模型数据进行验证和处理}
}
在上述代码中,[HttpPost(“register”)]表示该方法处理 HTTP POST 请求,路径为 “/Account/register”。[FromBody]特性表示从请求体中获取数据,并将其绑定到UserRegisterModel模型上。此时,model变量中就包含了客户端发送的用户注册信息。
- 验证数据:一旦接收到数据,接下来的关键步骤就是对数据进行验证。在ASP.NET Core 中,我们可以充分利用System.ComponentModel.DataAnnotations命名空间中的校验特性来实现这一目的。首先,定义UserRegisterModel模型类,并使用校验特性对其属性进行约束,示例代码如下:
using System.ComponentModel.DataAnnotations;public class UserRegisterModel
{[Required(ErrorMessage = "用户名不能为空")]public string Username { get; set; }[Required(ErrorMessage = "密码不能为空")][StringLength(100, ErrorMessage = "密码长度至少为6位", MinimumLength = 6)]public string Password { get; set; }[Required(ErrorMessage = "确认密码不能为空")][Compare("Password", ErrorMessage = "两次输入的密码不一致")]public string ConfirmPassword { get; set; }[Required(ErrorMessage = "邮箱不能为空")][EmailAddress(ErrorMessage = "请输入有效的邮箱地址")]public string Email { get; set; }
}
在这个模型类中,我们使用了[Required]、[StringLength]、[Compare]和[EmailAddress]等校验特性,分别对用户名、密码、确认密码和邮箱进行了严格的校验。然后,在控制器的Register方法中,ASP.NET Core 框架会自动根据这些校验特性对接收到的UserRegisterModel模型数据进行验证。如果数据不符合校验规则,框架会将验证失败的信息存储在ModelState中。
- 处理验证结果:验证数据之后,我们需要根据验证结果进行相应的处理。如果验证成功,说明数据符合要求,可以继续进行后续的业务逻辑处理,如将用户信息保存到数据库中。如果验证失败,我们需要返回错误信息给客户端,提示用户修改数据。在ASP.NET Core 中,我们可以通过检查ModelState.IsValid属性来判断验证是否成功,示例代码如下:
using Microsoft.AspNetCore.Mvc;[ApiController]
[Route("[controller]")]
public class AccountController : ControllerBase
{[HttpPost("register")]public IActionResult Register([FromBody] UserRegisterModel model){if (!ModelState.IsValid){// 验证失败,返回包含错误信息的BadRequest响应return BadRequest(ModelState);}// 验证成功,继续进行后续业务逻辑处理// 例如,将用户信息保存到数据库//...return Ok("注册成功");}
}
在上述代码中,如果ModelState.IsValid为false,表示验证失败,我们使用BadRequest方法返回一个 HTTP 400 Bad Request 响应,并将ModelState中的错误信息传递给客户端。客户端接收到这个响应后,可以根据错误信息提示用户修改相应的数据。如果ModelState.IsValid为true,表示验证成功,我们可以继续进行后续的业务逻辑处理,如将用户信息保存到数据库中,并返回一个成功的响应给客户端。
通过以上步骤,我们展示了在实际项目中基于ASP.NET Core 框架的数据验证的完整流程。从接收数据到验证数据,再到处理验证结果,每个环节都紧密相连,共同确保了数据的质量和业务逻辑的正确执行。在实际开发中,我们还可以根据项目的具体需求,对数据验证流程进行进一步的优化和扩展,如添加自定义的验证逻辑、统一的错误处理机制等,以提高项目的健壮性和可维护性。
六、总结与展望:数据校验的未来发展
在 C# 开发的广阔天地中,数据校验无疑是一项至关重要的技术。它不仅是保障数据准确性和完整性的坚固防线,更是提升系统稳定性和可靠性的关键因素。通过本文的深入探讨,我们全面认识了 C# 中数据校验的多种实现方式,从基础的System.ComponentModel.DataAnnotations命名空间中的常用校验特性,到能够满足复杂业务需求的自定义特性,再到利用Validator类进行数据验证的实战应用,每一种方式都为我们在不同场景下实现数据校验提供了有力的支持。
在实际项目中,我们将这些数据校验技术广泛应用于表单验证、数据模型验证以及 API 输入验证等多个环节,有效避免了错误数据的流入,确保了业务逻辑的正确执行。这些技术的运用,不仅提高了系统的质量和性能,还为用户提供了更加稳定和可靠的服务体验。
展望未来,随着技术的不断进步和业务需求的日益复杂,数据校验技术也将迎来新的发展机遇和挑战。一方面,人工智能和机器学习技术的快速发展,将为数据校验带来更加智能化的解决方案。通过训练模型,能够自动识别和校验各种复杂的数据模式,大大提高校验的准确性和效率。在电商领域中,利用机器学习算法可以对海量的商品数据进行实时校验,快速发现异常数据和潜在的风险。
另一方面,随着分布式系统和微服务架构的普及,数据校验也将面临新的挑战。如何在分布式环境下实现高效、一致的数据校验,确保各个服务之间的数据交互准确无误,将是未来研究的重点方向之一。区块链技术的兴起,为数据校验提供了新的思路。其去中心化和不可篡改的特性,能够确保数据在传输和存储过程中的安全性和完整性,为数据校验带来了更加可靠的保障。
此外,实时校验技术也将得到进一步发展。在大数据时代,数据的产生和传输速度极快,传统的事后校验方式已经无法满足需求。实时校验技术能够在数据产生的瞬间进行验证,及时发现和纠正错误,为数据的实时处理和分析提供了有力支持。
作为开发者,我们应当紧跟技术发展的步伐,不断学习和探索新的数据校验技术和方法。通过持续的实践和创新,将这些先进的技术应用到实际项目中,为打造更加健壮、可靠的软件系统贡献自己的力量。让我们携手共进,在数据校验的艺术之路上不断前行,创造更加美好的技术未来!
相关文章:
解锁C#数据校验:从基础到实战的进阶之路
一、引言:数据校验为何如此重要? 在软件开发的广袤领域中,数据校验宛如一座坚固的堡垒,守护着系统的稳定与安全。它是确保数据质量的关键防线,能有效避免错误数据的流入,进而提升系统的整体性能和可靠性。…...

Redis的通用命令
⭐️前言⭐️ 本文主要介绍Redis的通用命令 🍉欢迎点赞 👍 收藏 ⭐留言评论 🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言 🍉博客中涉及源码及博主日常练习代码均已上传GitHub 📍内容导…...
设计模式六大原则和单例模式
设计模式 目的 实现可重用解决方案,构筑易维护、可扩展的软件系统。 六大原则 单一职责: 类的职责单一,一个方法做一件事。 开闭原则: 拓展开放,修改关闭。 里氏替换: 父类能出现的地方,子…...
Redis性能优化
1.是否使用复杂度过高的命令 首先,第一步,你需要去查看一下 Redis 的慢日志(slowlog)。 Redis 提供了慢日志命令的统计功能,它记录了有哪些命令在执行时耗时比较久。 查看 Redis 慢日志之前,你需要设置慢…...

SAM 大模型杂谈
目录 1. 前言 2. 发展历程 3. SAM 大模型的技术架构 3.1 模型结构 3.2 训练方法 3.3 数据处理 4. SAM 大模型的应用领域 4.1 自然语言处理 4.2 计算机视觉 4.3 多模态学习 4.4 其他领域 5. SAM 大模型的优势与挑战 5.1 优势 5.2 挑战 6. SAM 大模型的未来发展方…...

openGauss 3.0 数据库在线实训课程2:学习客户端工具gsql的使用
openGauss数据库状态查看 前提 我正在参加21天养成好习惯| 第二届openGauss每日一练活动 课程详见:openGauss 3.0.0数据库在线实训课程 学习目标 学习openGauss数据库客户端工具gsql的使用。 课程作业 gsql是openGauss提供在命令行下运行的数据库连接工具&am…...

B站自研的第二代视频连麦系统(上)
导读 本系列文章将从客户端、服务器以及音视频编码优化三个层面,介绍如何基于WebRTC构建视频连麦系统。希望通过这一系列的讲解,帮助开发者更全面地了解 WebRTC 的核心技术与实践应用。 背景 在文章《B站在实时音视频技术领域的探索与实践》中ÿ…...

【远程控制】安装虚拟显示器
todesk远程发现没显示器的机器有问题 电脑如果不外接一个显示器那么会默认为1024 768 分辨率需要安装虚拟显示器参考 竟然是一个隐私屏幕的解决方案。 虚拟显示器 Parsec-vdd 项目地址 Parsec-vdd 最大的优点是:支持 4K 高刷、可添加多个虚拟屏、 H-Cursor&#…...

基于HAI部署DeepSeekR1的招标文书智能辅助生产开发与应用
一、前言 1.1行业背景 在日常商业活动中,招投标流程往往是企业竞标和项目落地的关键一环。其中,招标文书的编写工作对于投标企业极具挑战:既要保证逻辑清晰、条理分明,又必须遵循招标机构的各类格式规范,甚至还有特定…...

解决whisper 本地运行时GPU 利用率不高的问题
我在windows 环境下本地运行whisper 模型,使用的是nivdia RTX4070 显卡,结果发现GPU 的利用率只有2% 。使用 import torch print(torch.cuda.is_available()) 返回TRUE。表示我的cuda 是可用的。 最后在github 的下列网页上找到了问题 极低的 GPU 利…...
模拟实战-用CompletableFuture优化远程RPC调用
实战场景 这是广州某500-900人互联网厂的面试原题 手写并发优化解决思路 我们要调用对方的RPC接口,我们的RPC接口每调用一次对方都会阻塞50ms 但是我们的业务要批量调用RPC,例如我们要批量调用1k次,我们不可能在for循环里面写1k次远程调用…...
深入解析:Jsoup 库的多功能应用场景
Jsoup 是一个强大的 Java 库,主要用于解析和操作 HTML 文档。它不仅广泛应用于网络爬虫和数据抓取,还在网页内容分析、数据清洗与处理、自动化测试等多个领域有着广泛的应用。本文将详细介绍 Jsoup 库的多种用途,并提供具体的代码示例。 一、…...

Polardb三节点集群部署安装--附虚拟机
1. 架构 PolarDB-X 采用 Shared-nothing 与存储计算分离架构进行设计,系统由4个核心组件组成。 计算节点(CN, Compute Node) 计算节点是系统的入口,采用无状态设计,包括 SQL 解析器、优化器、执行器等模块。负责数据…...

Redis - 全局ID生成器 RedisIdWorker
文章目录 Redis - 全局ID生成器 RedisIdWorker一、引言二、实现原理三、代码实现代码说明 四、使用示例示例说明 五、总结 Redis - 全局ID生成器 RedisIdWorker 一、引言 在分布式系统中,生成全局唯一ID是一个常见的需求。传统的自增ID生成方式在分布式环境下容易出…...
【Vitest】单元测试
文章目录 测试:Vitest一、安装二、断言三、回调测试四、对象方法五、模拟第三库 测试:Vitest 一、安装 npm install vitest创建文件:example.test.ts 运行测试: npx vitest example二、断言 import { expect, test } from vi…...

达梦数据库从单主模式转换为主备模式
目录标题 达梦数据库单主转主备配置笔记前期准备服务器环境数据库安装磁盘空间 流程流程图说明基于脱机备份方式的单实例转主备流程图详细步骤说明 详细步骤1. 检查主库归档模式2. 配置主库配置文件dm.ini 文件dmmal.ini 文件dmarch.ini 文件 3. 备份主库数据库4. 备库配置新建…...

【Elasticsearch】nested聚合
在 Elasticsearch 中,嵌套聚合(nestedaggregation)的语法形式用于对嵌套字段(nestedfields)进行聚合操作。嵌套字段是 Elasticsearch 中的一种特殊字段类型,用于存储数组中的对象,这些对象需要独…...

虹科波形小课堂 | 三分钟掌握车辆相对压缩测试!不拆发动机、不测缸压就能判断故障缸!
不拆发动机、不测缸压,只测个电流也能知道哪个缸压缩有问题?没错!做个相对压缩测试,测下起动电流就行,简单又实用!今天,从原理到方法,几分钟教会你! 我们都知道…...

【玩转全栈】--创建一个自己的vue项目
目录 vue介绍 创建vue项目 vue页面介绍 element-plus组件库 启动项目 vue介绍 Vue.js 是一款轻量级、易于上手的前端 JavaScript 框架,旨在简化用户界面的开发。它采用了响应式数据绑定和组件化的设计理念,使得开发者可以通过声明式的方式轻松管理数据和…...

基于 Spring Cloud + Spring AI + VUE 的知识助理平台介绍以及问题
前言(一些废话) 在看这篇文章的各位大佬,感谢你们留出几分钟时间,来看这个产品介绍,其实重点说实话,不是这个产品怎么样。而是在最后有一个郁结在心里的几个问题,希望大佬们能给出一些建议。万…...

【LLM大模型技术专题】「入门到精通系列教程」LangChain4j与Spring Boot集成开发实战指南
LangChain4j和SpringBoot入门指南 LangChain4jLangchain4j API语言模型消息类型内存对象ChatMemory接口的主要实现设置 API 密钥SpringBoot Configuration配置ChatLanguageModelStreamingChatLanguageModel初始化ChatModel对象模型配置分析介绍说明通过JavaConfig创建ChatModel…...

Go语言学习-->项目中引用第三方库方式
Go语言学习–>项目中引用第三方库方式 1 执行 go mod tidy 分析引入的依赖有没有正常放在go.mod里面 找到依赖的包会自动下载到本地 并添加在go.mod里面 执行结果: 2 执行go get XXXX(库的名字)...
SQL 基础入门
SQL 基础入门 SQL(全称 Structured Query Language,结构化查询语言)是用于操作关系型数据库的标准语言,主要用于数据的查询、新增、修改和删除。本文面向初学者,介绍 SQL 的基础概念和核心操作。 1. 常见的 SQL 数据…...

国标GB28181设备管理软件EasyGBS远程视频监控方案助力高效安全运营
一、方案背景 在商业快速扩张的背景下,连锁店门店数量激增,分布范围广。但传统人工巡检、电话汇报等管理方式效率低下,存在信息滞后、管理盲区,难以掌握店铺运营情况,影响企业效率与安全。网络远程视频监控系统可有…...
二、【ESP32开发全栈指南:ESP32 GPIO深度使用】
GPIO(通用输入输出) 是ESP32最基础却最核心的功能。本文将带你深入ESP32的GPIO操作,通过按键读取和LED控制实现物理按键→ESP32→LED的完整信号链路。 一、ESP32 GPIO核心特性速览 34个可编程GPIO(部分引脚受限)输入模…...

OpenCV 图像色彩空间转换与抠图
一、知识点: 1、色彩空间转换函数 (1)、void cvtColor( InputArray src, OutputArray dst, int code, int dstCn 0, AlgorithmHint hint cv::ALGO_HINT_DEFAULT ); (2)、将图像从一种颜色空间转换为另一种。 (3)、参数说明: src: 输入图像,即要进行颜…...
八股学习-JS的闭包
一.闭包的定义 闭包是指函数和其周围的词法环境的引用的组合。 简单来说,就是函数可以记住并访问其在定义时的作用域内的变量,即使该函数在其它作用域调用。 也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。 function …...
使用 C/C++ 和 OpenCV 实现滑动条控制图像旋转
使用 C 和 OpenCV 实现滑动条控制图像旋转 本文将介绍如何使用 C 和 OpenCV 库创建一个简单的应用程序,该程序可以显示一张图片,并允许用户通过一个滑动条(Trackbar)来实时控制图片的旋转角度。这是一个非常实用的交互式功能&…...

AIGC赋能前端开发
一、引言:AIGC对前端开发的影响 1. AIGC与前端开发的关系 从“写代码”到“生成代码”传统开发痛点:重复性编码工作、UI 设计稿还原、问题定位与调试...核心场景的AI化:需求转代码(P2C)、设计稿转代码(D2…...
SON.stringify()和JSON.parse()之间的转换
1.JSON.stringify() 作用:将对象、数组转换成字符串 const obj {code: "500",message: "出错了", }; const jsonString JSON.stringify(obj); console.log(jsonString);//"{"code":"Mark Lee","message"…...