当前位置: 首页 > news >正文

.net 软件开发模式——三层架构

三层架构是一种常用的软件开发架构模式,它将应用程序分为三个层次:表示层、业务逻辑层和数据访问层。每一层都有明确的职责和功能,分别负责用户交互、业务处理和数据存储等任务。这种架构模式的优点包括易于维护和扩展、更好的组织结构和代码重用性、更高的安全性等方面。在具体实现中,需要根据不同的应用程序需求和技术平台选择适当的工具和框架,以达到最佳的开发效果和应用程序质量。

 

在 .NET 中,我们同样可以使用三层架构来构建我们的应用程序,实现表示层、业务逻辑层和数据访问层的分离。下面分别介绍在 .NET 中如何实现这三层架构。

        1.表示层

在 .NET 中,我们可以使用 WinForms、WPF、ASP.NET 等技术来实现表示层的功能。在 WinForms 和 WPF 中,我们可以使用各种控件来构建用户界面,以显示和收集数据。在 ASP.NET 中,我们可以使用 ASP.NET Web 窗体、MVC、Web API 等技术来生成和管理 Web 页面。

在所有情况下,表示层的主要职责是接收用户输入和显示数据。例如,在 WinForms 中,我们可以使用窗体和控件来表示 UI,并通过事件处理程序和数据绑定来响应用户输入和显示数据。在 ASP.NET 中,我们可以使用代码片段来生成 HTML、CSS 和 JavaScript,并使用服务器端脚本和控件来处理事件和数据绑定。

        2.业务逻辑层

在 .NET 中,我们可以使用类和接口来实现业务逻辑层。这些类和接口通常包括与应用程序相关的业务逻辑和规则,例如验证、授权、计算和处理数据。

业务逻辑层通常向表示层公开 API,以便 UI 可以与业务逻辑进行交互。例如,在 ASP.NET MVC 中,我们可以使用控制器和模型来处理请求,并使用视图来处理 UI。在 WinForms 中,我们通常将业务逻辑封装在一个专用的类或类库中,并使用事件处理程序和数据绑定来处理 UI。

        3.数据访问层

在 .NET 中,我们可以使用 ADO.NET 和 Entity Framework 来访问数据。ADO.NET 提供了一组用于连接到和操作关系型数据库的类和接口,而 Entity Framework 则提供了一种对象关系映射(ORM)框架,使我们可以将对象与数据库记录进行映射和交互。

数据访问层通常会使用一些技术和工具来管理和维护数据,例如 SQL Server Management Studio 或 LINQ。我们可以使用 ADO.NET 和 Entity Framework 来执行数据库操作,并使用仓储模式或 DAL 等设计模式来创建底层数据库连接和访问代码。

 下面通过一个简易的例题来演示三层架构的简易模式:

  1. 首先建立一个数据库(EmployeeSystem)
  2. 内部包含两个表(AdminInfo),(EmployeeInfo)
  3. AdminInfo表(登录验证表)包含两字段:主键:Account(varchar)用户名,Pwd(varchar) 密码  用于登录验证
  4. EmployeeInfo表(学生信息表)包含六个字段 :主键自增列:Id(int)编号,EmployeeName (varchar)  姓名,EmployeeNo(varchar)学号,EmployeeAge(int )年龄,EmployeeSalary(int)就业工资,EmployeeJob(varchar)职业名称

  以上完成了示例数据库的搭建 

接下来打开Microsoft Visual Studio2022,开始新建项目

 

  1.  在解决方案里创建一个Windows窗体应用程序取名UI作为我们这个项目的表示层
  2. 在解决方案里添加三个类库
  3. Model 模型层主要包含一些数据库中表对应的实体类,作为数据传递的载体
  4. DAL  数据访问层 :与数据库进行交互 执行增删改查的操作
  5. BLL 业务逻辑层:对业务逻辑进行处理 ,比如进行判断(必要的非空判断,添加前是否已经存在同样的数据)

 

        6.打开UI找到引用:

 第2步:定义连接字符串

        name 属性是用于标识连接字符串的名称的字符串。

        connectionString 是数据库连接时用到的字符串。

         providerName 属性是用于指定数据提供程序的名称字符串。它通常与 connectionString 属性一起使用,来告诉应用程序要使用哪个特定的 ADO.NET 数据提供程序来访问数据库。

