- 博客(54)
- 收藏
- 关注
原创 谈谈java中的SPI是什么
这是这个接口的具体方法,我们都知道数据库必须有Driver驱动,但是市面上的数据库种类繁多,比如有Mysql,Oracle,Druid等等,所以不同的数据库就需要利用JDK包下的这个Driver接口去实现自己各自的Driver实现类。其实这就是SPI,那么我们如果项目中有很多依赖,都实现了这个Driver接口,我们还可以在运行时,通过某种加载器(ServiceLoader,待会后面会讲)实现灵活的切换,而不用去显示的通过注解去注入不同的实现类。我们看看Mysql是如何去实现这个Driver接口的。
2025-06-04 11:17:11
801
原创 mysql隐式转换会造成索引失效的原因
如果本身字段是字符串类型,等号右边的值却是一个数值类型,那么会造成索引失效,因为字符串转化为浮点类型的时候,对非数字开头的会进行截取,同样也可以满足条件。这也是一种隐式转化,我们看看前面那7点,还是第7点会满足,等号右边的值‘88’还是转化为88,左边数据库里面的score本身就是int类型,所以匹配的结果还是1.好,现在我们换一个方向 ,就是重新新建一个字段叫做score,分数,然后类型是int类型,同时也为它创建索引。code是一个字符串类型,但是查询的值是一个数值类型,那么现在查询的结果是。
2025-05-30 17:02:53
595
原创 面试必懂:讲清Mysql的redo log 日志过程
当我们某个事务进行update更新的时候,事务提交之后,万一此时Mysql服务器宕机了,那么提交的事务就丢失了,也就不糊更新数据了,那么redo log就是在解决这种情况的,可以将修改的记录存放到redo log file中然后等服务器回复之后,就可以重新恢复事务提交的数据。的时候,是最稳妥的方法,不会丢失数据,因为如果你是0的话,写入到OS Buffer中,再每隔一秒进行刷盘,就代表有可能丢失这1秒之内的数据。我们知道Mysql事务的特性是ACID,A是原子性,C是一致性,I是隔离性,D是持久性。
2025-05-29 15:43:38
390
原创 浅谈Mysql的MVCC机制(RC与RR隔离级别)
继续向前找,100,100 不在活跃的事务ID列表里面,100也不等于创建当前ReadView的事务ID300,100比最小事务ID还小,可以访问,所以RC级别下读到的结果就是小红,那么如果是RR级别下读到的是什么呢?读已提交不会造成脏读,从名字来看就是已提交,就是解决读未提交产生的问题,它不会产生脏读,但是它会产生不可重复读,不可重复读,指的就是一个事务一直读取同一条记录,但是会被其他事务的更新操作影响到读取的结果,造成数据不一致。从第一个版本看,200,在活跃的事务ID列表里面,不可见,
2025-05-27 11:37:44
1210
原创 你知道mysql的索引下推么?
在储存引擎层的时候,还是只会通过辅助索引树的叶子结点找到name是为姓周的,而age是不管的(Mysql5.6的时候会管),然后再通过叶子结点上索引对应的主键ID回表主键索引树,找到主键对应的行记录,然后再把周的那些行记录返回给Mysql的Server层,Mysql服务层再此层再筛选出age大于25的行记录,再把结果返回给客户端。那么能不能就一次性在辅助索引树上就把姓周并且age> 25的筛选出来,那么这样的话就可以只回表一次,然后直接将最终结果返回给Mysql的Server层既可。
2025-05-20 18:08:02
380
原创 谈谈各种IO模型
select操作可能会阻塞,直到有某个请求数据就绪的时候才不会阻塞,但是阻不阻塞其实取决于timeout参数,值为0,那么就是没有请求数据就绪就直接返回,不用阻塞等待,可以干其他事情,就是应用程序发起一个read或者write请求的时候,后面的事就完全不用参与了,此时如果数据还没准备就绪就会立即返回,不用阻塞等待,可以继续干其他事,如果数据准备就绪,那么操作系统会将数据从内存拷贝到应用程序,然后通过回调通知应用程序,应用程序就可以直接读取就行了,不用再由应用程序去自己参与拷贝了。那么就是接下要介绍的。
2025-05-13 17:09:59
672
原创 最容易被忽视Http请求中的Accept
很奇怪,这个报错,完全没有思路,然后我就搜索了一些辅助工具,说是JSON解析异常,然后我就打印了返回结果发现是一个xml格式,我就纳闷了,为啥是xml格式,明明打印出来请求头header中的content-type是application/json,然后我就在我的过滤器里面,对请求头的content-type重新进行赋值一遍。然后就进行了排查,在过滤器filter中打印了请求头的content-type,我就想会不会是这个Accept的问题,然后我就了解了一下这个Accept的含义。
2025-05-09 17:35:07
391
原创 mysql数据表日期时间的类型还在用varchar或者char?
②当我们通过sql查询进行比较大小的话,比如where colume > '2025-05-09 10:38:15',数据库查询的时候是会一个字符一个字符进行比较,而DateTime和TimeStamp在比较的时候速度更快,数据库会直接转化为数值类型进行比较。①字符串的日期时间,存储占用的字节数多,如果一个字符按照一个字节,那么yyyy-MM-dd hh:mm:ss 这种格式应该是19个字符,也就是19个字节,DateTime占用的字节数是5-8,TimeStamp占用的字节数是4-7;
2025-05-09 11:24:06
320
原创 一篇文章讲清楚mysql的聚簇索引、非聚簇索引、辅助索引
聚簇索引如果索引列上的值发生改变的时候,不仅要重新维护索引在树中的有序关系,而且聚簇索引的叶子节点存放了索引和数据,所以数据也需要修改。非聚簇索引的索引和数据是分开存储的,叶子节点存放的是索引和指向数据文件的地址,通过叶子节点找到索引,再通过索引找到地址,再通过地址指向数据文件具体的数据。查询的时候select的字段也是索引字段,那么在找到索引之后直接读出来就可以了,就不用回表查询了,但是如果select的字段有其他额外的字段,那么就必须回表操作了。聚簇索引的索引和数据是存放在一起的,都是在叶子结点;
2025-05-08 17:40:55
368
原创 MYSQL之索引结构,为何要用B+树
只有叶子结点是存放数据的,同时叶子结点与叶子结点之间还有指针指向,那么对于范围查询也比较适合,就不用从根节点重新开始查找了,比如我要找id>17的,那么当我找到17的,直接向右查找就可以了,就不用每次都从根节点开始查找。但是也有缺点,因为索引是存放在一个磁盘页的,一个磁盘页只存放一个索引和数据,不但没有充分利用磁盘页的空间,而且当数据量越来越多的时候,这样就会创建更多的节点,节点越多,树的高度也就越高,那么查找的效率也就会降低了,磁盘IO次数多。19和11比较,19> 11,那么走右节点,右节点是18,
2025-05-08 11:45:57
517
原创 准确且通俗的文章:mysql在RR隔离级别下一定能解决幻读么?
我们首先要知道什么是幻读,幻读也就是说在一个事务中多次读取相同的记录,查询出来的结果最终会收到另外一个事务的insert而导致结果变化了。如果一个事务只有当前读,那么无论其他事务如何insert,mysql是通过next-key lock或者是record lock解决幻读。mysql在RR级别下不能完全解决幻读情况,如果出现当前读和快照读混合的情况,那么是可能无法解决幻读的。如果一个事务只有快照读,那么无论其他事务如何insert,mysql的MVCC是能够解决幻读的。其实说的都是很片面。
2025-05-07 17:10:21
531
原创 AOP的强大之处,一篇搞懂@Around环绕通知
我们看后面3个操作,假如我们抛开网关统一认证的事,就假如为了这个例子,每个方法我们都需要进行身份认证才能执行相关操作。那我们此时就可以定义一个切面,去为这几个方法进行相同的方法增强,就不用每一个方法都写相同的认证操作。环绕通知我们就写好了,就是在方法执行之前以及方法执行之后对目标方法进行方法增强,可以省去很多多余重复的操作。Aop面向切面编程说到底就是在不改变源代码的情况下,遇到一些重复且代码量多的情况,切入到每一个目标方法,对目标方法进行方法增强。:对目标方法进行方法增强所定义的方法。
2025-04-23 14:58:40
405
原创 绝对对你有用!EasyExcel对特定的区域范围进行合并代码
那么如果我们要合并的excel数据,就是单纯固定要对哪几列以及哪几行组成的这个“正方形”进行合并,那么就没有太多的代码,也就是说只有一个“正方形”,那么这种情况一般就是导出单表到一个sheet的情况,那么我们就可以省去那些分组的逻辑。那么对于这种情况,肯定需要多个“正方形”区域,那么我们就需要进行分组,按照主表的比如“编码”进行分组,然后看看重复的从表有多少行,这样我们就可以确定从哪一行到哪一行需要合并了。这种情况的改造就自己去改造,很简单的。1、构造“正方形”,第几行到第几行,第几列到第几列。
2024-11-27 17:29:17
586
1
原创 java中事务中遇到锁会造成什么问题,以及该如何解决?
当代码执行完毕,也就是finally里面的锁都释放了,去提交事务,但是提交事务也是需要时间的,有可能还没提交事务完,由于锁释放了,其他客户端就会拿到锁了,但是此时该用户感知不到此时DB数据库中的数据是最新的,也就是所谓的可见性,什么是可见性?在spring中实现事务有多种方式,主要是两种:一种是声明式事务,一种是编程式事务,今天我们就讲声明式事务中的一种,使用注解@Transactional,这个注解的作用就是帮助我们在代码执行完毕之后自动提交事务,在发生异常时进行回滚。而非释放锁之后再提交事务。
2024-06-05 11:24:06
1384
原创 巧用java8的stream流的.collect(Collectors.toMap(arg1,arg2))
按照java的sql思路,我们直接通过left join去关联表就行了,但是该低代码平台有对sql连表查询有限制,就是有些表它是存在一个domainKey的,实体表的domainKey如果不相同的话连表是不允许的。所以就无法使用连表了。巧用java8的stream流的.collect(Collectors.toMap(arg1,arg2))适用于通过返回结果的id查对应表的某一个数据。所以最终的想法,就是单独查询xxx_id对应表名的数据,查询xxx_id对应表名的数据,查询ddd_id对应表名的数据。
2024-05-28 17:58:56
297
原创 java同步大量数据到本地数据库方法总结
由于同步任务是一个非常耗时的操作。所以我们可以用一个调度任务然后在夜间某个时间点进行同步,当然由于三方接口返回的数据也会进行更新的,所以我们可以进行增量同步,但是我们并不知道更新的是哪些数据,当然你可以去挨个数据对比,但是比较麻烦,所以我们只能先做全部删除,然后再做全量同步。但是全部删除delete from 实则也是一个耗时操作,实际也是一行一行删除的,相对比全量同步可能稍微会快点,所以我们也需要对全部删除分批次+同步串行 或者是分批次+异步并行,也就是帮我们上面的同步串行改成删除就可以了。
2024-05-01 12:06:38
1182
2
原创 赞:java使用easy-excel导入模板下载提供用户进行导入
是相同的思路,只是我们导出数据是对前端表格页面上勾选的数据导出到excel,此时excel里面的数据就是前端表格页面上的数据行记录,但是我导入模板下载说白了也是导出一个excel,只不过excel里面的数据是我们自己定义的固定模板表头(封装实体)一般就是一行。导入模板下载其实就是导出,只不过导出到excel的数据是我们自己自定义的数据。就是我们在点击导入的时候,一般都是有一个模板的,我们需要下载这个模板,然后再按照这个excel模板填充数据之后,再导入。那么导出模板下载,说白了和前面一篇。
2024-04-18 17:48:23
392
原创 赞:java使用easy-excel导入数据的通用模板思路
1、需要一个输入流(当然也可以读取一个固定路径盘符的文件filename+'.xls');我们在项目中都会有导入导出的功能,这篇文章主要是讲导出的,导入我会在另外一篇博客文章中讲解。1、需要一个输入流(当然也可以读取一个固定路径盘符的文件filename+'.xls');这个方法仅仅是从外部excel文件导入后解析进行返回数据给前端展示,但并未保存到数据库。这个方法就有了,就是从外部的excel文件导入接续之后,保存到数据库。首先:需要在项目中的pom.xml中导入easy-excel的依赖。
2024-02-21 11:39:24
516
原创 赞:java使用easy-excel导出数据的通用模板思路
4、准备存放导出的路径,fileName+‘.xls’,但是一般我们是在测试的时候才会写特定的存放路径,在系统里面,我们一般是直接用outputStream输出流,让用户自己选择导出的盘符路径。4、准备存放导出的路径,fileName+‘.xls’,但是一般我们是在测试的时候才会写特定的存放路径,在系统里面,我们一般是直接用outputStream输出流,让用户自己选择导出的盘符路径。我们在项目中都会有导入导出的功能,这篇文章主要是讲导出的,导入我会在另外一篇博客文章中讲解。
2024-02-20 18:05:42
735
原创 java中实体pojo对于布尔类型属性命名尽量别以is开头,否则 fastjson可能会导致属性读取不到
假如我们有一个场景,就是需要将一个对象以字符串的形式,也就是jsonString存到一个地方,比如mysql,或者redis的String结构。success还是success,valid还是valid,证明可能是fastjsob框架在解析的时候会默认把is去掉。现在我导入fastjson依赖,创建一个CusPojo对象,然后序列化为jsonString,我们打印结果如何。有两个属性是布尔类型的,一个属性是有is开头,一个是没有is开头的,我们就可以做个对比。
2024-02-19 17:06:12
944
原创 一般系统的请求认证授权思路【gateway网关+jwt+redis+请求头httpheader】
redis中有两个key,一个key就是刚刚关于认证token的,另一个就是授权的。gateway:网关,我们都知道网关的作用就是对系统的所有请求,网关都会进行拦截,然后做一些操作(例如:设置每个请求的请求头httpHeader,身份认证等等)此时一般会使用到网关过滤器,创建一个过滤器去实现GlobalFilter接口。登录接口是不需要进行拦截的,我们在登录接口的时候,如果登录成功,才会生成一个token,还有查询该用户对应的菜单权限API列表,然后会把相关信息存到redis中去。
2024-02-05 14:32:13
1570
原创 spring中生成jwtToken字符串以及解析手写通用工具类
我画一个jwt的对象结构图出来,其实只要按照这个结构来就很容易理解上面的工具类中的生成和解析代码。当前使用JWT,肯定得提前准备jwt相关的导入依赖。-- 关于jwt 生成令牌-->
2024-02-01 18:23:34
511
原创 系统登录的时候的密码如何做到以加密的形式进行登录【java.security包下的api】工具类。
所以以后在登录的时候呢,前端会对界面输入的明文密码进行公钥加密成密文密码,然后再传给后端,后端就会利用私钥进行解密解密出明文密码,然后与数据库的进行比较。如果大家觉得这篇文章对大家有所帮助的话,希望能给个免费的赞赞,也祝各位码农在未来的IT道路上能越走越远。我们写一个测试方法,看看明文加密之后的密文,在经过解密后的明文是否一致。使用java.security包下的api进行密码的加密传输(公加私解)四个方法我直接贴出来,两个方法是关于公钥的,两个方法是关于私钥的。
2024-01-24 17:56:48
838
原创 如何在一个集合对象中A排除另外一个集合对象B中A中拥有的数据通用思路,很精妙!
所以模板思路就是以后我们要在哪一个集合对象里面排除另一个集合对象,那么我们就将要排除的做map映射,然后对另一个集合对象做filter过滤掉contains为false的,就是最终的结果,以这个题目就是A排除B,那么就将B做map映射,将A做filter过滤掉contains为false的。只是我们需要将里面的那个contains过滤掉为true的,然后最终结果如果返回的集合存在数据,就代表有交集了,有交集,肯定就是出现重复的了。外层循环遍历集合对象B,内层循环遍历集合对象A,也是可以的。
2024-01-23 17:03:24
945
原创 springboot实现文件上传与下载的通用思路模板流程
一般我们的参数是一个文件名或者是一个文件编号ID,因为可能存储在一些非关系型数据库,比如MongoDB,那么我们上传时保存到MongoDB就会有一个文件编号ID,所以我们下载的时候,就通过ID找到实际的File,是这样获得的。这就是springboot实现文件上传与下载的通用思路模板流程,具体可以根据自己的业务场景进行修改。需要将参数设置成为MultipartFile类型。
2024-01-09 14:53:48
653
1
原创 为什么需要在bean上使用@EqualsAndHashCode(callSuper = true)这个注解
所以一开始两个child虽然他们的code是不同的,name是相同的,但是由于没加上这个注解,忽略了父类的code,只会关注子类Child的name,就会就是true了。创建了两个Child,属性code是不一样的,一个是c1,一个是c2,但是name是相同的,都是“小毛孩”,然后我们现在也没有在子类Child类上加注解@EqualsAndHashCode(callSuper = true),我们看看运行结果是如何,通过运行结果来分析。那么他们的内容值是不同的,为什么最终结果还是true呢?
2024-01-04 11:56:27
492
2
原创 面试官问:你知道try...catch放for循环外面和里面有什么区别吗?什么时候放外面,什么时候放里面?
如果我们就是要统计这一批货物的不合格数是多少,不想终止的话,那么我们就将try..catch放在for循环里面。对比两种运行结果,我们来看看。try...catch在for循环里面的话,不会终止整个for循环,会执行完整个for循环。try...catch在for循环里面的话,不会终止整个for循环,会执行完整个for循环。我们看运行结果,最终还是走完了整个for循环,还是可以统计出不合格数是50。
2024-01-03 18:06:37
858
原创 @Autowired和@Resource注解的区别是什么?
因为@Resource注解默认是按照name名称注入,那么@Resource注解是可以在括号中声明name的,比如@Resource(name = "xxx"),那么它就会按照声明的去找对应的bean,能找到的话就会去找,找不到的话就会按照类型去找吗,那么如果你没有在括号中声明name,直接是@Resource,那么它就会将你声明的变量名作为name,比如第①种情况。而@Autowired默认就是按照类型去找的,所以能找到StringRedisTemplate的bean。可以看到此时控制台是没有报错的。
2023-12-28 16:05:46
425
原创 mysql字段声明的长度是否就是最大长度?比如int(2)最大长度就是2吗,值最大是99吗?
也就是如果你sno设计的是sno int(4) zerofill,那么当你插入1,10,100,1000会是什么结果呢?我们先不着急看答案是什么。①mysql字段括号声明的值并不是字段的值的最大长度,mysql的int占据4个字节,1个字节是8位,最大值是2^32-1 =这三个字段都是int类型的,id和test_number是没有指定长度的,sno是有指定的,我们用sql语句添加该列。所以括号声明的值并不是字段的值的最大长度,mysql的int占据4个字节,1个字节是8位,最大值是2^32-1 =
2023-12-27 15:08:48
506
原创 CompletableFuture底层支撑的是一个线程池嘛?
如果ForkJoinPool.getCommonPoolParallelism() > 1 的话,USE_COMMON_POOL就是true了,如果为true的话,ASYNC_POOL的值就是ForkJoinPool.commonPool()。值是15,> 1 ,说明USE_COMMON_POOL是true,那就证明调用了ForkJoinPool.commonPool()的方法,我们看看这个方法又是如何样的。supplyAsync(),发现这个值是ASYNC_POOL,我们去追溯一下。
2023-12-12 11:13:55
581
1
转载 SpringBoot 项目 Jar 包运行启动加密,防止反编译
最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去。要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来。第一种方案使用代码混淆采用proguard-maven-plugin插件在单模块中此方案还算简单,但是现在项目一般都是多模块,一个模块依赖多个公共模块。那么使用此方案就比较麻烦,配置复杂,文档难懂,各模块之间的调用在是否混淆时极其容易出错。第二种方案使用代码加密采用classfinal-maven-plugin插件此方案比对上面的方案来说,就简单了许多。
2023-12-11 10:57:38
499
原创 jdk21新发布的一种插入有序的Map集合好用之处
然后此时如果我们想获取和数组一样第index下的entry,我们此时用map是解决不了的,那么现在我们用上jdk21的时候,我们可以使用一个新的Map,叫做SequencedMap接口。我们都知道map是一个无序不可重复key的,为什么是无序的,可以自己查看源码去理解,本质原因在于key的hash值,所以现在java21新出了一种可以得到插入有序的map。我现在模拟一个场景就是,我现在要对订单删除的时候,做一些记录,把这些删除的订单记录到系统操作日志里面去,然后我要获取第一条删除的订单记录数据。
2023-12-07 18:16:27
1769
原创 面试常出的关于catch...finally中return的返回结果的题!!
所以,如果finally中有return的话,那么最终返回的值是在finally中确定的,如果finally中没有return的话,那么最终返回的值就是在catch中确定的。直接看finally中有没有return,如果有的话,那么最终返回的值就是在finally中确定的,如果没有的话,就是在catch中确定的。有人说是12,有人说是13,那到底是多少呢?大家觉得最终val的运行结果是多少呢?
2023-12-06 17:14:26
399
1
原创 Optional判断非空的巨大优势!!
的话,value就不为空,那么在调用map映射的时候,此时map()方法会判断Optional成员变量value是否为null,此时不是null,那么不为null的话,就给成员变量value赋值getName()的结果,此时getName()的结果有可能为null的,继续走后面的orElse("Not Found"),orElse会去判断Optiaonal成员变量value的值是否为null,如果前面getName()返回的结果为null的话,就会返回Not Found。待会看看代码就知道了。
2023-11-30 18:01:39
548
2
原创 灵魂拷问:注解括号中不声明变量,直接赋值,这个值是属于注解类中的哪一个变量?
注解括号里面,不注明变量,直接赋值字符串,这个值代表的是注解中变量value的值,而且也只能是value,因为如果注解中没有声明变量value的话,也不可以直接赋值,当出现在注解的括号中声明超过1个变量的时候,就不能省略value了,必须按照"name=value"键值对的方式存在了。然后也添加几个变量,直接在某个测试类比如:CusAnnotationTest声明一个字段username,直接用上该注解,然后赋值一个值,假如是下面这样叫做"张三"也就是说如果你要直接省略赋值字符串,必须包含value变量。
2023-11-30 11:00:34
444
原创 java8的Stream流接口的allMatch()好用之处,赞!!
代码是不是优雅简洁了很多。其实Stream中也有好多api,比如还有一个和allMatch()相似的,叫做anyMatch(),它的意思代表流中只要有任意一个元素满足断言Predicate,那么就会返回true。我需要判断studentDTOS集合中的每一个studentgDTO的enabled是不是都是true,如果都是true,才执行下一个逻辑就是添加到学生数据表中。我的想法思路很简单,就是一个for循环,然后只要判断是false的直接break出去,然后在break出去之前,赋值给一个变量flag。
2023-11-28 18:18:33
1376
原创 java中使用Arrays.asList(T ... a)容易踩add(T t)的坑!!
所以我们就知道了,喔~原来是因为Arrays.asList()返回的是Arrays类里面静态内部类ArrayList对象,这个内部类里面没有对add()方法进行重写,所以调用的是父类AbstractList的add()方法,而父类AbstractList的add()方法就是会直接throw new UnsupportedOperationException();那么它调用的add()就是调用父类AbstractList的add()方法,我们看看AbstractList的add()方法。我们同样也是看源码。
2023-11-28 11:27:58
505
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人