Linux:开发工具(2)

一、Linux编译器-gcc/g++使用

1.1 为什么我们可以用C/C++做开发呢?

       无论是在windows、还是Linux中,C++的开发环境不仅仅指的是vs、gcc、g++,更重要的是语言本身的头文件(函数的声明)和库文件(函数的实现)。所以我们在安装这些软件的时候,同时也选择了相关的开发包,会同步下载对应的头文件和库文件。

     所以任何一款编译型语言的使用,都必要需要安装相应的开发包(头文件和库文件)

查看头文件:ls /usr/include/

1.2 预处理(进行宏替换)

预处理阶段会涉及到很多操作

a、去注释

    注释我们一般用于对我们的代码进行解释说明,但并不参与编译,所以是可以直接去掉的,节省文件的大小。

b、头文件展开

     头文件里面包含了我们需要的一些函数的声明,由于在链接之前各个文件都是独立进行编译和转汇编的,所以头文件将函数声明展示出来其实就是为了在编译过程的时候告诉编译器,这个函数是存在的,一定要放行,而最后的函数定义一般得等到链接的时候才能找到

c、条件编译

     条件编译其实就是有选择的编译,比较常见的一种情况比如说我们要通过打印来观察代码的运行情况(调试),但是仅仅只是为了起到一个调试的作用,所以我们调试后还要删掉其实有点可惜,所以我们可以通过条件编译来对他进行保留,在必要的时候启动这段代码或者是去掉这段代码。

还有一种技巧就是 -D(宏)           直接在外面定义宏 

一种使用条件编译的场景举例——vs的社区版(免费)和专业版(付费)

      一般在下载VS的时候可能会存在这两种版本,而一般我们购买那一种是根据我们的需求,而专业版是付费的所以必然功能是更加健全的,但从开发人员的角度,社区版和专业版难道需要维护两份代码么??其实他们是一份代码,只不过对于社区版,他们通过条件编译去掉了一些功能!!

命令:gcc -E test.c -o test.i 

告诉gcc,从现在开始进行程序编译,从预处理工作就停下来,不要往前走了 

1.3 编译(生成汇编) 

       在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等(有错误会直接崩掉),以确定代码的实际要做的工作,在检查 无误后,gcc 把代码翻译成汇编语言。其实头文件里包含的函数声明,其实就是告诉编译器,这个函数是存在的,你要放行!

命令:gcc -S test.i -o test.s

告诉gcc,从现在开始进行程序编译,将编译过程做完就停下来 

1.4 汇编(生成机器可识别代码) 

汇编阶段是把编译阶段生成的“.s”文件转成目标文件(可重定位目标二进制文件)

命令:gcc -c test.i -o test.o

告诉gcc,从现在开始进行程序编译,汇编结束就停下来

注意:有执行权限和具有可执行能力是两回事,就好比一个富二代,他有继承家产的权利,但是他未必就有管理家业的能力——>所以.o文件是无法运行的!!需要经过链接才行!! 

1.5 链接(生成可执行文件或库文件)

 将目标文件和库进行链接,就得到了可执行程序

命令:gcc test.o -o test 

明明已经生成了机器可以读懂的文件,为什么还需要链接才能运行呢???

     原因就在于我们当前的文件并只有函数调用、函数声明,缺没有函数方法,所以必须要和库(C语言标准库,本质上就是一个文件)链接,函数的方法就存在于库中(其实就是把源文件.c经过一定的编译,然后打包,最后只给你提供一个文件)这样做有两个好处:

1、方便源文件的隐藏(未来我们想把程序给别人用,但不希望他看到源码,也可以这样)

2、不让我们做重复工作(帮我们造好了轮子),站在巨人的肩膀上 。

所以软件=头文件的方法+库文件提供的方法实现+你的代码

      个人觉得在日常的学习中,我们要尽可能地去尝试自己造轮子,研究底层,扎实内功,这样才可能应对未来的一些更复杂的情况,而在以后工作的时候,尽可能用一些已经写好的高效的代码,避免重复工作。而如果需要自己造轮子,早期的学习就会给你提供很大的帮助。

1.6 .o和库是如何链接的(静态链接和动态链接)

1.6.1 动态库文件和静态库文件

在Linux中: .so(动态库)  .a(静态库)

