2024 Summary
Good 升职加薪 换新项目,与 grab insurance 的工程师合作,提升了英语听力和口语 重构老项目的同时更加了解业务和工程化(构建优化、单测、CI/CD等) 得益于 AI 助手(cody)支持分析代码行,提升了开发效率 了解 go 博客 academic 主题不好升级,貌似有 breaking change,直接换了个新主题 PaperMode,顺带升级了 hugo 掌握蛙泳抱水 Bad 软考内容只看了两章 New targets 拿到软考证书 现有项目中引入 nx 继续了解 go
React Learning
使用 react 时阅读文档的笔记 核心概念 高级指引 API REFERENCE react 顶层 API 概览 组件 React.Component 转换元素 cloneElement
Nacos
Nacos 持久化:conf/application.properties 的 ### Count of DB: 处配置数据库信息 本地单机(非集群)运行:bin/startup.cmd 中配置 set MODE="standalone" 不配置会报错: Caused by: com.alibaba.nacos.api.exception.NacosException: java.net.UnknownHostException: jmenv.tbsite.net auth和system启动报错 https://gitee.com/y_project/RuoYi-Cloud/issues/I1O1NJ *************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular profile you may need to activate it (the profiles local are currently active). Disconnected from the target VM, address: '127.0.0.1:5979', transport: 'socket' Process finished with exit code 1 REF nacos RuoYi-Cloud
RegExp
JS 正则表达式 纵向: exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。 test() 方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配。返回 true 或 false。 match() 方法检索返回一个字符串匹配正则表达式的结果。 横向: 全局匹配时, match() 方法返回所有匹配内容,而 exec() 返回单次匹配内容。 let s='abhab' let reg=/ab/g //此处有标识 g let res1=reg.exec(s) //["ab", index: 0, input: "abhab", groups: undefined] let res2=reg.exec(s) //["ab", index: 3, input: "abhab", groups: undefined] let res3=reg.exec(s) //null console.log(res1,res2) let res3=s.match(reg) //["ab", "ab"] let res4=s.match(reg) //["ab", "ab"] console.log(res3,res4) Ref: 正则表达式 - JavaScript | MDN RegExp - JavaScript | MDN RegExp.prototype.exec() - JavaScript | MDN String.prototype.match() - JavaScript | MDN 探究js正则匹配方法:match和exec
MQ
Kafka RabbitMQ
Boxing and Unboxing
装箱与拆箱 装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的(xxx代表对应的基本数据类型)。 Integer f1 = 1, f2 = 1, f3 = 200, f4 = 200; // 对于引用类型的变量之间的比较是引用,而非变量的值 System.out.println(f1 == f2);//true System.out.println(f3 == f4);//false 包装类Integer“==”运算在遇到算术运算的时会自动拆箱 Integer内部有一个缓存内部类IntegerCache,缓存范围(-128~127),当被赋的值在该范围内时,就直接从缓存池中去。 Ref 深入剖析Java中的装箱和拆箱 面试官:兄弟,说说基本类型和包装类型的区别吧
Why Must the Pojo Attribute Type Be Wrappers
为什么 POJO 的属性必须要用包装类型呢? 数据库的查询结果可能是 null,如果使用基本类型的话,因为要自动拆箱(将包装类型转为基本类型,比如说把 Integer 对象转换成 int 值),就会抛出 NullPointerException 的异常。
Tcp
TCP三次握手和四次挥手以及11种状态 1、三次握手 置位概念:根据TCP的包头字段,存在3个重要的标识ACK、SYN、FIN ACK:表示验证字段 SYN:位数置1,表示建立TCP连接 FIN:位数置1,表示断开TCP连接 三次握手过程说明: 1、由客户端发送建立TCP连接的请求报文,其中报文中包含seq序列号,是由发送端随机生成的,并且将报文中的SYN字段置为1,表示需要建立TCP连接。(SYN=1,seq=x,x为随机生成数值) 2、由服务端回复客户端发送的TCP连接请求报文,其中包含seq序列号,是由回复端随机生成的,并且将SYN置为1,而且会产生ACK字段,ACK字段数值是在客户端发送过来的序列号seq的基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP建立请求已得到验证。(SYN=1,ACK=x+1,seq=y,y为随机生成数值)这里的ack加1可以理解为是确认和谁建立连接。 3、客户端收到服务端发送的TCP建立验证请求后,会使自己的序列号加1表示,并且再次回复ACK验证请求,在服务端发过来的seq上加1进行回复。(SYN=1,ACK=y+1,seq=x+1) 2、四次握手 四次握手过程说明: 1、客户端发送断开TCP连接请求的报文,其中报文中包含seq序列号,是由发送端随机生成的,并且还将报文中的FIN字段置为1,表示需要断开TCP连接。(FIN=1,seq=x,x由客户端随机生成) 2、服务端会回复客户端发送的TCP断开请求报文,其包含seq序列号,是由回复端随机生成的,而且会产生ACK字段,ACK字段数值是在客户端发过来的seq序列号基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP断开请求已经得到验证。(FIN=1,ACK=x+1,seq=y,y由服务端随机生成) 3、服务端在回复完客户端的TCP断开请求后,不会马上进行TCP连接的断开,服务端会先确保断开前,所有传输到A的数据是否已经传输完毕,一旦确认传输数据完毕,就会将回复报文的FIN字段置1,并且产生随机seq序列号。(FIN=1,ACK=x+1,seq=z,z由服务端随机生成) 4、客户端收到服务端的TCP断开请求后,会回复服务端的断开请求,包含随机生成的seq字段和ACK字段,ACK字段会在服务端的TCP断开请求的seq基础上加1,从而完成服务端请求的验证回复。(FIN=1,ACK=z+1,seq=h,h为客户端随机生成) 至此TCP断开的4次挥手过程完毕。 3、流程及11种状态 三次握手流程 1、一开始,建立连接之前服务器和客户端的状态都为CLOSED; 2、服务器创建socket后开始监听,变为LISTEN状态; 3、客户端请求建立连接,向服务器发送SYN报文,客户端的状态变味SYN_SENT; 4、服务器收到客户端的报文后向客户端发送ACK和SYN报文,此时服务器的状态变为SYN_RCVD; 5、然后,客户端收到ACK、SYN,就向服务器发送ACK,客户端状态变为ESTABLISHED; 6、服务器端收到客户端的ACK后变为ESTABLISHED。此时3次握手完成,连接建立! 四次握手流程 由于TCP连接是全双工的,断开连接会比建立连接麻烦一点点。 1、客户端先向服务器发送FIN报文,请求断开连接,其状态变为FIN_WAIT1; 2、服务器收到FIN后向客户端发送ACK,服务器的状态围边CLOSE_WAIT; 3、客户端收到ACK后就进入FIN_WAIT2状态,此时连接已经断开了一半了。如果服务器还有数据要发送给客户端,就会继续发送; 4、直到发完数据,就会发送FIN报文,此时服务器进入LAST_ACK状态; 5、客户端收到服务器的FIN后,马上发送ACK给服务器,此时客户端进入TIME_WAIT状态; 6、再过了2MSL长的时间后进入CLOSED状态。服务器收到客户端的ACK就进入CLOSED状态。 至此,还有一个状态没有出来:CLOSING状态。 CLOSING状态表示:客户端发送了FIN,但是没有收到服务器的ACK,却收到了服务器的FIN,这种情况发生在服务器发送的ACK丢包的时候,因为网络传输有时会有意外。 11种状态 LISTEN:等待从任何远端TCP 和端口的连接请求。 SYN_SENT:发送完一个连接请求后等待一个匹配的连接请求。 SYN_RECEIVED:发送连接请求并且接收到匹配的连接请求以后等待连接请求确认。 ESTABLISHED:表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传输阶段的正常状态。 FIN_WAIT_1:等待远端TCP 的连接终止请求,或者等待之前发送的连接终止请求的确认。 FIN_WAIT_2:等待远端TCP 的连接终止请求。 CLOSE_WAIT:等待本地用户的连接终止请求。 CLOSING:等待远端TCP 的连接终止请求确认。 LAST_ACK:等待先前发送给远端TCP 的连接终止请求的确认(包括它字节的连接终止请求的确认) TIME_WAIT:等待足够的时间过去以确保远端TCP 接收到它的连接终止请求的确认。 TIME_WAIT 两个存在的理由:可靠的实现tcp全双工连接的终止;允许老的重复分节在网络中消逝。 CLOSED:不在连接状态(这是为方便描述假想的状态,实际不存在) Ref TCP三次握手和四次挥手以及11种状态 《码出高效》1.5节TCP/IP
Cross Origin
Vuex 踩坑记之 Unknown Mutation Type
Q: Unknown Mutation Type 近日,我在 vuex 3.1.3 的 mutations 中封装 antd 提供的 notification 时,遇到了 unknown mutation type: SHOW_NOTIFICATION // vuex下的common模块common.js部分代码 ... namespaced: true, // 可圈可点 // notice: { type: 'error', msg: '-1' } state: { userId: '', role: Number, token: '', code: 'cslg', noticeType: 'error' }, mutations: { SHOW_NOTIFICATION(state, msg) { // 通过设置key唯一notification // const key = 'unique' console.log('SHOW_NOTIFICATION') alert(state.noticeType + msg) notification[state.noticeType]({ // key, message: msg, }); }, OK(state, msg) { state.noticeType = 'success' console.log(state===this) // false,原因不详( this.commit('SHOW_NOTIFICATION', msg) }, ... }, actions: {...} ... A1(不推荐) 前情提要:各路大佬表示不建议在 mutation 中 commit。 野路子:由于设置了 namespaced 为 true,所以在 mutation 中 commit 时需要加上 moduleName。 ...