Add an assistant with dify
本文环境: go 1.25 hexo框架 butterfly主题 dify 1.11.4 0 起 突然想给自己的博客网站添加一个ai助手,帮助我提问关于博客有关的知识。 1 选型 目前搭建的博客网站是一个静态网站,是没有后端来处理的,所以为节省成本,不如直接就使用云服务来完成。 最后选择的是dify,他有如下优点: 低代码平台,构建简单 有学生认证的优惠,零成本 2 工作流构建 为了提高输出的质量,考虑将自己的博客内容作为知识库传给ai助手,在工作流中直接识别是否是博客相关内容。 最后构建出来的工作流如图所示: 用户输入问题,通过知识库检索给出检索结果。使用LLM判断query和检索结果是否相关,并输出格式化的数据。 根据格式化的数据进行分支,一路根据知识库结果回复,另一路直接处理回复。 3 知识库的同步 写完博客后,如何将博客内容同步到知识库呢? 有两种方案: 方案一:自动同步 自动去爬取博客内容,定时同步博客知识库。 优点: 自动化程度高 缺点: 需要云服务器来部署服务,自行完成同步。成本较高。 同步的时机需要再仔细考量,是要设置定时任务来更新,还是设置触发器? 维护会更困难 方案二: 手动同步 在本地使用hexo发布博客时使用脚本顺便更新知识库。 优点: 成本低 逻辑简单 容易维护 缺点: 每次都要手动操作,需要多执行一条命令 最后选择的时方案二 4 知识库同步的实现 查看知识库的api文档,看到有“从文本创建文档”这一条目,完美契合需求。 只需要发送类似这样的http请求就可以了 123456curl --request POST \ --url https://api.dify.ai/v1/datasets/{dataset_id}/document/create-by-file \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: multipart/form-data' \ --form 'data={"indexing_technique":"high_quality","process_rule":{"mode":"custom", "rules": { "segmentation":{"separator":"###", "max_tokens":500}}}}' \ --form file='@example-file' 我使用go语言来编写代码 代码逻辑是: 读取命令行参数,确定本地文档所在目录->读取目录下的markdown文档->构建http请求,更新到知识库->返回结果 我的同步代码在这里 代码仓库 还有可以优化的地方,比如使用json等方式缓存已经构建过的文档,防止重复构建。 5 嵌入ai助手 获取js代码:构建好dify应用后点击发布->嵌入到网站->复制js代码 我想实现在所有页面都可以随时点出来询问的效果。 首先在themes/butterfly/layout/_partial目录下创建dify.pug 将代码粘贴到其中。添加模块头dify。 由于footer.pug模块在各个页面中都会出现,可以考虑嵌入到这个部分。 在footer.pug的最后加上模块的引用。 6 测试和微调 本地测试,此时应该已经可以在右下角看到蓝色气泡了,点击应可以正常唤起。输入问题,可以给予正确的回复。 与原有组件冲突问题: 当前气泡只有在页面底部才会出现,页面中间是没有的。 当前气泡的位置与我原来的网站的组件有重叠,所以需要微调位置。 在当前dify版本,气泡的位置是直接由dify-chatbot-bubble-button来控制的。 修改参数,修改right改为60px,同时加上fixed,确保中间也有气泡。 再次测试,就可以获得正确的效果了。 目前还没有适配手机页面,手机竖屏看会有一些问题。
2025电赛小结
2025年电赛小结 序言: 2025年电赛,我们选做的是G题。目前还没有出结果,估计最后不加报告是70分,进国测应该是没希望了。不过对于一个已经转码,决定不搞硬件的人来说其实可以接受了。 日志: 2025年7月30日上午 选定题目 D、G甚至F G:感觉难点在于如何复现信号,保证同频 D:应该算精密测量了 F:完全不想做 G题大题思路: G题最重要的就是测量后DAC复现的问题: 数字滤波器?参数固定,不可即时更改(deprecated)(赛后补充,其实我最开始这个想法是正确的,但是和队长商量后他给出了这样的回复,总之就是还是不熟悉吧,也实现不了) 使用dds合成后dac输出,高精度,或许可以抵消滚波(赛后补充,赛后证明是可以的方案,确实可以实现无反馈锁相,只要输出的基波频率足够准确) 基础部分: 搭出预设的电路 经仿真,是一个低通滤波器 且在100Hz~3kHz范围内放大倍数约在5~0.7倍 后续电压步进要在0.1V,所以dac精度应至少有0.02V 使用ad9959可以轻松达到此精度 发挥部分: 现在有3种方案 1.FIR 2.FFE 3.高精度DDS 串口屏需求: 基础 不加电路100~1MHz正弦波输出 加电路2V 1kHz 1~2V 步长0.1V(100Hz~3kHz)[设置+启动] 发挥 滤波类型判断(学习键) 数字重现(一键启动探究装置) 2025年7月31日上午 完成了基础部分的全部内容,硬件结构有9959->放大器->已知电路模型 12:53:48 “如果解决不了这个问题,就等着退赛吧”,这是队长的原话。 起因是想移植之前写的fft到队长发来的代码框架,但是之后发生了严重问题! 这个程序只要一烧写,芯片就会死锁,然后死掉,程序也不能运行,以为是烧写器或板子的问题,就又换了一个板子,可谁曾想,换了之后另一个板子也崩了。 结果就是stm32都用不了了,这如果解决不了,我们就要退赛了。 烧写后,一直报cannot halt the core,知道这大概是死锁了,原因大概是flash中的程序上电后就在跑,导致了无法烧写。 在经过约一个小时的调试,找到了比较好的解决办法 首先记得条stlink的模式为normal,能够识别到stlink之后参考下述博客 stm32 Invalid Rom Table...
Redis之多级缓存
Redis之多级缓存——亿级流量方案 序言 传统缓存问题: 传统缓存一般是请求到达Tomcat后,Tomcat先查询Redis缓存,如果未命中则查询数据库。存在下面问题: 请求要经过Tomcat服务器,Tomcat的性能成为整个并发缓存的瓶颈 如果Redis缓存失效,会对数据库产生冲击 多级缓存 充分利用各环节,分别添加缓存,减轻Tomcat的压力 客户端缓存->NGINX本地缓存->Redis->Tomcat->DB 其中Nginx缓存是业务Nginx,通常部署为集群,再由专门的Nginx做反向代理 JVM进程缓存 Caffeine技术 缓存驱逐策略: 基于容量、基于时间、基于引用 实现效果: 第一次查询走数据库,然后就会放入缓存,之后查询就走缓存 Lua语法 轻量小巧的脚本语言 数据类型 nil、boolean、number、string、function、table、type函数 变量 声明变量 12345local var_name = var_value#数组local arr = {'java','python','c++'}#maplocal map = {name = 'Jack',age = 2} 访问数组,下标从一开始arr[1] 访问Map, 12map['name']map.name 循环遍历 1234567local arr = {'Java','lua','python'}for index,value in ipairs(arr) do print(index,value) endfor key,value in pairs(map) do prinr(key,value) end 函数 1234function fun_name(para) --- return nil end 条件控制 123456if(布尔表达式) then --- else --- end 多级缓存 配置nginx OpenResty是基于Nginx的高性能Web平台 OpenResty使用流程类似于Nginx的使用 监听路径类似于Response Lua文件类似于Service层 请求参数处理,不同参数格式有相应解析代码 nginx查询Tomcat 小规律:服务器前三位地址相同,第四位换为1 nginx提供了内部API用以发送http请求 Tomcat集群的负载均衡 保证缓存一直生效,同一路径访问同一服务器 修改负载均衡算法由轮询改为Hash算法来直接匹配 添加Redis缓存 冷启动:服务器初启动时,没有缓存,此时查询会都导向数据库,带来较大的数据库压力 缓存预热:利用大数据统计热点数据,将热点数据存到缓存 实现nginx优先查询Redis缓存: OpenResty如何操作Redis? OpenResty提供了操作Redis的模块,大概模块如下: 封装函数,从Redis读取数据并返回 引入Redis模块,并初始化Redis模块 封装函数,释放Redis连接,其实是放入连接池 Nginx本地缓存 利用shared dict开启词典 修改查询逻辑,加入缓存业务 缓存同步 三种方式 设置有效期 同步双写,在修改数据的同时直接修改缓存 异步通知,改数据库时发事件通知,相关服务进行监听到通知后修改缓存 监听mysql,使用MQ/canal实现 canal基于mysql的主从模式,canal伪装为mysql的一个slave节点完成通知
分布式缓存——Redis高级篇
分布式缓存——Redis高级篇 单节点Redis问题 数据丢失问题:实现Redis数据持久化 并发能力问题:搭建主从集群,实现读写分离 故障恢复问题:Redis哨兵,实现健康检测和自动恢复 存储能力问题:搭建分片集群,利用插槽机制实现动态扩容 一、持久化 方式之一:RDB持久化 RDB全称RedisDatabaseBackup file(Redis数据备份文件) 有两个命令可以进行RDB持久化 save命令:由主进程执行RDB,会阻塞所有命令 bgsave命令:开子进程执行RDB,避免主进程受影响 默认Redis停机时会执行一次RDB (停机≠宕机) 可以通过修改redis.conf文件来配置相关的RDB参数 1234567save 900 1 #900秒内由1次修改,就会执行bgsave。参数可以进行修改#是否压缩,建议不开启,压缩也会消耗CPU,磁盘的话相对不值钱rdbcompression yes#RDB文件名称dbfilename dump.rdb#文件保存的路径目录dir ./ bgsave流程 bgsave开始时会fork主进程得到子进程(在fork过程中主进程会被阻塞),子进程共享主进程的内存数据。fork后主进程可以正常读写,子进程会读取内存数据并写入RDB文件。 如果只是这样可能会有脏数据的问题,就是说在子进程读的时候主进程可能更改了数据。 要理解这个问题,需要理解内存结构。 如图是我参考课程使用visio绘制的fork框图,下面结合这个来解释一下fork的流程。 首先是关于linux的结构,在linux中,进程都是不能直接更改物理内存的,它在虚拟内存中,通过一个页表来维护关系,进程通过修改页表修改内存中的数据。 当使用bgsave的时候,首先会进行fork,会开启子进程,子进程复制主进程的页表,复制完后,为避免脏读的情况,会将数据A和数据B设为只读的共享内存,这样子进程在存储RDB时就不会被主进程干扰。 相应的主进程要更改数据,数据B会被拷贝为数据B的副本,主进程通过修改副本实现修改的功能。 因为内存进行了拷贝,所以极限情况下可能会占用两倍的内存,这也就是为什么使用Redis都要预留一定的内存空间。 RDB缺点: RDB间隔较长,两次RDB间由数据丢失风险 fork子进程、压缩写出RDB比较耗时 方式二:AOF持久化 AOF全程Append Only File(追加文件),可以看成命令日志文件 可以通过redis.conf配置文件开启和配置AOF 1234567#开启appendonly yesappendfilename "名字"#频率appendfsync always#每执行一次命令,立即写到AOFappendfsync everysec#写命令执行完先放入AOF缓冲区,每隔一秒将缓冲数据写到AOFappendfsync no#写命令执行完先放入AOF缓冲区,由操作系统决定什么时候将缓冲数据写到AOF AOF体积压缩 因为AOF记录的是每条命令,多条命令叠加下可能很多命令是无效的,所以体积会很大。 可以使用bgrewriteaof命令将AOF文件进行重写以减小体积 什么时候进行重写? 可以在redis.conf文件中配置 12auto-aof-rewrite-percentage 100#AOF文件增长超过多少百分比触发重写auto-aof-rewrite-min-size 64mb#AOF文件体积最小多大以上触发重写 RDB和AOF对比 各有优缺点,如果对数据安全性要求较高,在实际开发中往往会将两种方式结合起来使用 RDB AOF 持久化方式 定时对整个内存做快照 记录每一次执行的命令 数据完整性 不完整,两次备份之间会丢失 相对完整,取决于刷盘策略 文件大小 会有压缩,文件体积小 记录命令,文件体积大 宕机恢复速度 很快 慢 数据恢复优先级 低,因为数据完整性不如AOF 高,因为数据完整性高 系统资源占用 高,大量CPU和内存消耗 低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源 使用场景 可以容忍数分钟的数据丢失,追求更快的启动速度 对数据安全性要求较高 二、主从集群 搭建主从架构 开启主从关系 1replicaof/slaveof(5.0之前) host...
Spring框架
Spring Framework Java开发要用的Spring家族的基础就是SpringFramework、SpringBoot、SpringCloud。这里笔记记录的就是SpringFramework技术,学习视频是黑马的SSM快速入门Spring-01-初识Spring_哔哩哔哩_bilibili 要注意的是,本内容仅是对Spring框架应用的学习以及架构的认识,更加深入的内容要在Spring源码的部分进一步学习。 Spring系统架构 IoC(Inversion of Control)控制翻转 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象的创建控制权由程序转移到外部,这个思想就是控制翻转。 IoC、Bean和DI: Spring提供了一个容器,称为IoC容器,用来充当Ioc思想中的“外部” IoC容器负责对象的创建、初始化的一系列工作,被创建或管理的对象在IoC容器中统称为Bean DI(依赖注入)在容器中建立起bean与bean之间的关系 我们这样做的目的是充分解耦,具体做法可以概括如下: 使用IoC容器管理bean(IoC) 在IoC容器中将有依赖关系的bean进行关系绑定(DI) bean管理 bean作用范围 bean的作用范围对应着scope属性,主要就是控制其是否为单例。 为什么bean默认为单例? IoC容器就适合管理单例的对象,这样才能有效地提高效率。 适合交给容器管理的bean 表现层对象 业务层对象 数据层对象 工具对象 不适合交给容器管理的bean 封装实体的域对象、 bean的实例化 构造方法(常用) 提供可访问的构造方法 配置 无参构造器如果不存在,会抛出BeanCreationException 静态工厂(了解) 实例工厂(了解) 使用FactoryBean实例化,其中有三个方法,用来得到Bean实例、设定Bean类型、设定是否为单例(实用) bean的生命周期 bean生命周期:bean从创建到销毁的整体过程 bean生命周期控制:在bean创建后到销毁前做的一些事情 生命周期控制 配置的方式 接口控制 bean的生命周期 初始化容器 创建对象(内存分配) 执行构造方法 执行属性注入(set操作) 执行bean初始化方法 使用bean 执行业务操作 关闭/销毁容器 执行bean销毁方法 bean销毁 容器关闭前触发bean的销毁 关闭容器方式: 手动关闭容器,ConfigurableApplicationContext接口close()操作 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机,ConfigurableApplicationContext接口registerShutdownHook()操作 总结 bean相关标签属性 123456789101112<bean id="bookDao" name="dao bookDaoImpl daoImpl" class="com.itheima.dao.impl.BookDaoImpl" scope="singleton" init-method="init" destroy-method="destory" autowire="byType" factory-method="getInstance" factory-bean="com.itheima.factory.BookDaoFactory" lazy-init="true" /> id: bean的Id name: bean别名 class: bean类型,静态工厂类,FactoryBean类 scope: 控制bean的实例数量 init-method: 生命周期初始化方法 destroy-method: 生命周期销毁方法 autowire: 自动装配类型,实际开发一般用注解,该属性一般不用 factory-method: bean工厂方法,应用于静态工厂或实例工厂 factory-bean: 实例工厂bean lazy-init: 控制bean延迟加载 依赖注入 手动装配 setter注入 引用类型使用ref配置 简单类型:使用property标签value属性进行配置 12<property name="bookDao"...
SpringMVC之登录校验
SpringMVC之登录校验 登录功能的实现比较简单,只需要根据输入的用户名和密码,或者其他登录验证形式,到数据库查询是否有这条数据就可以了。 但实际上这是一个伪登录的功能。因为HTTP协议是一种无状态的协议,所以在后续的访问中无法记录登录状态。也就是登录校验功能没有实现,下边来详细讲解一下该功能的实现。 graph LR 浏览器-->|请求|拦截器 拦截器-->|响应|浏览器 拦截器-->login 拦截器-->Controller接口 login-->|存|登录标记 登录标记-->|取|拦截器 上图展示了登录验证这一业务的实现流程 实现登录标记:会话技术 实现统一拦截:过滤器(filter)、拦截器(interceptor) 下边介绍这些技术 会话技术 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应 会话跟踪:一种维护浏览器状态的方法,服务器需要多次请求是否来自于同一浏览器,以便在同一次会话的多次请求之间能够共享数据 Cookie 客户端会话跟踪技术 服务端在响应的响应头里携带Set-Cookie:name=value 之后浏览器在请求时请求头里携带Cookie:name=value 优点: HTTP协议中支持的技术,浏览器自动进行 缺点: 在移动端无法使用Cookie 不安全,用户可以自己禁用Cookie Cookie不能跨域 session 服务器会话跟踪技术,是基于Cookie实现的 缺点 服务器集群环境下无法使用session cookie的缺点:因为底层就是用cookie实现的 令牌技术 优点: 支持PC端和移动端,因为现在不需要把令牌存储在Cookie中,其他的存储空间也是可以的 解决集群环境下的认证问题 减轻服务器端的存储压力 后边在redis还会详细讲解其实现 JWT令牌:(令牌的一种形式) JSON Web Token(https://jwt.io) 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全传输信息。由于数字签名的存在,这些信息是可靠的。 JWT令牌的组成: 第一部分:Header(头),记录令牌类型、签名算法等。 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 第三部分:Signature(数字签名),防止Token被篡改,确保安全性。融入header、payload,并加入指定秘钥,通过指定签名算法计算而来。 介绍一下Base64编码:是一种基于64个可打印字符(A-Z a-z 0-9 + /)来表示二进制数据的编码方式。 JWT校验: JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的 如果JWT令牌解析时报错,则说明JWT令牌被篡改或失效了,令牌非法 JWT校验需要使用统一拦截的技术,下面将会讲解统一拦截的实现方式 统一拦截 过滤器 过滤器(Filter)是JavaWeb三大组件(Filter、Servlet、Listener)之一。 过滤器可以把对资源的请求拦截下来,从而实现一些特殊功能 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等 Filter快速入门:(并不重要) 定义:实现Filter接口 配置: 在实现类上加上@WebFilter(urlPatterns=“/*”)表示拦截路径 Filter并不是SpringBoot的组件,所以需要在启动类上加上@ServletComponentScan 过滤器的执行流程 graph LR 浏览器-->|请求|Filter subgraph...
Redis
Redis基础部分 介绍 Redis诞生于2009年,全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。 特征: 键值(key-value)型,value支持多种不同数据结构,功能丰富 单线程,每个命令具备原子性 低延迟,速度快(基于内存、IO多路复用、良好的编码) 支持数据持久化 支持主从集群、分片集群 支持多语言客户端 redis安装 关于redis,这里推荐装linux版的。 所以建议先学习安装linux和它的常用vi命令。这里做几点建议: win10及以上可以直接使用自带的wsl2来安装linux子系统,具体教程b站上有。我使用的是Ubuntu,并且没有什么问题 redis的安装和测试可以参考这个教程如何在 Ubuntu 20.04 上安装和配置 Redis-阿里云开发者社区 redis常用的命令 命令不用死记,建议去redis官网查询命令 又或者,你也可以在命令行中使用help [command]来查询,例如: 下边总结常用的命令 KEYS:查看符合模版的所有key,不建议在生产环境设备上使用,因为效率过低 DEL:删除一个指定的key EXISTS:判断key是否存在 EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除 TTL:查看一个key的剩余有效期 String类型 String类型,也就是字符串类型,是Redis中最简单的存储类型 其value是字符串,不过根据字符串的格式不同,又可以分为3类:string、int、float String的常见命令 SET:添加或者修改已经存在的一个String类型的键值对 GET:根据key获取String类型的value MSET:批量添加多个String类型的value MGET:根据多个key获取多个String类型的value INCR:让一个整型的key自增1 INCRBY:让一个整型的key自增并指定步长 INCRYBYFLOAT:让一个浮点类型的数字自增并指定步长 SETNX:添加一个String类型的键值对,前提是这个key不存在,否则不执行 SETEX:添加一个String类型的键值对,并指定有效值 Key的层级格式: Redis的key允许有多个单词形成层级结构,多个单词之间用‘:’隔开,这样就会形成层级结构。 Hash类型 Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。 Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD: Hash的常见命令: HSET key field value:添加或修改hash类型key的field的值 HGET key field:获取一个hash类型key的field值 HMSET:批量添加多个hash类型key的field值 HMGET:获取获取多个hash类型key的field值 HGETALL:获取一个hash类型的key中的所有的field和value HKEYS:获取一个hash类型的key中的所有field HVALS:获取一个hash类型的key中的所有value HINCRBY:让一个hash类型key的字段值自增并指定步长 HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行 List类型 Redis中的List类型与Java中的LinkedList基本一致 List的常见命令: LPUSH key element…:想列表左侧插入一个或多个元素 LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil RPUSH key element…:向列表右侧插入一个或多个元素 RPOP key:移除并返回列表右侧的第一个元素 LRANGE key start end:返回一段角标范围内的所有元素 BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil 如何利用List结构模拟一个栈? 入口和出口在同一边 如何利用List结构模拟一个队列? 入口和出口在不同边 如何利用List结构模拟一个阻塞队列? 入口和出口在不同边 出队时采用BLPOP或BRPOP Set类型 Redis的Set结构和Java中的HashSet类似,可以看做是一个value为null的HashMap。 Set的常见指令: SADD key member …:向Set中添加一个或多个元素 SREM key member …:移除set中的指定元素 SCARD key:返回set中元素的个数 SISMEMBER key...
Mybatis入门
修改历史: 2025-06-28 修改了部分错误,优化了文档结构 2025-07-01 修复了代码块sql语句无法高亮的问题 Mybatis入门 0.序 Mybatis是持久层(也就是三层架构中的Dao层)的一款框架,简化了JDBC的开发。内容来自视频->Day08-14. Mybatis-入门-快速入门程序_哔哩哔哩_bilibili。 1.入门 快速入门 开启一个模版程序,实现使用Mybatis查询所有用户数据 准备工作(创建springboot文件,定义实际类User,数据库表user) 添加mybatis相关依赖,配置mybatis(数据库连接信息) 编写SQL语句(注解/XML) 具体操作流程如下: 创建springboot文件:与springboot入门中的创建方法基本一致,注意要勾选Mybatis Framework和MySQL Driver依赖。 定义实际类:实际类要与数据库中user的字段保证一致,常见的几种类型对应:int->Integer,varchar->String,tinyint->Short,主要使用其包装类。同时声明相应的getset方法、构造器、toString方法。 在properties配置文件中加入以下内容,格式比较固定,url要根据相应的数据库名称确定,密码设定为自己的密码 1234spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mybatisspring.datasource.username=rootspring.datasource.password=1234 编写SQL语句(注解/XML) 123456@Mapper//在运行时,MyBatis会扫描这个接口,并为其生成一个实现类对象(代理对象),并交给IOC管理public interface UserMapper { //查询 @Select("select * from user") public List<User> list();} 单元测试 123456789101112@SpringBootTest//springboot整合单元测试的注解class SpringbootMybatisQuickstartApplicationTests { @Autowired private UserMapper userMapper; @Test public void testListUser() { List<User> userList = userMapper.list(); for (User user : userList) { System.out.println(user); } }} 创建完成后的文件结构如图 配置SQL提示 在上边的SQL语句中,如果没有配置,那么就不会显示相应的提示,即使写错了也不会提醒,这对于开发是非常不利的。好在Idea中可以为其配置MySQL数据库连接。 选中SQL语句,右键,配置为MySQL语句 点击右侧边栏的数据库选项,点击加号,数据源选择MySQL,填写host、port、用户和密码、数据库 数据库连接池 数据库连接池是个容器,负责分配、管理数据库连接 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个 能够释放空闲时间超过最大空闲时间的连接,避免因为没有释放连接引起的数据库连接遗漏 好处:资源重用 提升系统响应速度...
SpringBoot入门
修改历史: 增加了Web入门的基础知识,完善了结构 SpringBoot入门 0.概述 本篇只是对springboot的基本使用的总结,学习视频->Day05-01. 请求响应-概述_哔哩哔哩_bilibili,使用postman进行调试。 1.Web入门 HTTP协议 概述 HTTP协议(HyperTextTransferProtocol),超文本传输协议,规定了浏览器和服务器之间数据传输的规则。 特点: TCP协议:面向连接,安全 基于请求-响应模型:一次请求对应一次响应 HTTP是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的 缺点:多次请求无法共享数据 优点:速度快 请求协议 请求数据包括三个部分: 请求行:请求数据第一行(请求方式,资源路径、协议) 请求头:第二行开始,格式key: value 请求体:POST请求,存放请求参数 两种请求方式对比: 请求方式-get:请求参数在请求行中,没有请求体。get请求大小是有限制的。 请求方式-post:请求参数在请求体中,post请求大小是没有限制的。 响应协议 响应数据包括三部分: 响应行:相应数据第一行(协议、状态码、描述) 响应头:key: value 响应体:存放响应数据 常见状态码: 状态码 描述 1xx 响应中 2xx 成功 3xx 重定向-重定向到其他地方;让客户端再发起一次请求以完成整个处理 4xx 客户端错误-处理发生错误,责任在客户端。如请求了不存在的资源、客户端未被授权、禁止访问 5xx 服务器错误-处理发生错误,责任在服务端。如程序抛出异常 目前主要了解:200 处理成功,404 请求资源不存在,500 服务器端异常 更多状态码见网站: 状态 | Status - HTTP 中文开发手册 - 开发者手册 - 腾讯云开发者社区-腾讯云 协议解析 服务器端要做的事情,一方面是要根据请求协议,解析浏览器发送的请求;另一方面是要根据响应协议,发送响应数据。 这种解析的工作较为固定,有不少Web服务器已经完成了这些工作,这样后端就只用关注业务逻辑的实现。常见的Web服务器有:Tomcat、IBM、jetty、WebLogic等 Tomcat服务器 具体内容暂时不用详细了解,SpringBoot已经内嵌了Tomcat服务器,所以不用专门下载。介绍在此省略 2.请求 此处请求的含义:后端接收来自浏览器端的请求指令,进行解析 简单参数 请求: GET指令:http://localhost:8080/simpleParam?name=miku&age=16 POST指令:http://localhost:8080/simpleParam请求体:name=Miku&age=16 Java代码: 原始方式: 12345678910//在原始的Web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取@RequestMapping("/simpleParam")public String simpleRequest(HttpServletRequest request) { String name = request.getParameter("name");//需要与请求参数的key保持一致 String ageStr = request.getParameter("age");//需要与请求参数的key保持一致 int age = Integer.parseInt(ageStr); System.out.println("Name: " + name + ", Age: " + age); return "OK";}//繁琐,并且需要进行手动类型转换 SpringBoot方式: 简单参数,参数名与形参列表名相同,定义形参即可接收参数 12345@RequestMapping("/simpleParam")public String simpleRequest(int age,String name) { System.out.println(name + ":" + age); return...
Maven
Maven 概述 Maven是一款管理和构建Java项目的工具。基于POM(项目对象模型)的概念,通过一小段描述来管理项目 Maven坐标,唯一标识和定位一个项目 groupId:组织 artifactId:模块名称 version:版本 仓库:用于存储资源,管理jar包 本地仓库:自己计算机上的一个目录 中央仓库:由Maven团队维护的全球唯一的仓库 远程仓库:一般由公司团队搭建的私有仓库 使用顺序:本地仓库>远程仓库>中央仓库 依赖管理 依赖:指当前项目运行所需的jar包 配置依赖(在IDEA中) 在pom.xml中编写标签 在标签中使用引入坐标 定义坐标的groupId,artifactId,version 点击刷新按钮,引入最新加入的坐标 12345678<dependencyies> <dependency> <groupId></groupId> <artifactId></artifactId> <version></version> </dependency> ...</dependencyies> 依赖传递 依赖具有传递性 直接依赖:在当前项目中通过依赖配置建立的关系 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源 排除依赖:主动断开依赖的资源,被排除的资源无需指定版本 123456<exclusions> <exclusion> <groupId></groupId> <artifactId></artifactId> </exclusion></exclusions> 依赖范围 scope值 主程序 测试程序 打包(运行) 范例 compile(默认) Y Y Y log4j test - Y - junit provided Y Y - servlet-api runtime - Y Y jdbc驱动 可以通过下面的xml标签来设置依赖范围 1<scope>...</scope> 生命周期 每套生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。(运行后面的阶段,前面的阶段也会运行) 生命周期阶段(常见) 常见生命周期阶段 clean 移除上一次构建生成的文件 compile 编译项目源代码 test 使用合适的单元测试框架运行测试 package 将编译后的文件打包,如:jar、war等 install 安装项目到本地仓库