命名规则:libname.so.XXX

在windows中:.dll(动态库)  .lib(静态库)

在Linux中,通过ls /usr/lib64/libc.so*  可以看到我们的动态库文件

通过指令ldd 可以查看该可执行程序所依赖的动态库

 还有之前我们知道其实指令的本质就是可执行程序,所以我们也可以去查看指令所依赖的动态库,我们会发现大部分都是用C的库

静态库的文件默认是没有安装的,需要通过以下指令去手动安装

C静态库:sudo yum install -y glibc-static

C++静态库:sudo yum install -y libstdc++-static

 1.6.2 动态库和静态库理解

1、假设我们考上了一所高中,这里不让上网,但是你是一个喜欢打游戏的人,你通常会将打游戏这件事列入到自己每天的计划表中,而你的学校附近恰好有一个网吧,你在将计划进行到规定时间的时候就会翻墙出去上网,然后再回来。

自己的计划表——可执行程序

学校——编译器

网吧——动态库

网吧里的电脑——库文件

      也就是说当程序执行到某个地方时,他会跳出到动态库继续执行,然后再回来,这个过程就是动态链接。  

2、假设有一天网吧老板突然被举报,并且没有营业执照而被迫查封,这个时候我的计划就无法如期进行了,并且影响的不只是你,还有学校其他喜欢打游戏的人!

     所以动态库不能缺失!!一旦缺失影响的不仅仅是一个程序,而是多个程序都会崩溃!

3、突然有一天学校允许学生上网了,这个时候网吧老板捕捉到了商机,把网吧的电脑搬出来开了一家二手电脑专卖店,然后喜欢打游戏的同学都过来购买了电脑了!!

二手电脑专卖店——静态库

二手电脑——库文件

     也就是说,静态库进行静态链接的时候,会将自己的方法拷贝到目标程序中,该程序以后不用再依赖静态库!

4、有一天那个老板又被举报查封了,但是这个时候学校里的学校却没有人知道这件事,因为大家都有自己的电脑了,店查不查封对他们没什么影响。

    所以静态链接的程序并不依赖库文件,即使静态库丢失了程序也可以正常运行!

1.6.3 控制链接方式的选择

当我们不做限制时,会默认使用动态链接。如果我们想要静态链接 就需要加 -static选项

1、如果没有-static,默认编译可能会出现三种情况:动态链接->静态链接->报错。而有了static,就会去掉第一种情况,即静态链接->报错

2、不一定是纯的动态链接或者静态链接,也可以是混合的

1.6.4 动态链接和静态链接的优缺点

动态库:

优点:动态库是共享库,可以有效节省资源(磁盘空间、内存空间、网络空间)

缺点:动态库一旦缺失,所有的程序将无法运行

静态库:

优点:不依赖库,程序可以独立运行

缺点:体积大,消耗资源

       一般来说,我们在实际应用中更倾向于使用动态链接,因为体积大所带来的影响是很大的,比方说你下个游戏要1G,但是用静态链接可能就需要上百G,所以无论是我们还是Linux默认,都是会尽量选择动态链接。

1.6.5 debug&&release 

       debug可以被追踪调试,是因为在形成可执行程序的时候被添加了debug信息,所以占用的空间会更大一点。而release一般作为发行版,重在用户体验,所以体积会较小一点,我们Linux下编译默认是release版本,-g选项可以帮助我们改成debug版本。

扩展:可执行程序形成的时候,不是无序的二进制构成,而是有自己的格式的——>可执行程序有自己的二进制格式!(ELF格式)

 readelf -S可以查看可执行程序的二进制构成

二、Linux项目自动化构建工具-make/Makefile

为什么我们会需要自动化构建工具????

        一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

     所以,makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率

说明:

1、make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命 令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。

2、make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2.1 依赖关系和依赖方法

       举个例子,到月底的时候,你会给你爸打电话要下个月的生活费,这是因为你们两个之间存在依赖关系,而讨要生活费就是你们之间的依赖方法,现实中人与人之间能建立联系其实就是因为有依赖关系和依赖方法。 

      而我们使用makefile文件也同样需要依赖关系和依赖方法

我们会发现这个过程其实有点像是函数调用,特别像递归,形成了makefile的自动推导

