- 博客(31)
- 收藏
- 关注
原创 AI 应用开发
注入 OpenAiApi,OpenAiApi 是真正“干活”与 OpenAI 服务器对话的工具,后续 SpringAI 的封装层,比如说 ,其内部持有 的实例 方法产生流式对话 :“文本向量化”工具调用 OpenAI 的 API 来生成“词嵌入”(Embeddings)。词嵌入是一种将文本(如单词、句子)转换为数值向量(一串数字)的技术,这些向量能捕捉文本的语义含义。:连接到 PostgreSQL 的“向量数据库”存储、管理和检索由上一个 Bean(embeddingModel)生成的向量。这
2025-10-27 11:45:14
669
原创 基于 go 的分布式缓存
代码解析1. 配置 ( 和 ) 结构体: 定义了连接 etcd 所需的配置,包括 etcd 服务器的地址列表 () 和连接超时时间 ()。 变量: 提供了一个默认配置,方便快速使用。默认连接本地的 etcd (),超时时间为 5 秒。2. 核心注册函数 ()这是实现服务注册最关键的函数。函数签名: 接收三个参数:: 服务的名称,例如 “user-service” 或 “product-api”。: 服务的网络地址,例如 “192.168.1.10:8080” 或仅仅是一个端口 “
2025-10-13 20:52:23
723
原创 go 基础
类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值), 它们针对给定接口值所存储的值的类型进行比较。试着修改示例程序中的切片操作,向外扩展它的长度,看看会发生什么。数组的长度是其类型的一部分,因此数组不能改变大小。这看起来是个限制,不过没关系,Go 拥有更加方便的使用数组的方式。的底层数组太小,不足以容纳所有给定的值时,它就会分配一个更大的数组。每个数组的大小都是固定的。一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。
2025-10-03 16:01:51
768
原创 手写跳表 - Java
跳表是算法设计中简洁性和概率力量的有力证明。它为其核心操作实现了令人垂涎的OlognO(\\log n)Ologn平均时间性能,可与复杂的平衡树相媲美,但其实现却更直接、更容易理解。这段 Java 代码提供了一个极佳的、真实世界的例子,展示了如何从零开始构建一个跳表,并配备了泛型和数据持久化功能。它是每个开发者工具箱中一个强大的工具,也是算法优雅之美的一个完美例证。跳表是一种概率性数据结构,基于多层链表,每一层都是下一层的一个子集。
2025-09-10 12:44:36
1004
原创 手写 Tomcat
使用 Socket 简单实现ResponseHttpServer03 动态 Response : 按照规范构造返回流04 各司其职的 Server : 拆分响应模块与处理模块#mermaid-svg-2INa1N7vV9JzTK1K {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2INa1N7vV9JzTK1K .error-icon{fill:#5522
2025-09-04 11:55:24
5208
原创 MySQL 是怎样运行的学习总结
如果我们乐意,我们可以连接任意数量张表,但是如果没有任何限制条件的话,这些表连接起来产生的 笛卡尔 积 可能是非常巨大的。比方说3个100行记录的表连接起来产生的 笛卡尔积 就有 100×100×100=1000000 行数 据!涉及单表的条件这种只设计单表的过滤条件我们之前都提到过一万遍了,我们之前也一直称为 搜索条件 ,比如 t1.m1 > 1 是只针对 t1 表的过滤条件, t2.n2 < ‘d’ 是只针对 t2 表的过滤条件。涉及两表的条件。
2025-08-11 12:21:50
677
原创 JVM 学习总结
程序计数器,也常被称为 PC 寄存器,是 JVM 内存模型中一块非常小的内存空间。你可以把它想象成是当前线程正在执行的字节码指令的地址或行号指示器。简单来说,它就是一个“书签”,记录着虚拟机“读”到了哪一行代码,下一行应该“读”什么。在 JVM 的规范中,每个 Java 线程都有其自己独立的程序计数器。这些计数器在线程创建时一同创建,并伴随线程的整个生命周期。特性描述定义当前线程所执行的字节码指令的地址指示器。作用控制程序执行流程,实现分支、循环、跳转、异常处理、线程恢复等功能。归属线程私有。
2025-08-02 00:20:41
862
原创 仿小红书交流社区(微服务架构)
在单体项目中,使用 ThreadLocal 就可以满足要求,但在微服务项目,存在微服务间调用的问题,这时 ThreadLocal 就不能保证全局上下文,需要放置拦截器,将信息放在请求头中,保证透传。这个项目提供的注册方式手机验证码,当尝试通过手机号注册时,会先检查数据库,如果存储则返回原有账户,如果不存在则新加一个账户插入到数据库中,用户的 Id,是由上文提到的分布式 id 服务生成的。用户在注册成功后,默认设置为普通用户,并将用户的角色缓存在 redis 中,供后续网关鉴权使用。
2025-07-03 20:51:05
1013
原创 Spring 源码阅读(循环依赖、Bean 生命周期、AOP、IOC) - 5.2.15.RELEASE
先说 “一级缓存” 作用,变量名为singletonObjects,结构是Map<String, Object>,它是单例池,将初始化好的对象存入,供其他线程使用。若无一级缓存,无法保证 Spring 单例属性。直接看 “三级缓存”,变量名为singletonFactories,结构是Map<String, ObjectFactory<?>>,其Value是对象的代理工厂。三级缓存作用是存放对象的代理工厂,核心是通过工厂生成 “半成品单例 Bean” 以打破循环依赖。
2025-05-25 10:40:27
713
原创 ThreadPoolExecutor源码阅读以及手写简单线程池 —— JDK17
如果想知道线程是否正在执行任务,只需要调用 Woker 的 tryLock 方法,根据是否加锁成功就能判断,加锁成功说明当前线程没有加锁,也就没有执行任务了,在调用 shutdown 方法关闭线程池的时候,就时用这种方式来判断线程有没有在执行任务,如果没有的话,会尝试打断没有执行任务的线程。这段代码主要为了并发情况下,线程数量的问题,其内部的循环尝试通过 CAS 增加线程的数量 c,如果成功则通过 retry 退出外部循环继续向下执行,如果失败,则继续尝试,直到成功或者条件不符。
2025-05-10 18:00:46
894
原创 MyDB - 手写数据库
当释放一个 DateItem 引用时,会将对应的 references 减一,如果 references 为零, 则会清除该缓存,对应的 page 引用也减一,如果此时 page 的引用也为零,就会将该 page 写回磁盘中。可以注意到,被选择的页,会直接从 PageIndex 中移除,这意味着,同一个页面是不允许并发写的。此框架的作用是向上提供缓存,向下读取文件,使用引用计数的方式来处理缓存,当从缓存读取一个数据,对应的计数加一,当上层应用不在使用该缓存时,对应的计数减一,当计数为零时,会写回文件。
2025-05-05 19:42:46
1272
3
原创 SQL学习总结
存储过程是一组为了完成特定任务而预先编译并存储在数据库中的 SQL 语句集合。你可以把它想象成编程里的函数,它接收输入参数,执行一系列操作,还能返回结果。触发器是在插入、更新和删除语句前后自动执行的一堆SQL代码。在建立二级索引时,主键会自动加入二级索引中。视图可以简化查询,也可以提供一层抽象。事件是根据计划执行的任务或者一些。视图不存放数据,它只是查询的结果。
2025-03-31 20:21:30
1036
原创 Java-动态代理学习总结
类似与Spring中的AOP,是对原有代码的增强,也是对原有代码的封装在Java中,代理(Proxy)是一种设计模式,用于控制对某个对象的访问。代理模式通过创建一个代理对象,来替代原始对象,以实现对原始对象的访问控制。代理对象和原始对象实现相同的接口,客户端对象可以透明地使用代理对象。
2025-02-17 19:57:30
348
原创 SpringCloud学习总结
Component //自定义断言Config> {@Override@Override@Overrideif (first!@Validated@NotEmpty@NotEmpty- name: Vip #自定义断言args:value: lei此断言判断https://cn.bing.com/user=lei,如果user不等于lei则拒绝访问@Component@Override@Override}));
2025-01-31 21:52:29
733
1
原创 NIO学习总结
而引入Selector后,可以将Channel注册在Selector上(相当于Channel添加到Selector这个集合中),每个由这个Channel所触发的事件,会放在SelectionKey中,然后由selector.select()进行阻塞,一旦有事件发生,就会处理。这段代码处理accept事件,并将客户端的channel注册在selector上,对可读事件进行反应,下次客户端发来数据,该channel会触发可读事件并添加到SelectionKey中,等待处理。将多个buffer写入同一个文件中。
2025-01-01 10:31:33
964
原创 JUC学习总结
文章目录锁锁机制原理Mark WordCAS重量级锁轻量级锁偏向锁volatile关键字Lock和Condition接口LockCondition可重入锁公平锁和非公平锁读写锁锁降级和锁升级原子类并发容器CopyOnWriteArrayListConcurrentHashMap阻塞队列线程池线程池的使用锁锁机制原理synchronized使用的锁就是存储在Java对象头中的,在Java中,对象存储在内存中,而每个对象内部,都有一部分空间用于存储对象头信息,其中就包含锁的信息monitorenter
2024-12-27 17:11:17
802
原创 操作系统—段、页、虚拟内存
虚拟内存(Virtual Memory)是操作系统提供的一种技术,它允许程序使用比实际物理内存更大的地址空间。页(Page)是另一种内存管理方式,它将内存划分为固定大小的块,称为页框(Frame),同时将程序的逻辑地址空间划分为相同大小的块,称为页。假如说直接将程序的程序段、数据段直接放入内存中,有可能会造成内存浪费,比如两个段之间有一小段内存,不会被使用,造成浪费,这就是内存碎片。从用户角度看,内存是一段连续空间,可以自由地将程序的段放入内存中,而虚拟内存可以将数据放入内存的页中。
2024-12-23 15:57:10
374
原创 Java并发编程基础篇
的线程的ThreadLocalMap中以该线程为key,赋的值的为值来创建当前线程的对应的HashMap,在Java中,启动main函数时,其实启动的是一个JVM的进程,尔main函数所在的线程是主线程。是进程的一个执行路径,一个进程可以有多个线程,线程之间共享进程的资源。:使用完这些变量后要及时删除,否则可能会造成内存溢出。在线程中对ThreadLocal赋值时,实际上是。是系统分配资源的基本单位,
2024-12-09 19:28:39
320
原创 mybatis复杂查询一对一,一对多
这段 MyBatis 配置代码用于查询。这段 MyBatis 配置代码用于查询。表的数据,并通过关联查询获取。表的数据,并通过关联查询获取。
2024-11-29 21:08:16
523
原创 反射与注解
注解是提供一种为程序元素设置元数据的方法,理解起来还是一样的,程序元素就是指接口、类、属性、方法,这些都是属于程序的元素,那啥叫元数据呢?就是描述数据的数据(data about data)通过class对象获取类的方法,但在使用方法时,要指名那个对象。运行结果发现输出为真说明类的class对象在内存中是唯一的。将上述代码的class文件反编译后。可以通过反射获取构造器来构造对象。可以看出注解本质是一个接口。
2024-11-28 21:15:27
423
原创 SpringBoot3+Vue3 前后端分离项目基于Jwt的校验方案
使用redis实现黑名单功能,用户在退出登录时会将token的uuid存放在redis数据库上,用户在每次请求数据时,后端会校验。用户每次向后端请求数据,会携带token,在SpringSecurity过滤链中进行校验。包装成一个map,并转存到消息队列中,还有将验证码存入到redis中,供后续验证。首先用户向后端请求验证码,来验证邮箱是否正确,以此来判断用户是否可以重置密码。在队列的监听器中,监听器根据队列里的内容发送对应邮件。用户在请求验证码时,后端会将用户的。实现mapper,service。
2024-11-27 09:46:41
637
原创 王爽汇编总结
实际上在执行cal指令会将cal的下一个指令压入栈,在执行ret的指令时,会将栈顶的数据pop给IP。在内存中指令和数据没有差别,都是二进制信息,cpu将CS:IP指向的内存视为指令。观察红色方框,发现汇编指令与源代码不符,这样因为数据与指令混在一起,而在内存中。在debug中查看,代码先执行一遍s代码,然后执行loop,相当于c++中的。汇编中的数组与c++类似,不过汇编中的数组偏移的单位是字节。在c++中函数的目的是可以重复调用某段代码,在汇编中使用。,观察上图的栈帧,发现此时的栈顶数据正是。
2024-11-21 11:41:40
933
原创 基于Servlet实现上传和下载文件
基于servlet可以实现前后端分离,前端的html页面中可以用form表单,后端可以在service方法中实现上传与下载
2024-09-17 17:10:15
889
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