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

news2024/9/24 5:25:30

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

 

在 .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);
            //实例化DataTable
            DataTable 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());
            //接收执行查询时返回的结果集中第一行第一列的值如果有数据就会大于0
            int r = Convert.ToInt32(com.ExecuteScalar());
            //判断r的值来决定返回的bool
            if(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的集合

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

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

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

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

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

相关文章

Vue的详细安装教程,使用NVM安装是我所推荐的方式

第一步&#xff1a;卸载之前安装的node&#xff0c;安装NVM 进入网站&#xff1a;Releases coreybutler/nvm-windows GitHub 选择一个版本进行安装即可 安装的路径我就不用多说了&#xff0c;全英文路径&#xff0c;尽量不要安装在c盘上&#xff0c;计算机人都懂为什么&…

vmware17+ubuntu18.04通过qemu8.0.2启动arm64虚拟机-测试vsock

文章目录 一、环境搭建1.qemu-8.0.22.buildroot配置 3.编译工具链gcc-linaro-7.2.1下载交叉编译工具链 4.linux kernel 5.16config_kernel.sh配置内核build_kernel.sh 5.启动虚拟机&#xff08;1&#xff09;创建磁盘镜像文件&#xff08;2&#xff09;拷贝内核镜像和根文件系统…

ESP32(MicroPython)端午节项目

本程序致敬了屏幕驱动例程&#xff0c;依次以4种字体显示Happy Dragon Boat Festival!&#xff0c;并重复一次。 代码如下 from ili934xnew import ILI9341, color565 from machine import Pin, SPI import m5stack import tt14 import glcdfont import tt14 import tt24 imp…

JDK自带的构建线程池的方式之newWorkStealingPool

newWorkStealingPool和之前的几种线程池的创建方式有很大的不同&#xff0c;之前定长、单例、缓存、定时任务的四大线程池都是基于ThreadPoolExecutor去实现的。newWorkStealingPool则是基于ForkJoinPool的方式构建出来的。 ThreadPoolExecutor的核心特点 只有一个阻塞队列Dela…

深度学习(24)——YOLO系列(3)

深度学习&#xff08;24&#xff09;——YOLO系列&#xff08;3&#xff09; 文章目录 深度学习&#xff08;24&#xff09;——YOLO系列&#xff08;3&#xff09;1. BOF(bag of freebies)2. Mosaic data augmentation3. 数据增强4. self-adversarial-training&#xff08;SAT…

深入浅出MySQL索引

索引 索引在MySQL中是举足轻重的。在添加索引后&#xff0c;我们在MySQL的查询上会极大的提高我们的查询效率&#xff0c;这也是慢查询解决办法之一。 数据结构 最初的时候MySQL中是采用二叉树进行插入数据的&#xff0c;这样的缺点很明显&#xff0c;就是树太高了&#xff…

C++QT入门

CQT 文章目录 CQT1. QT概述1.1 什么是QT1.2 QT的发展史1.3 支持的平台1.4 QT版本1.5 Qt 的下载与安装1.6 QT的优点1.7 成功案例 2. 创建QT项目2.1 使用向导创建2.2 手动创建2.3 .pro 文件2.4 设置父对象2.5 按钮设置属性2.5.1 按钮设置文本2.5.2 设置移动2.5.3 设置固定大小 2.…

[进阶]网络通信:UDP通信,一发一收、多发多收

UDP通信 特点&#xff1a;无连接、不可靠通信。不事先建立连接&#xff1b;发送端每次把要发送的数据&#xff08;限制在64KB内&#xff09;、接收端1P、等信息封装成一个数据包&#xff0c;发出去就不管了。Java提供了一个java.net.Datagramsocket类来实现UDP通信。 Datagram…

Qt/C++使用QUiLoader动态加载ui资源文件

目录 动态对话框使用场景注意事项动态对话框加载获取动态对话框的控件对象与动态对话框建立关联动态修改ui资源文件效果测试 动态对话框 动态对话框(dynamic dialog)就是在程序运行时使用的从Qt设计师的.ui文件创建而来的那些对话框。动态对话框不需要通过uic把 .ui文件转换成…

【ARM裸机编程 | 海思SS528】- 操作 GPIO 寄存器输出低电平点亮 LED 灯

目录 一、概述二、看原理图&#xff0c;找LED灯的GPIO管脚三、使能 GPIO 管脚功能四、配置 GPIO 管脚为输出五、设置 GPIO 管脚输出高、低电平 一、概述 这篇文章主要介绍在 海思SS528 开发板&#xff0c;去操作某个 GPIO 寄存器输出高、低电平&#xff0c;来熄灭或点亮 LED 灯…

Spring框架中,什么是控制反转?什么是依赖注入?使用控制反转与依赖注入有什么优点

目录 一、Spring 二、控制反转 三、依赖注入 四、控制反转与依赖注入有什么优点 一、Spring Spring框架是一款开源的Java应用程序框架&#xff0c;它为企业级Java应用提供了全面的基础设施支持和编程模型。通过Spring框架&#xff0c;开发人员可以快速地搭建出高效、可维护…

C++【红黑树】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 &#x1f307;前言&#x1f3d9;️正文1、认识红黑树1.1、红黑树的定义1.2、红黑树的性质1.3、红黑树的特点 2、红黑…

chatgpt赋能python:Python中是否有局部变量?-完全解析

Python 中是否有局部变量&#xff1f;- 完全解析 Python 是一种高级编程语言&#xff0c;它因其易学、可读性强、开发速度快、功能丰富、能够快速交互、具有跨平台特性等方面而备受欢迎。其中一块关键功能是变量&#xff0c;变量可以存储值&#xff0c;以供稍后使用&#xff0…

[保姆级啰嗦教程] Tesseract OCR 5在Windows 10下编译安装及测试 (亲测成功)

作为一个优秀的文字识别&#xff08;OCR&#xff09;库&#xff0c;Tesseract最早并非开源软件&#xff0c;它是HP实验室在1985-1994年开发的专属软件&#xff0c;直到2005年&#xff0c;HP及内华达大学拉斯维加斯分校以开源的形式发布&#xff0c;然后由Google从2006年开始赞助…

[SpringBoot 分布式调度elasticjob 整合 ]

目录 &#x1f96b;前言: &#x1f96b;配置作业 &#x1f96b;实现任务处理类 &#x1f96b;启动SpringBoot应用程序 &#x1f96c;下面是代码是我另一个文章看见 记录的笔记, 我前面也使用了elastic-job做重试机制,有兴趣可以看一下 &#x1f96c;依赖: &#x1f96c;…

基于MATLAB的CFAR检测仿真程序分享

基于MATLAB的CFAR检测仿真&#xff0c;得到平均CFAR检测。 完整程序&#xff1a; clc; clear; close all; warning off; addpath(genpath(pwd)); cfar phased.CFARDetector(NumTrainingCells,200,NumGuardCells,50,Method,CA); % Expected probability of False Alarm (no u…

【瑞萨RA_FSP】CTSU——电容按键检测

文章目录 一、1. 电容按键介绍二、电容按键原理三、瑞萨QE在电容按键上面的运用四、电容按键实验1. 硬件设计2. FSP配置3.复制文件4.主函数 一、1. 电容按键介绍 电容式感应触摸按键可以穿透绝缘材料外壳 8mm &#xff08;玻璃、塑料等等&#xff09;以上&#xff0c;准确无误…

OpenStack(2)--项目(租户)、用户、角色

一、项目&#xff08;租户&#xff09;、用户、角色的关系 重点理解项目&#xff08;project/租户&#xff09;、用户&#xff08;user&#xff09;、角色&#xff08;role&#xff09;三者之间的关系&#xff0c;首先这三者都可以单独新建&#xff0c;但是绑定关系是通过open…

10 分钟玩转Elastcisearch——数据可视化分析

在当今这个快速发展的科技时代&#xff0c;Elasticsearch 已经成为企业和开发者的重要技术工具。随着数据的爆发式增长&#xff0c;Elasticsearch 可以帮助个人和企业更好的理解数据、发现数据中的规律趋势和模式、并从海量数据中洞察业务价值。 为了帮助开发者能够快速上手&am…

基于SpringBoot的电子文档管理系统(源码、文档、数据库)

网上文件管理系统所用的资料库是由 SpringBoot架构所建立的 Mysql资料库。在进行设计的时候&#xff0c;要充分地保证了系统代码拥有良好的可读性、实用性、易扩展性、通用性、便于后期维护、操作容易、页面简洁等优势。 一、开发工具及技术介绍 &#xff08;1&#xff09;.J…