最后再到UI层

 

 到这里了接下来进入Model层

 我们首先从模型层开始写:

这里类里添加了两个类分别对应数据库里的两张表以及各字段 

到这个模型层算搭建完(记得把修饰符改成公有的)

 下一步给各层设置相互之间的引用

  1.  UI表示层需要引用BLL业务逻辑层和Model模型层
  2. DAL数据访问层需要引入Model模型层
  3. BLL业务逻辑层需要引入DAL数据访问层和Model模型层

 到这个项目的引用关系也就完事了

接下来就可以开始着手DAL数据访问层的内容了

DAL 层中的 SqlHelper 方法通常被称为数据访问助手方法(Data Access Helper Method),它们主要用于将应用程序的业务逻辑和底层数据访问逻辑分离开来。

通常情况下,SqlHelper 方法都包装了底层 ADO.NET API,以提供更简单、更易用的 API 接口,从而帮助开发人员更轻松地访问数据库。这些方法通常包括执行 SQL 语句、存储过程的方法,还有获取数据表、数据集等返回值的方法。

SqlHelper 方法可以接受连接字符串、SQL 语句、存储过程名称以及参数等信息作为参数,并使用它们来构建和执行数据库操作。通过将这些详细信息隐藏在方法内部,SqlHelper 方法帮助程序员简化了代码逻辑,提高了代码结构的清晰度和可读性。同时,SqlHelper 方法还可以处理数据库连接、异常处理等底层逻辑,从而提高了数据访问代码的可靠性和稳定性。

需要注意的是,不同的数据访问技术和开发框架通常有不同的 SqlHelper 实现方式,例如在 ASP.NET 中,我们通常使用 SqlHelper 类来访问 SQL Server 数据库,而在 Entity Framework 中,我们可以使用 DbContext 来管理数据访问逻辑,或者使用 LINQ 表达式来查询数据。

  1.  建立一个公有,静态类SqlHelper (内部方法也均为公有静态方法)
static readonly string ido= ConfigurationManager.ConnectionStrings["配置文件内add里的name名"].ToString();
//这段代码的作用是从应用程序配置文件 (App.config) 中获取名为 “配置文件内add里的name名” 的连接字符串,并将其存储在一个名为 “ido” 的静态只读字符串常量 ido 中。

     2.接下来写下两个方法

        思路:根据执行数据库增删改查操作的返回值来分类方法

                        1.查询操作返回的是DataTable 是一个 C# 中的数据表格类,它代表了一个内存中的数据表格,提供了一种方便的方法来存储和操作数据。

                        2.增删改操作的不同点只是sql语句有差异,他们共同点的返回类型都是受影响的行数。

                        3.由此存在了两种返回类型的值,可以在拟定两个返回值类型的方法分别为int和DataTable

   3.查询表值的方法返回DAtaTable