所以其实我们乱序也可以,因为他会自己去找,如果找不到就会报错。

 2.2 make clean

还是上面这个情景,我们一make就生成了很多文件

但是我们如果想要清理的话,就需要用clean(不需要依赖关系)

 

 

为什么make执行前面的,而make clean执行后面的呢???

         原因就是因为,如果make没有指定的话,默认就是从第一行开始扫描到第一个make就执行,所以建议将编译的工作放到最前面,然后把清理的工作写到后面!!

 2.3 为什么不会允许多次make呢??(重点)

我们会发现我们make一次之后,就不然我们继续make了。这是为啥呢?

 1、为了提高编译效率!如果我们的文件相较于之前没有发生过任何的变化,那么就不能进行make(因为系统觉得没必要,纯属浪费时间),如果相较于之前的内容有更新过,那么就会重新形成一次新的可执行程序覆盖掉

 2、那么我们的系统究竟是如何做到判断这个文件是否被更新过呢??难道是将文件扫描一遍??显然不现实。其原理如下:

     首先,可执行程序一定是由源文件形成的,所以源文件的最近修改时间一定比可执行程序的最近时间要老——>推到得出,如果我们的源文件的最近修改文件比可执行程序时间新,那么就说明这个文件被修改过!!!

总结:只需要比较可执行程序的时间和源文件的最近修改时间即可!

.exe比.c老,说明被修改过,需要重新编译

.exe比.c新,说明没有被修改过,就不需要重新编译(提高了编译效率!)

 2.4 stat指令

stat指令是查看文件或者文件系统的详细信息

 Access表示访问时间,任何增删查改都算访问操作

Modify表示修改文件内容的时间

Change表示修改文件属性的时间

1/  按道理来说,Access的修改频率应该是最高的,但有些时候是无意义的,并且由于磁盘是属于外部设备,如果频繁访问的话,效率是极低的,所以在设计的时候,Access的时间其实是取决于另外两个时间的!

(1)当仅读取或者访问文件文件时,只有Access会改变

(2)当修改文件内容时,Modify(文件内容)和Change(文件大小)都会改变,Access不一定改变

(3)当修改文件权限属性时, 只有Change会改变

2/ .PHONY:

    所以make会根据源文件和目标文件的新旧,判定是否需要重新执行依赖关系进行编译,那么如果我们希望依赖关系总是被执行,就需要.PHONY:(伪目标)

     .PHONY:其实就是告诉make,这个目标是我的朋友,只要他想编你就让他编,不要阻拦,所以这个关键词常用在clean的身上。

3、 在一个文件不存在的时候,touch的作用是将该文件新建出来,但是如果这个文件存在的话,touch就可以将三个时间都修改成当前的时候,或者是用-a -m -c 选项来强制修改其中一个。

2.5 特殊符号 

1、$@和$^  分别指代依赖关系的前一个和后一个

2、依赖方法最前面+@ ——>对应的依赖方法在make后不会回显到屏幕上

三、Linux小程序-进度条

3.1 回车换行

其实回车和换行是两个概念,换行仅仅表示从当前位置跳到下一行,而回车则是回到该行的起点

其实\n 默认是换行+回车  而\r才是回车(键盘上的enter图标)

       以前的老式打印机,通过打字他会自动从左往右写,而当我们写到最右边的时候,先往下跳(换行),再把他拉到最左边接着写(回车)

3.2 缓冲区 

 首先认识一下sleep函数 参数表示休息多少秒 头文件是<unistd.h> 方便我们观察

 他会输出在输出hello Linux的时候,然后休眠2秒。 

 

如果我们去掉换行,则hello Linux会在两秒后才出现

思考:去掉了\n,为什么会是先休眠再输出呢??

        首先我们要肯定的是,代码运行的顺序必然是从前往后的,所以sleep一定是在printf之后执行的,这说明在休眠的时候,hello Linux必然被保存在某个地方,其实就是缓冲区!!缓冲区是由C语言维护的一段内存,他默认是按行刷新回显到显示器上!!所以如果我们想要提前刷新的话,就需要用fflush

参数可以是:标准输出(stdin)、标准输入(stdout)、标准错误(stderr) 

 这样就可以将缓冲区的内容刷新出来了!!!

