diff --git a/README.md b/README.md index 3da4210ce338f9e85454ff0011b52c405399cb1d..aae5cd4a7c4bb4586180fdb1ea945c8192f867cf 100644 --- a/README.md +++ b/README.md @@ -47,3 +47,5 @@ npm run dev ``` ![](https://api.isoyu.com/bing_images.php) + +![](img/python-select-qrcode.jpeg ':size=40%') \ No newline at end of file diff --git a/_navbar.md b/_navbar.md new file mode 100644 index 0000000000000000000000000000000000000000..3352acee7c61990b2cb5f3460ed317e9edd031e1 --- /dev/null +++ b/_navbar.md @@ -0,0 +1,22 @@ +* [程序员导航](https://mouday.github.io/hao123/) + +* [学习笔记](https://mouday.github.io/LearningNote/) + +* [在线Demo](https://mouday.github.io/front-end-demo/) + +* [个人网站](https://www.pengshiyu.com/) + +* 博客站点 + * [GitHub](https://github.com/mouday) + + * [CSDN](https://pengshiyu.blog.csdn.net/) + + * [51CTO](https://blog.51cto.com/u_13567403) + + * [稀土掘金](https://juejin.cn/user/3104676568106567) + + * [知乎](https://www.zhihu.com/people/pengshiyu) + + * [华为云](https://bbs.huaweicloud.com/community/usersnew/id_1628242835316833) + + * [阿里云](https://developer.aliyun.com/group/pengshiyu) \ No newline at end of file diff --git a/_sidebar.md b/_sidebar.md index a4688c213a534e1710a1995648ae511faeaca0d8..80d6fa2741e9e337d6dc1a6577588ebd363155e4 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -9,6 +9,7 @@ - [Canvas](doc/canvas.md) - [微信小程序](doc/miniprogram.md) - [Vue.js](doc/vue.md) + - [websocket](blog/websocket/index.md) - 后端 diff --git a/blog/mysq-advance/index.md b/blog/mysq-advance/index.md new file mode 100644 index 0000000000000000000000000000000000000000..c975a3b1b5c7d9cbd9d51781364359e19b38f0dc --- /dev/null +++ b/blog/mysq-advance/index.md @@ -0,0 +1,4 @@ + +MySQL进阶 + +https://www.bilibili.com/video/BV1Kr4y1i7ru?p=58 \ No newline at end of file diff --git a/blog/php-basic/index.md b/blog/php-basic/index.md index 607ec40725a292617c801a1f4b921cdb0b488645..390745db5256183881d08ea4244c56ad118ea47d 100644 --- a/blog/php-basic/index.md +++ b/blog/php-basic/index.md @@ -1,4 +1,4 @@ -# 笔记:黑马程序员 PHP 零基础入门到精通教程(P1 基础 6 天) +笔记:黑马程序员 PHP 零基础入门到精通教程(P1 基础 6 天) 视频地址:[https://www.bilibili.com/video/BV18x411H7qD](https://www.bilibili.com/video/BV18x411H7qD) @@ -12,9 +12,9 @@ 5. [PHP 运算符 operator](blog/php-basic/operator.md) -[PHP 流程控制](blog/php-basic/process.md) +6. [PHP 流程控制](blog/php-basic/process.md) -[PHP 常用的系统函数](blog/php-basic/system.md) +7. [PHP 常用的系统函数](blog/php-basic/system.md) [PHP 文件包含](blog/php-basic/include.md) diff --git a/blog/php-mysql/index.md b/blog/php-mysql/index.md index d3de127fa074f125b5f2e9423762a63135c74ff3..33afff8ff81d556aaf9655022cf5fd85cb88f030 100644 --- a/blog/php-mysql/index.md +++ b/blog/php-mysql/index.md @@ -63,3 +63,5 @@ [函数 function](blog/php-mysql/sql-function.md) [存储过程 procedure](blog/php-mysql/sql-procedure.md) + +[触发器 trigger](blog/php-mysql/sql-trigger.md) diff --git a/blog/php-mysql/sql-procedure.md b/blog/php-mysql/sql-procedure.md index b6fd33072e7cdfcdfa7e1d555a08b684cdef211b..28081fed37b96871ffa91353887aae5d4dc57c3d 100644 --- a/blog/php-mysql/sql-procedure.md +++ b/blog/php-mysql/sql-procedure.md @@ -206,6 +206,3 @@ mysql> select @var1, @var2, @var3; 1、实参传入过程之后,实际上没有改变外部变量的值,而是把值给了形参,out类型不能接收外部变量的值,默认为null 2、当过程执行到end 的时候,如果是out或inout变量,会将形参的值重新赋值给实参变量 - - -https://www.bilibili.com/video/BV1Vx411g7uJ?p=75&spm_id_from=pageDriver \ No newline at end of file diff --git a/blog/php-mysql/sql-trigger.md b/blog/php-mysql/sql-trigger.md new file mode 100644 index 0000000000000000000000000000000000000000..5b93b8498f79ac5ae511beb0849eb4caa1ae6a5c --- /dev/null +++ b/blog/php-mysql/sql-trigger.md @@ -0,0 +1,336 @@ +# 触发器 + +## 一、基本概念 + +触发器是一种特殊类型的存储过程,触发器通过事件进行触发而被执行 + +触发器 trigger 和js事件类似 + +1、作用: + +1. 写入数据表前,强制检验或转换数据(保证数据安全) +2. 触发器发生错误时,异动的结果会被撤销(事务安全) +3. 部分数据库管理系统可以针对数据定义语言DDL使用触发器,称为DDL触发器 +4. 可以依照特定的情况,替换异动的指令 instead of(mysql不支持) + +2、触发器的优缺点 + +2.1、优点 + +1. 触发器可通过数据库中的相关表实现级联更改(如果一张表的数据改变,可以利用触发器实现对其他表的操作,用户不知道) +2. 保证数据安全,进行安全校验 + +2.2、缺点 + +1. 对触发器过分依赖,势必影响数据库的结构,同时增加了维护的复杂度 +2. 造成数据在程序层面不可控 + +## 二、创建触发器 + +1、基本语法 + +```sql +create trigger 触发器名字 触发时机 触发事件 on 表 for each row +begin + +end +``` + +2、触发对象 + +`on 表 for each row` 触发器绑定表中所有行,没一行发生指定改变的时候,就会触发触发器 + + +3、触发时机 + +每张表对应的行都有不同的状态,当SQL指令发生的时候,都会令行中数据发生改变,每一行总会有两种状态:数据操作前和数据操作后 + +- before: 数据发生改变前的状态 +- after: 数据已经发生改变后的状态 + +4、触发事件 + +mysql中触发器针对的目标是数据发生改变,对应的操作只有写操作(增删改) + +- inert 插入操作 +- update 更新操作 +- delete 删除操作 + +5、注意事项 + +一张表中,每一个触发时机绑定的触发事件对应的触发器类型只能有一个 + +一张表表中只能有一个对应的after insert 触发器 + +最多只能有6个触发器 + +```sql +before insert +after insert + +before update +after update + +before delete +after delete +``` + +### 1.1 需求 + +下单减库存 + +有两张表,一张是商品表,一张是订单表(保留商品ID)每次订单生成,商品表中对应的库存就应该发生变化 + +1、创建两张表 + +```sql +create table my_item( + id int primary key auto_increment, + name varchar(20) not null, + count int not null default 0 +) comment '商品表'; + +create table my_order( + id int primary key auto_increment, + item_id int not null, + count int not null default 1 +) comment '订单表'; + +insert my_item (name, count) values ('手机', 100),('电脑', 100), ('包包', 100); + +mysql> select * from my_item; ++----+--------+-------+ +| id | name | count | ++----+--------+-------+ +| 1 | 手机 | 100 | +| 2 | 电脑 | 100 | +| 3 | 包包 | 100 | ++----+--------+-------+ +3 rows in set (0.00 sec) + +mysql> select * from my_order; +Empty set (0.02 sec) +``` + +2、创建触发器 + + +如果订单表发生数据插入,对应的商品就应该减少库存 + +```sql +delimiter $$ + +create trigger after_insert_order_trigger after insert on my_order for each row +begin + -- 更新商品库存 + update my_item set count = count - 1 where id = 1; +end +$$ +delimiter ; +``` + +## 三、查看触发器 + +```sql + +-- 查看所有触发器 +show triggers\G +*************************** 1. row *************************** + Trigger: after_insert_order_trigger + Event: INSERT + Table: my_order + Statement: begin + + update my_item set count = count - 1 where id = 1; +end + Timing: AFTER + Created: 2022-04-16 10:00:19.09 + sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION + Definer: root@localhost +character_set_client: utf8mb4 +collation_connection: utf8mb4_general_ci + Database Collation: utf8mb4_general_ci +1 row in set (0.00 sec) + + +-- 查看创建语句 +show crate trigger 触发器名字; + +-- eg: +show create trigger after_insert_order_trigger; +``` + +## 四、触发触发器 + +让触发器执行,让触发器指定的表中,对应的时机发生对应的操作 + + +```sql +insert into my_order (item_id, count) values(1, 1); + +mysql> select * from my_order; ++----+---------+-------+ +| id | item_id | count | ++----+---------+-------+ +| 1 | 1 | 1 | ++----+---------+-------+ +1 row in set (0.00 sec) + +mysql> select * from my_item; ++----+--------+-------+ +| id | name | count | ++----+--------+-------+ +| 1 | 手机 | 99 | +| 2 | 电脑 | 100 | +| 3 | 包包 | 100 | ++----+--------+-------+ +3 rows in set (0.00 sec) +``` + +## 五、删除触发器 + +```sql +drop trigger 触发器名字; + +-- eg +drop trigger after_insert_order_trigger; +``` + +## 六、触发器的应用 + +记录关键字 new old + + +### 6.1 完善 + +商品自动扣除库存 + +触发器针对的是数据表中的每条记录,每行数据再操作前后都有一个对应的状态 + +触发器在执行之前就将对应的数据状态获取到了: +- 将没有操作之前的数据状态都保存到`old`关键字中 +- 操作后的状态都放在`new`中 + +触发器中,可以通过old和new来获取绑定表中对应的记录数据 + +基本语法 + +```sql +关键字.字段名 +``` + +old和new并不是所有触发器都有 + +- insert 插入前为空,没有old +- delete 清除数据,没有new + + +商品自动扣减库存 + +```sql +delimiter $$ +create trigger after_insert_order_trigger after insert on my_order for each row +begin + -- 通过new关键字获取新数据的id 和数量 + update my_item set count = count - new.count where id = new.item_id; +end +$$ +delimiter ; +``` + +触发触发器 + +```sql +mysql> select * from my_order; ++----+---------+-------+ +| id | item_id | count | ++----+---------+-------+ +| 1 | 1 | 1 | ++----+---------+-------+ + +mysql> select * from my_item; ++----+--------+-------+ +| id | name | count | ++----+--------+-------+ +| 1 | 手机 | 99 | +| 2 | 电脑 | 100 | +| 3 | 包包 | 100 | ++----+--------+-------+ + +insert into my_order (item_id, count) values(2, 3); + + +mysql> select * from my_order; ++----+---------+-------+ +| id | item_id | count | ++----+---------+-------+ +| 1 | 1 | 1 | +| 2 | 2 | 3 | ++----+---------+-------+ + +mysql> select * from my_item; ++----+--------+-------+ +| id | name | count | ++----+--------+-------+ +| 1 | 手机 | 99 | +| 2 | 电脑 | 97 | +| 3 | 包包 | 100 | ++----+--------+-------+ +``` + +### 6.2 优化 + +如果库存数量没有商品订单多怎么办? + +```sql +-- 删除原有触发器 +drop trigger after_insert_order_trigger; + + +-- 新增判断库存触发器 +delimiter $$ +create trigger after_insert_order_trigger after insert on my_order for each row +begin + -- 查询库存 + select count from my_item where id = new.item_id into @count; + + -- 判断 + if new.count > @count then + -- 中断操作,暴力抛出异常 + insert into xxx values ('xxx'); + + end if; + + -- 通过new关键字获取新数据的id 和数量 + update my_item set count = count - new.count where id = new.item_id; +end +$$ +delimiter ; +``` + +结果验证 + +```sql +mysql> insert into my_order (item_id, count) values(3, 101); +ERROR 1146 (42S02): Table 'mydatabase2.xxx' doesn't exist + +mysql> select * from my_order; ++----+---------+-------+ +| id | item_id | count | ++----+---------+-------+ +| 1 | 1 | 1 | +| 2 | 2 | 3 | ++----+---------+-------+ +2 rows in set (0.00 sec) + +mysql> select * from my_item; ++----+--------+-------+ +| id | name | count | ++----+--------+-------+ +| 1 | 手机 | 99 | +| 2 | 电脑 | 97 | +| 3 | 包包 | 100 | ++----+--------+-------+ +3 rows in set (0.00 sec) +``` + diff --git a/blog/websocket/demo-chat-update.md b/blog/websocket/demo-chat-update.md new file mode 100644 index 0000000000000000000000000000000000000000..e54110d25b7e41dbfac142d2c785ff852bc59d2c --- /dev/null +++ b/blog/websocket/demo-chat-update.md @@ -0,0 +1,168 @@ +# 示例3 聊天室升级版 + +## 客户端 + +```html + + + + + + + + + WebSocket Demo + + + + + +
+ + + + + +``` + +## 服务端 + +```js +// server.js +const ws = require('nodejs-websocket'); +var dayjs = require("dayjs"); + +// 消息类型枚举 +const message_type = { + OPEN: 'open', + CLOSE: 'close', + MESSAGE: 'message', +}; + +// 端口号 +const PORT = 8080; + +// 所有用户数 +var count = 0; + +function getTime(){ + return dayjs().format('HH:mm'); +} + +// 监听事件 +var server = ws.createServer(function (conn) { + console.log('New connection'); + count++; + conn.user_name = '用户' + count; + + broadcast({ + type: message_type.OPEN, + message: conn.user_name + '加入了聊天室', + time: getTime(), + }); + + // 接收客户端发送的数据 + conn.on('text', function (data) { + console.log('Received ' + data); + // conn.sendText(data) + broadcast({ + type: message_type.MESSAGE, + message: conn.user_name + ':' + data, + time: getTime(), + }); + }); + + // 客户端断开 + conn.on('close', function (code, reason) { + console.log('Connection closed'); + let message = conn.user_name + '离开了聊天室'; + broadcast({ + type: message_type.CLOSE, + message: message, + time: getTime(), + }); + }); + + // 客户端异常 + conn.on('error', function (err) { + console.log('异常'); + }); +}); + +// 广播给所有用户 +function broadcast(data) { + server.connections.forEach(function (conn) { + conn.sendText(JSON.stringify(data)); + }); +} + +// 启动服务 +server.listen(PORT, () => { + console.log(`Server started on port ${PORT}`); +}); + +``` \ No newline at end of file diff --git a/blog/websocket/demo-chat.md b/blog/websocket/demo-chat.md new file mode 100644 index 0000000000000000000000000000000000000000..2b37b5a2031fbf5a38e74fd5dac65c8597048651 --- /dev/null +++ b/blog/websocket/demo-chat.md @@ -0,0 +1,106 @@ +# 示例2 聊天室 + +## 客户端 + +```html + + + + + + + + + WebSocket Demo + + + + + +
+ + + + + +``` + +## 服务端 + +```js +// server.js +const ws = require("nodejs-websocket") + +// 端口号 +const PORT = 8080; + +// 所有用户数 +var count = 0; + +// 监听事件 +var server = ws.createServer(function (conn) { + console.log("New connection") + count++; + conn.user_name = "用户" + count; + + broadcast(conn.user_name + "加入了聊天室"); + + // 接收客户端发送的数据 + conn.on("text", function (data) { + console.log("Received "+data) + // conn.sendText(data) + broadcast(conn.user_name + ":" + data) + }) + + // 客户端断开 + conn.on("close", function (code, reason) { + console.log("Connection closed") + broadcast(conn.user_name + "离开了聊天室") + }) + + // 客户端异常 + conn.on("error", function (err) { + console.log('异常') + }) +}) + +// 广播给所有用户 +function broadcast(msg){ + server.connections.forEach(function (conn) { + conn.sendText(msg) + }) +} + +// 启动服务 +server.listen(PORT, () => { + console.log(`Server started on port ${PORT}`) +}) +``` + diff --git a/blog/websocket/demo-echo.md b/blog/websocket/demo-echo.md new file mode 100644 index 0000000000000000000000000000000000000000..24492372842cd10ae6ff2bb4ae0848a082feecb1 --- /dev/null +++ b/blog/websocket/demo-echo.md @@ -0,0 +1,95 @@ +# 示例1 Echo + +## 客户端代码 + +```html + + + + + + + + + WebSocket Demo + + + + + +
+ + + + + +``` + +## 服务端代码 + +使用到的库 + +nodejs-websocket + + - npm: https://www.npmjs.com/package/nodejs-websocket + - github: https://github.com/sitegui/nodejs-websocket + +```bash +cnpm i nodejs-websocket -S +``` + +```js +// server.js +var ws = require("nodejs-websocket") + +const PORT = 8080; + +// 监听事件 +var server = ws.createServer(function (connection) { + console.log("New connection") + + // 接收客户端发送的数据 + connection.on("text", function (data) { + console.log("Received "+data) + connection.sendText(data) + }) + + // 客户端断开 + connection.on("close", function (code, reason) { + console.log("Connection closed") + }) + + // 客户端异常 + connection.on("error", function (err) { + console.log('异常') + }) +}) + +// 启动服务 +server.listen(PORT, () => { + console.log(`Server started on port ${PORT}`) +}) +``` diff --git a/blog/websocket/demo-socket.io.md b/blog/websocket/demo-socket.io.md new file mode 100644 index 0000000000000000000000000000000000000000..5eb9a5e818fac8e1a717dcf5df10ac451e74c9e9 --- /dev/null +++ b/blog/websocket/demo-socket.io.md @@ -0,0 +1,55 @@ +## 示例4 socket.io + +## 客户端 + +```html + + + + + +``` + +## 服务端 + +安装依赖 + +``` +cnpm i socket.io -S +``` + +代码示例 + +```js +const { Server } = require('socket.io'); +const { createServer } = require('http'); + +const httpServer = createServer(); + +// 处理跨域 +const io = new Server(httpServer, { + cors: { + origin: '*', + }, +}); + +io.on('connection', (socket) => { + // 接收数据, 监听自定义事件 + socket.on('message', (data) => { + // 发送数据 + socket.emit('message', data); + }); +}); + +httpServer.listen(8080); +``` diff --git a/blog/websocket/index.md b/blog/websocket/index.md new file mode 100644 index 0000000000000000000000000000000000000000..6b776ab3e01bb3df0dff62c30b51a186e70db650 --- /dev/null +++ b/blog/websocket/index.md @@ -0,0 +1,59 @@ + +[websocketd](http://websocketd.com/) is the WebSocket daemon, It's like CGI, twenty years later, for WebSockets + + +Web前端-3小时教你打造一个聊天室(websocket) + +https://www.bilibili.com/video/BV14K411T7cd + + +WebSocket 协议 + +基于TCP的一种新的网络协议,它实现了浏览器与服务器全双工(full-duplex)通信 + +允许服务器主动发送消息给客户端 + + +文档:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket/WebSocket + + +创建websocket对象 +```js +var ws = new WebSocket(url, [protocols]); +``` + +方法 + +方法 | 说明 +- | - +close() | 关闭链接 +send(data) | 发送数据 + +事件 + +事件名 | 说明 +- | - +open | 连接打开 +message | 接收到新消息 +error | 出现错误 +close | 连接关闭 + +实现技术: + +- 客户端:WebSocket +- 服务端:[nodejs-websocket](https://www.npmjs.com/package/nodejs-websocket) / [ws](https://www.npmjs.com/package/) + + + + +## 示例 + +[示例1 Echo](blog/websocket/demo-echo.md) + +[示例2 聊天室](blog/websocket/demo-chat.md) + +[示例3 聊天室升级版](blog/websocket/demo-chat-update.md) + +[示例4 socket.io](blog/websocket/demo-socket.io.md) + +https://www.bilibili.com/video/BV14K411T7cd?p=8&spm_id_from=pageDriver \ No newline at end of file diff --git a/doc/java.md b/doc/java.md index b5904a6ceb924d3049772a358eb1385b3dbe8733..e1eb97f905839bc339046568ee9d5dd789c99ed8 100644 --- a/doc/java.md +++ b/doc/java.md @@ -10,7 +10,14 @@ [Spring Initializr](https://start.spring.io/) -[JavaGuide](https://snailclimb.gitee.io/javaguide/#/) +[JavaGuide](https://snailclimb.gitee.io/javaguide/#/): 「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。 + + - [JavaGuide](https://javaguide.cn/) JavaGuide 在线阅读网站(新版,推荐👍) + +[Java 全栈知识体系](https://pdai.tech/) 包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 数据库原理, MySQL, ElasticSearch, MongoDB, Docker, k8s, CI&CD, Linux, DevOps, 分布式, 中间件, 开发工具, Git, IDE, 源码阅读,读书笔记, 开源项目... + +[CS-Notes](https://github.com/CyC2018/CS-Notes) 技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计 + - [http://www.cyc2018.xyz/](http://www.cyc2018.xyz/) [Java 教程 | 菜鸟教程](https://www.runoob.com/java/java-tutorial.html) @@ -26,6 +33,8 @@ - [在 html 中使用 thymeleaf 编写通用模块](https://www.cnblogs.com/miaoying/p/7804351.html) +[freemarker](https://freemarker.apache.org/): 用 Java 语言编写的模板引擎, + [JavaLite](https://javalite.io/) - Java, light as a feather [MyBatis-Plus](https://baomidou.com/): (简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 diff --git a/doc/mysql.md b/doc/mysql.md index 55be1f97a584365fabbd3fd174a8bfc31b5bdb3a..9577ead1fc88c652e91012aba3ef31b6c05f1447 100644 --- a/doc/mysql.md +++ b/doc/mysql.md @@ -1,3 +1,10 @@ # MySQL [H2 Database](http://www.h2database.com/): Very fast, open source, JDBC API + + +# 学习视频 + +[尚硅谷 MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!](https://www.bilibili.com/video/BV1iq4y1u7vj) 2021-11-17 + +[黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级](https://www.bilibili.com/video/BV1Kr4y1i7ru) 2022-01-18 \ No newline at end of file diff --git a/img/python-select-qrcode.jpeg b/img/python-select-qrcode.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b5c482fc1f299bfd8def95b524b48c0b9daacc1f Binary files /dev/null and b/img/python-select-qrcode.jpeg differ diff --git a/index.html b/index.html index ff3da023ebc41ae2741fedab5feec35effc2452f..bc51b946fa66618101a51c39668e171f0d38db3f 100644 --- a/index.html +++ b/index.html @@ -29,6 +29,11 @@ margin: 2em 0; padding-left: 20px; } + + /* 右侧目录 */ + .page_toc { + margin-top: 20px; + } @@ -40,6 +45,10 @@ window.$docsify = { name: 'Coding Tree', loadSidebar: true, + + // 导航栏 + loadNavbar: true, + // loadNavbar: true, repo: 'mouday/coding-tree', alias: {