public static DataTable selectall(string sql){//建立数据库连接 App.config里准备的数据库连接语句在这个时候可以体现用处了SqlConnection conn = new SqlConnection(ido);//打开数据库连接conn.Open();// 创建数据适配器对象SqlDataAdapter ter = new SqlDataAdapter(sql, conn);//实例化DataTableDataTable dt = new DataTable();// 使用数据适配器填充数据集ter.Fill(dt);//关闭数据库连接conn.Close();//返回值return dt;}

   4.增删改的方法返回受影响行数

public static int CUD(string sql){SqlConnection conn = new SqlConnection(ido);conn.Open();//创建sql命令对象SqlCommand com= new SqlCommand(sql,conn);//用一个int 变量来接收受影响的返回行数int r=com.ExecuteNonQuery();//返回r的值return r;}

   5.参数化命令的增删改方法

public static bool selectal(string sql,List<SqlParameter> list){SqlConnection conn = new SqlConnection(ido);conn.Open();SqlCommand com = new SqlCommand(sql, conn);//使用 AddRange 方法一次性添加多个 SqlParameter 对象,list需要转换成数组添加com.Parameters.AddRange(list.ToArray());//接收执行查询时返回的结果集中第一行第一列的值如果有数据就会大于0int r = Convert.ToInt32(com.ExecuteScalar());//判断r的值来决定返回的boolif(r >0) { return true; } else { return false; }}

到这一步数据访问助手的类已经完成了

DAL 数据访问层再为每张表定义一个类调用数据访问助手(在这里可以写入你需要执行的sql语句操作)

首先我们来做最简单的AdminInfo表(登录验证表)做执行一个登录的查询操作

        这里需要主要预防sql注入攻击,所以要采用参数化命令的方法

 在DAL层创建一个AdmDAL类调用SqlHelper类的方法

//参数为AdminInfo类public bool admopen(AdminInfo info){//sql语句string sql = "select count(*) from AdminInfo where Account=@Account and Pwd=@Pwd";//创建了一个 List<SqlParameter> 实例,用于存储多个 SqlParameter 对象。然后通过调用 List<T> 对象的 Add 方法向集合添加一个参数,或使用 AddRange 方法一次添加多个参数List<SqlParameter> list= new List<SqlParameter>();list.Add(new SqlParameter("@Account", info.Account));list.Add(new SqlParameter("@Pwd", info.Pwd));//返回值调用SqlHelper的方法(传入sql语句和参数化命令对象的值)最终返回一个bool类型的值return SqlHelper.selectal(sql, list);}

DAL层最后一个类EmpADL类 EmployeeInfo表(学生信息表)的各项操作

全部采取的sqlHelper的方法

简易的只需要写一条sql语句再返回调用方法(传入string sql语句参数)

有参数化命令的方法就根据sql语句创建一个list集合来存储方法类的值再返回参数化命令方法(sql语句,list集合)

 //添加学生的方法public int EmpInsert(EmployeeInfo info){string sql = "insert into EmployeeInfo values(@EmployeeName,@EmployeeNo,@EmployeeAge,@EmployeeSalary,@EmployeeJob)";List<SqlParameter> list = new List<SqlParameter>();list.Add(new SqlParameter("@EmployeeName", info.EmployeeName));list.Add(new SqlParameter("@EmployeeNo", info.EmployeeNo));list.Add(new SqlParameter("@EmployeeAge", info.EmployeeAge));list.Add(new SqlParameter("@EmployeeSalary", info.EmployeeSalary));list.Add(new SqlParameter("@EmployeeJob", info.EmployeeJob));return SqlHelper.CUD(sql, list);}//修改方法public int EmpUpdate(EmployeeInfo info){string sql = "update EmployeeInfo set EmployeeName=@EmployeeName,EmployeeNo=@EmployeeNo,EmployeeAge=@EmployeeAge,EmployeeSalary=@EmployeeSalary,EmployeeJob=@EmployeeJob where Id=@Id";List<SqlParameter> list = new List<SqlParameter>();list.Add(new SqlParameter("@EmployeeName", info.EmployeeName));list.Add(new SqlParameter("@EmployeeNo", info.EmployeeNo));list.Add(new SqlParameter("@EmployeeAge", info.EmployeeAge));list.Add(new SqlParameter("@EmployeeSalary", info.EmployeeSalary));list.Add(new SqlParameter("@EmployeeJob", info.EmployeeJob));list.Add(new SqlParameter("@Id", info.Id));return SqlHelper.CUD(sql, list);}//删除方法public int EmpDelete(int id){string sql = $"delete from EmployeeInfo where Id={id}";return SqlHelper.CUD(sql);}//查询整表的方法public DataTable select(){string sql = "select * from EmployeeInfo";return SqlHelper.selectall(sql);}//根据编号查询的方法public DataTable selectID(int id) {string sql = $"select * from EmployeeInfo where Id={id}";return SqlHelper.selectall(sql);}//根据姓名模糊查询的方法public DataTable SelectName(string name) {string sql = $"select * from EmployeeInfo where EmployeeName like '%{name}%'";return SqlHelper.selectall(sql);}

以上这些就是DAL 数据访问层的基本方法 如果有额外的需求的话可以根据个人的要求结合所学的知识再去新建方法体

下面我们再来到BLL业务逻辑层

业务逻辑层需要做什么呢?

简单的来讲就是连接UI表示层和DAL数据访问层的桥梁,在这里会对数据进行一些加工例如判断数据是否为空等等,该怎么做需要屏幕前的你来发挥了

下面来看示例

 public class EmpBLL{//实例化DAL数据访问层的EmpDAL类 并用方法调用EMpDAL类的方法private EmpDAL EmpDAL = new EmpDAL();//添加的方法public int EmpInsert(EmployeeInfo info){return EmpDAL.EmpInsert(info);}//修改的方法public int EmpUpdate(EmployeeInfo info){return EmpDAL.EmpUpdate(info);}//删除的方法public int EmpDelete(int id){return EmpDAL.EmpDelete(id);}//查询整表的方法public DataTable select(){return EmpDAL.select();}//根据姓名模糊查询的方法public DataTable SelectName(string name){return EmpDAL.SelectName(name);}//根据编号查询的方法public DataTable SelectID(int id){return EmpDAL.selectID(id);}

以上是EmployeeInfo学生信息表需要在表示层使用的方法

接下来是AdminInfo登录信息表需要的业务逻辑层方法

 public class AdmBLL{//实例化数据访问层的AdmDAL类 并调用方法private AdmDAL AdmDAL=new AdmDAL();//登录方法public bool admopen(AdminInfo info){return AdmDAL.admopen(info);}}

到这里业务逻辑层也就完工了

最后一个UI 表示层 使用WinForms窗体应用程序搭建

首先完成一个简易的登录操作

在UI层建立一个窗体form1 

使用控件 label* 2 ,textbox*2 button*1

 给窗体登录按钮 双击添加点击事件

private void button1_Click(object sender, EventArgs e){//实例化模型层Model 的AdminInfo类 并把文本框的值赋给里面的字段AdminInfo info= new AdminInfo();info.Account = textBox1.Text;info.Pwd= textBox2.Text;//实例化BLL 业务逻辑层调用相对应的方法AdmBLL adm= new AdmBLL();//定义一个bool值的变量来接收返回值bool f= adm.admopen(info);//通过判断f的值来选择执行的操作,为true则弹窗登录成功并打开后续的窗体if (f==true){MessageBox.Show("登录成功");Form2 form2 = new Form2();form2.Show();}else { MessageBox.Show("登录失败"); }}

最后再给UI表示层添加一个form2窗体用于示例DAL和BLL的方法

为了简易采用dategridview

 上面的窗体我们添加了多个按钮

先从窗体的加载事件开始,首先在窗体内部添加一个公有的BLL业务逻辑层的实例对象,便于调用其方法。

 public EmpBLL empBLL = new EmpBLL();//实例化业务逻辑层
//初始化dategridview的表值
//将方法放入form2_load窗体加载事件中即可初始化值
public void select(){dataGridView1.DataSource = empBLL.select();//调用业务逻辑层查询整表的方法加载到datagridview控件中dataGridView1.ClearSelection();//取消默认选中状态}

删除按钮:button2

//删除按钮点击事件 
private void button2_Click(object sender, EventArgs e){//对datagridview的选中项进行判断,未选中行时弹窗提示if (dataGridView1.SelectedRows.Count<=0){MessageBox.Show("请选中你需要删除的一行!");}else if (dataGridView1.SelectedRows.Count > 0){//获取选中行的第一行第一列的值用 一个int的变量来接收方便调用后续的业务逻辑层删除的方法int id = Convert.ToInt32(this.dataGridView1.SelectedRows[0].Cells[0].Value);//接收删除方法的返回值进行受影响的行判断int i = empBLL.EmpDelete(id);if (i > 0){//删除成功时弹窗提示并调用给datagridview赋值的方法(select())MessageBox.Show("删除成功");select();}else { MessageBox.Show("删除失败"); }}}

添加的按钮:button1

private void button1_Click(object sender, EventArgs e){//设置跳转到目标窗体并设置父子级Form3 form3 = new Form3();form3.Owner= this;form3.Show();}

form3窗体如下:

注:编号Id为自增列,所有只有五个字段

 这里只需要为添加按钮添加点击事件:

//添加按钮点击事件 
private void button1_Click(object sender, EventArgs e){//实例化EmployeeInfo类EmployeeInfo info = new EmployeeInfo();info.EmployeeName=textBox1.Text;info.EmployeeNo=textBox2.Text;info.EmployeeAge=int.Parse(textBox3.Text);info.EmployeeSalary=int.Parse(textBox4.Text);info.EmployeeJob=textBox5.Text;//给类中的每个字段赋值EmpBLL empBLL = new EmpBLL();//实例化BLL业务逻辑层的EmpBLL方法类,调用其中的添加方法把info作为参数传入int r= empBLL.EmpInsert(info);//用变量接收返回值来判断受影响行数if (r > 0) { MessageBox.Show("添加成功"); Form2 form=this.Owner as Form2;form.select();this.Close();} else { MessageBox.Show("添加失败"); }}

Form2 form=this.Owner as Form2:

这段的理解是:将当前窗体的拥有者窗体转换为 Form2 类型,并将转换后的实例赋值给了 form 变量。这样,我们就可以直接访问该窗体对象的属性和方法,例如 form 属性或者 Show 方法等。需要注意的是,如果 this.Owner 不是 Form2 类型的对象,则 form 变量将为 null。

之后再调用form2窗体的select()方法实现添加成功之后刷新form2的datagridview的集合

剩余的几个按钮就不一一进行讲解了,原理同上,有时间可以自己多练习熟能生巧,该文章只供参考用于理解软件开发模式的三层架构,相信认真看了的小伙伴能够看出对于传统的一个控件一个控件来完善的方式节省的代码量是非常可观的。

最后文章到这里就结束了,如果感觉对你有帮助的话可以点赞或收藏来加深理解。

再感谢认真看完文章的人对我的认可,本人会持续更新更多对粉丝有用的文章喜欢的可以关注支持哦

相关文章:

.net 软件开发模式——三层架构

三层架构是一种常用的软件开发架构模式&#xff0c;它将应用程序分为三个层次&#xff1a;表示层、业务逻辑层和数据访问层。每一层都有明确的职责和功能&#xff0c;分别负责用户交互、业务处理和数据存储等任务。这种架构模式的优点包括易于维护和扩展、更好的组织结构和代码…...

SpringBoot如何优雅的实现重试功能

文章目录 使用背景spring-retry介绍快速使用加入依赖开启Retry使用参数 使用背景 在有些特定场景&#xff0c;如和第三方对接。 我们调用接口时需要支持重试功能&#xff0c;第一次调用没成功&#xff0c;我们需要等待x秒后再次调用。 通常会设置重试次数&#xff0c;避免业务…...

【CEEMDAN-VMD-GRU】完备集合经验模态分解-变分模态分解-门控循环单元预测研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

OpenText Exceed TurboX(ETX)—— 适用于 UNIX、Linux 和 Windows 的远程桌面解决方案

由于新技术的采用&#xff0c;以及商业全球化和全球协作的现实&#xff0c;几乎所有企业&#xff08;无论其规模和所处行业&#xff09;的员工的工作方式、时间和地点都发生了重大变化。业务领导者正在推动其 IT 部门提出解决方案&#xff0c;以帮助其远程员工提高工作效率&…...

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降 逻辑回归分类Logistic Regression ClassificationLogistic Regression: Log OddsLogistic Regression: Decision BoundaryLikelihood under the Logistic ModelTraining the Logistic ModelGradient Desc…...

k8s pod “cpu和内存“ 资源限制

转载用于收藏学习&#xff1a;原文 文章目录 Pod资源限制requests&#xff1a;limits&#xff1a;docker run命令和 CPU 限制相关的所有选项如下&#xff1a; Pod资源限制 为了保证充分利用集群资源&#xff0c;且确保重要容器在运行周期内能够分配到足够的资源稳定运行&#x…...

datagrip 连接 phoenix

jar替换完后尽量重启datagrip. 然后重新连接即可. 不重启貌似报错... 效果:...

黑客入侵的常法

1.无论什么站&#xff0c;无论什么语言&#xff0c;我要渗透&#xff0c;第一件事就是扫目录&#xff0c;最好一下扫出个上传点&#xff0c;直接上传 shell &#xff0c;诸位不要笑&#xff0c;有时候你花很久搞一个站&#xff0c;最后发现有个现成的上传点&#xff0c;而且很容…...

VB报警管理系统设计(源代码+系统)

可定时显示报警系统是一个能够定时并及时报警,提醒人们安全有效地按计划完成任务的系统。本论文从软件工程的角度,对可定时显示报警系统做了全面的需求分析,简要说明了该系统的构思、特点及开发环境;阐述了系统的主要功能,论述了它的设计与实现,并且叙述了系统的测试与评…...

Redis入门 - Redis Stream

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - Redis Stream | CoderMast编程桅杆Redis入门 - Redis Stream Redis Stream 是 Redis 5.0 版本新增加的数据结构。 Redis Stream 主要用于消息队列&#xff08;MQ&#xff0c;Message Queue&#xff09;&#xf…...

微服务中常见问题

Spring Cloud 组件 Spring Cloud五大组件有哪些&#xff1f; Eureka&#xff1a;注册中心 Ribbon&#xff1a;负载均衡 Feign&#xff1a;远程调用 Hystrix&#xff1a;服务熔断 Zuul/Gateway&#xff1a;服务网关 随着SpringCloud Alibaba在国内兴起&#xff0c;我们项目中…...

更新删除清理购物车

目录 1 更新购物车 2 取会员门店购物车项 3 取会员门店购物车项(无缓存) 4 删除门店购物车某项 5 删除门店购物车多项 6 清理门店购物车 7 清理门店购物车 8 添加商品至购物车 9 添加商品至购物车...

基于Intel NUC平台的字符设备陀螺仪GX5-25驱动程序

陀螺仪GX5-25连接到Intel NUC上可能需要进行一些设备树的修改和编写驱动程序的工作。这是因为陀螺仪GX5-25可能需要特定的设备树配置和驱动程序来与Intel NUC的硬件和操作系统进行通信。 如果陀螺仪GX5-25没有官方的Linux驱动程序或文档&#xff0c;您可能需要自己编写驱动程序…...

建立小型医学数据库(总结)

建立小型医学数据库 小型医学数据库可以用于存储和管理医学数据&#xff0c;如患者病历、药品信息、试验结果等。这对于医疗机构和科研机构来说非常必要&#xff0c;可以提高数据管理和共享的效率&#xff0c;进而促进医学研究和诊疗水平的提升。 建立小型医学数据库有以下基本…...

Git学习笔记

文章目录 一. 引入1. SCM软件2. 概念 二. GitHubDesktop三. Git1. 版本号 (底层原理)1.1 视频笔记1.2 实操记录 2. Git命令2.0 汇总2.1 仓库操作2.2 文件操作2.3 分支操作2.4 标签操作2.5 远程仓库 四. idea操作 一. 引入 1. SCM软件 2. 概念 集中式版本控制 文件冲突 可以上…...

vue面试题1. 请说下封装 vue 组件的过程?2. Vue组件如何进行传值的?3. Vue 组件 data 为什么必须是函数?4. 讲一下组件的命名规范

1. 请说下封装 vue 组件的过程&#xff1f; 首先&#xff0c;组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块&#xff0c;解决了我们传统项目开发&#xff1a;效率低、难维护、复用性等问题。 分析需求&#xff1a;确定业务需求&#xff0c;把页面中可以…...

Docker使用记录

文章目录 Docker基本使用Docker配置查看状态卸载安装使用 apt 存储库安装在 Ubuntu 上安装 Docker 桌面(非必要) Docker实例使用现有的镜像查找镜像拖取镜像列出镜像列表更新镜像导出镜像删除镜像导入镜像清理镜像查看容器导出容器导入容器-以镜像的方式创建容器重启容器进入容…...

OpenCV(图像处理)-基于Python-形态学处理-开运算、闭运算、顶帽、黑帽运算

1. 形态学2. 常用接口2.1 cvtColor()2.2 图像二值化threshod()自适应阈值二值化adaptiveThreshod() 2.3 腐蚀与膨胀erode()getStructuringElement()dilate() 2.4开、闭、梯度、顶帽、黑帽运算morphologyEx() 1. 形态学 OpenCV形态学是一种基于OpenCV库的数字图像处理技术&…...

chatgpt赋能python:Python支持跨平台软件开发

Python支持跨平台软件开发 作为一种高级编程语言&#xff0c;Python 以其丰富的库和跨平台支持而备受开发人员欢迎。Python 通过将应用程序的可移植性最大化&#xff0c;使得开发人员可以轻松地在不同的操作系统平台上构建和部署软件。 跨平台支持 Python 支持各种不同的操作…...

哈工大计算机网络课程网络层协议详解之:CIDR与路由聚集

哈工大计算机网络课程网络层协议详解之&#xff1a;CIDR与路由聚集 文章目录 哈工大计算机网络课程网络层协议详解之&#xff1a;CIDR与路由聚集CIDR与路由聚集CIDR路由聚集 CIDR与路由聚集 CIDR CIDR&#xff1a;无类域间路由&#xff08;CIDR&#xff1a;Classless InterDo…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...