3.3 简单倒计时的设置

首先我们需要processbar.c  processbar.h  main.c 三个文件

接下里先实现一个简单倒计时

我们要考虑两个问题:

(1) 倒计时要覆盖之前的位置,所以需要回车/r

(2)缓冲区是按行刷新的,所以必须要提前刷新

 但是我们一旦将cnt变成10以上,就会出现这样的情况

 

      这是因为我们的显示器是字符显示设备,所以他都是一个字符一个字符去打印的,你以为10是一个整体,其实对于他来说,是字符1和字符0  所以为了解决这个问题,我们需要去设置格式。比如说%-2d表示两个字符,格式左对齐

3.4 进度条基础版本

 改进的地方:

(1)需要一个[ ]括起来 

(2)需要一个数字来展示进度

(3)最后希望能有一个类似转圈的东西

 #include"processBar.h"                                          2 #define NUM 102                                            3 const char* lable="|/-\\";//\\转义为1个                        4 void processbar()                                             5 {                                                              6   char bar[NUM];                                               7   memset(bar,'\0',sizeof(bar));                                                                                 8   int len=strlen(lable);                                       9   int cnt=0;                                                   10   while(cnt<=100)                                              11   {                                                            12     printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);  13     fflush(stdout); //需要刷新出来                             14     bar[cnt++]=STYLE;                                          15     usleep(100000);                                            16   }                                                           17   printf("\n");                                              18 }    

3.5 进度条外部调用版本

        以上进度条是我们去设置进度的,但是实际我们的这个进度条应该由外部去调用,根据软件的具体情况去调用进度条,而具体的进度应该是由外部软件决定的。

 #pragma once                            |  1 #include"processBar.h"                     1 #include"processBar.h"2 #include<stdio.h>                       |  2                                          |  2 #define NUM 1023 #include<unistd.h>                      |  3 int main()                               |  3 const char* lable="|/-\\";//\\转义为1个4 #include<string.h>                      |  4 {                                        |  4 char bar[NUM];5 void processbar(int rate);              |  5   //模拟当前正在下载一款软件             |  5 void processbar(int rate)6 #define STYLE '#'//风格                 |  6   int total=1000;                        |  6 {7                                         |  7   int cur=0;                             |  7   if(rate<0||rate>100) return;//防止你非8                                         |  8   while(cur<=total)                      |    法
~                                           |  9   {                                      |  8   int len=strlen(lable);             
~                                           | 10     processbar(cur*100/total);           |  9     printf("[%-100s][%d%%][%c]\r",bar,ra
~                                           | 11     cur+=10;                             |    te,lable[rate%len]);
~                                           | 12     usleep(50000);                       | 10     fflush(stdout); //需要刷新出来
~                                           | 13   }                                      | 11     bar[rate++]=STYLE;              
~                                           | 14   printf("\n");                          | 12 }                                       
~                                           | 15   return 0;                              | 13                                   
~                                           | 16 }                               

3.6 进度条回调版本

       有些时候我们希望能进行多任务下载,因此可以将该进度条设置成回调函数,这样不同的软件就可以传对应不同的进度条。

 #pragma once                                 1 #include"processBar.h"                 |  1 #include"processBar.h"2 #include<stdio.h>                       |    2                                        |  2 #define NUM 1023 #include<unistd.h>                      |    3 int main()                             |  3 const char* lable="|/-\\";//\\转义为1个4 #include<string.h>                      |    4 {                                      |  4 char bar[NUM];5 void processbar(int rate);              |E>  5   download(processbar);                |  5 void processbar(int rate)6 #define STYLE '#'//风格                 |    6   return 0;                            |  6 {7 typedef void(*callback_t)(int);//回调函>|    7 }                                      |  7   if(rate<0||rate>100) return;//防止你非数                                      |    8                                        |    法8 void downLoad(callback_t cb);           |  ~                                          |  8   int len=strlen(lable);9                                         |  ~                                          |  9     printf("[%-100s][%d%%][%c]\r",bar,ra
~                                           |  ~                                          |    te,lable[rate%len]);
~                                           |  ~                                          | 10     fflush(stdout); //需要刷新出来
~                                           |  ~                                          | 11     bar[rate++]=STYLE;
~                                           |  ~                                          | 12 }
~                                           |  ~                                          | 13 
~                                           |  ~                                          | 14 void download(callback_t cb)
~                                           |  ~                                          | 15 {
~                                           |  ~                                          | 16 
~                                           |  ~                                          | 17   int total=1000;
~                                           |  ~                                          | 18   int cur=0;
~                                           |  ~                                          | 19   while(cur<=total)
~                                           |  ~                                          | 20   {
~                                           |  ~                                          | 21     cb(cur*100/total);
~                                           |  ~                                            22     cur+=10;
~                                           |  ~                                          | 23     usleep(50000);
~                                           |  ~                                          | 24   }
~                                           |  ~                                          | 25   printf("\n");

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cesium 实战 - 自定义纹理材质系列之 - 半球雷达效果(力场闪烁)

Cesium 实战 - 自定义纹理材质系列之 - 半球雷达效果(力场闪烁) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材…

后端Web之数据库(以MySQL为例)

目录 1.概述 2.MySQL 3.DDL 4.DML 5.DQL 1.概述 对于我们自己写的一些小功能&#xff0c;数据一般存储在文件中&#xff0c;比如XML文件。而在实际项目中&#xff0c;数据都是存放在数据库中的。数据库&#xff08;DataBase &#xff09;是一个存储数据的集合&#xff0c…

OpenCv图像处理: 时域滤波与频域滤波

时域滤波&#xff1a; 空间域滤波的步骤一般如下&#xff1a; 1. 选择滤波器 选择一种低通滤波器&#xff0c;常见的包括&#xff1a; 均值滤波&#xff08;平均滤波器&#xff09;高斯滤波&#xff08;Gaussian filter&#xff09; 2. 定义滤波器核 根据选择的滤波器类型&…

【C++篇】迈入新世界的大门——初识C++(上篇)

文章目录 C发展历史C起源C版本更新C23小故事 C在工作领域的应用C参考网站及文档书籍编程语言排行榜C难度参考文档书籍参考文档参考书籍 C第一个程序命名空间为什么要使用namespacenamespace定义及规则命名空间使用 C输入&输出名字含义 缺省参数函数重载 C发展历史 C起源 …

VUE中出现Cannot find module ‘@/api/xxx.js‘ or its corresponding type declarations

在使用VSCode编写Vue程序时发现之前使用以下代码时却报出了错误 import {getEmployeeList} from /api/employee\ 保证文件地址正确且其中的方法也可以正常调用&#xff0c;只是报出了错误&#xff0c;该行代码上加入一个‘//ts-ignore’就可以解决。 修改后的代码 //ts-ig…

python基础篇(15):闭包

在函数嵌套的前提下&#xff0c;内部函数使用了外部函数的变量&#xff0c;并且外部函数返回了内部函数&#xff0c;我们把这个使用外部函数变量的内部函数称为闭包。 1 简单闭包 def outer(logo):def inner(msg):print(f"<{logo}>{msg}<{logo}>")retu…

苹果(ios)私钥证书和profile文件申请教程

苹果&#xff08;ios&#xff09;私钥证书&#xff0c;可以理解为p12后缀的苹果证书&#xff0c;我们在苹果开发者中心可以生成cer格式的证书&#xff0c;然后使用mac电脑或者第三方转换成p12后缀格式的私钥证书。 证书profile文件&#xff0c;又叫描述文件&#xff0c;这个文…

Android系统和开发--安全性和权限管理 SELinux 策略 安全架构

学习android权限知识 SElinux chmod -R 777 ./ setenforce 0 adb root su fastboot oem at-unlock-vboot adb disable-verity Android权限 Android系统是基于Linux内核构建的&#xff0c;因此它继承了Linux的权限管理机制。Android应用需要通过声明权限来访问系统的某些功能&…

融资融券利率和手续费详情,融资融券开通门槛50W资产必须沪深市值?

融资融券利率和手续费 融资融券就是可以向证券公司借钱借券来进行证券交易&#xff0c;实现杠杆操作。融资是向证券公司借款买入股票&#xff0c;而融券则是向证券公司借入股票并卖出。 融资融券的利率是浮动的、个性化的&#xff0c;但一般最低可以达到4.0%~5.0%&#xff0c…

Selenium + Python 自动化测试14(发送报告)

我们的目标是&#xff1a;按照这一套资料学习下来&#xff0c;大家可以独立完成自动化测试的任务。 上一篇我们讨论了使用HTMLTestRunner 生成HTML报告的方法。 本篇文章我们接着讲生成HTML报告是否可以自动邮件发送出去&#xff0c;提高我们测试报告的及时性&#xff0c;方便…

WordPress美化节日灯笼插件,适合春节的时候使用

源码介绍&#xff1a; WordPress美化节日灯笼插件&#xff0c;适合每年过年的时候安在网站上使用&#xff0c;这款插件可以备用着&#xff0c;一款WordPress节日灯笼美化插件&#xff0c;可以给网页自动加一个灯笼效果使用说明&#xff1a;到网站WP后台 - 插件 - 安装插件 - 上…

Java代码基础算法练习-乘阶求和-2024.08.18

对应的源代码可以在我的 Gitee 仓库中找到&#xff0c;欢迎star~ [Gitee 仓库](https://gitee.com/yukongji/java-basic-algorithm) 任务描述&#xff1a; 求Sn1!2!3!4!5!…n!之值&#xff0c;其中n是一个数字(n<10)。 解决思路&#xff1a; 输入: 读取用户输入的 n 值。检查…

Android:使用Gson常见问题(包含解决将Long型转化为科学计数法的问题)

一、解决将Long型转化为科学计数法的问题 1.1 场景 将一个对象转为Map类型时&#xff0c;调用Gson.fromJson发现&#xff0c;原来对象中的long类型的personId字段&#xff0c;被解析成了科学计数法&#xff0c;导致请求接口失败&#xff0c;报参数错误。 解决结果图 1.2、Exa…

leetcode108.把升序数组转换成二叉搜索树

题目描述 [-10,-3,0,5,9] 转换成如下二叉搜索树&#xff1a; 解题的核心原理是&#xff1a;二叉搜索树的中序遍历结果是一个升序数组&#xff0c;所以根节点的数值&#xff0c;也位于数组的中部。 class Solution {public TreeNode sortedArrayToBST(int[] nums) {return h…

基于Hadoop的汽车大数据分析系统设计与实现【爬虫、数据预处理、MapReduce、echarts、Flask】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍爬虫数据概览HIve表设计Cars Database Tables1. cars_data2. annual_sales_volume3. brand_sales_volume4. city_sales_volume5. sales_volume_by_year_and_brand6. sales_distribu…

MATLAB 手动实现一种高度覆盖值提取建筑物点云的方法(74)

专栏往期文章,包含本章 MATLAB 手动实现一种高度覆盖值提取建筑物点云的方法(74) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 手动实现一种基于高度覆盖值的建筑物点云提取方法,适用于高大的城市建筑物,比只利用高度提取建筑物的方法更加稳定和具有价值,主要…

IntelliJ IDEA 集成 ShardingSphere-JDBC 访问分库分表

背景 众所周知&#xff0c;IntelliJ IDEA 是 Java 领域常用的开发工具之一&#xff0c;IDEA Ultimate&#xff08;旗舰版&#xff09;或其他例如 DataGrip 等 Intellij 平台的工具都集成了对数据库的访问能力。 但是&#xff0c;对于做了分库分表的项目&#xff0c;直接使用 …

消防隐患在线小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;消防隐患举报管理&#xff0c;消防隐患分类管理&#xff0c;统计分类管理&#xff0c;处理结果管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;我…

学习笔记 韩顺平 零基础30天学会Java(2024.8.18)

P514 Vector源码解读 P515 双向链表模拟 LinkedList的添加和删除可以通过改变节点的指向完成 遍历的时候&#xff0c;如果要重新遍历&#xff0c;要把指针调回到最前面或者最后面&#xff0c;才能重新全部遍历一次 插入的时候&#xff0c;插入对象的next和pre都要操作&#xff…

探索tailwindcss多主题切换

现在的多主题切换基本上都是用的 css 变量的形式, 而tailwindcss也支持 css 变量定义主题的方式 至于为什么用 tailwindcss变量, 还是因为 tailwind 写类名提示比较方便, 也不需要再在css或者style中去一个个var的形式去写变量了 这里我在assets/style/theme文件夹中创建了三个…