假设我们现在有这样一个需求:多人聊天室。我的思路是客户端发送消息给服务器,然后服务器把聊天信息全部返回,看起来比较简单哈,但是其中有一个问题,如果我不发消息的话,服务器怎么把其他人的聊天信息返回呢?一个比较笨的方法就是一直询问服务器,其他人是否发消息。出现这样的情况是因为http协议是单向通信,只支持客户端到服务端的通信,不支持服务端到客户端的通信,那我们有没有什么更简单的解决方案呢?为了解决实时数据传输和双向通信的需求,我们的主角WebSocket登场了。
View DetailsOkHttp 在 Java 和 Android 世界中被广泛使用,深入学习源代码有助于掌握软件特性和提高编程水平。
本文首先从源代码入手简要分析了一个请求发起过程中的核心代码,接着通过流程图和架构图概括地介绍了 OkHttp 的整体结构,重点分析了拦截器的责任链模式设计,最后列举了 OkHttp 拦截器在项目中的实际应用。
在生产实践中,常常会遇到这样的场景:需要针对某一类 Http 请求做统一的处理,例如在 Header 里添加请求参数或者修改请求响应等等。这类问题的一种比较优雅的解决方案是使用拦截器来对请求和响应做统一处理。
在 Android 和 Java 世界里 OkHttp 凭借其高效性和易用性被广泛使用。作为一款优秀的开源 Http 请求框架,深入了解它的实现原理,可以学习优秀软件的设计和编码经验,帮助我们更好到地使用它的特性,并且有助于特殊场景下的问题排查。本文尝试从源代码出发探究 OkHttp 的基本原理,并列举了一个简单的例子说明拦截器在我们项目中的实际应用。本文源代码基于 OkHttp 3.10.0。
本次选用各中间件的最新版本。 Nginx-1.23.2 + PHP 8.2.0 + Mysql 8.0.31。 先去各自官网下载 windows 对应的安装包备用。 PHP 安装 解压安装包 配置 在解压的目录下复制 php.ini-development 到 php.ini 作为正式的配置文件。 设置常用信息 memory_limit = 128M (脚本可用的最大内存) error_reporting = E_ALL (显示错误等级) display_errors = On (是否显示错误) post_max_size = 8M (post 提交的最大容量) file_uploads = On (是否可以上传文件) upload_max_filesize = 2M (最大上传文件大小) max_file_uploads = 20 (最多上传文件数量) date.timezone = Asia/Shanghai (设置时区) 开启需要的扩展,常用扩展默认都包含,不需要去掉前面的注释 Mysql 安装 解压安装包 安装&配置 以管理员身份运行 cmd 切到解压后的 bin 目录 执行 mysqld -install 进行安装,完成后会提示 Service successfully installed. 执行 mysqld--initialize-insecure --user=mysql 初始化数据库 完成后会生成 data 目录 并在 data 目录中 xxx.err 文件中记录初始账号密码信息 把 bin 目录加入环境变量中 解压目录下新建 my.ini 文件,根据需求记入配置信息
1 2 3 4 |
[mysqld] basedir=D:\TOOLS\PHP-DEV\mysql-8.0.31 datadir=D:\TOOLS\PHP-DEV\mysql-8.0.31\data port=3306 |
确认 执行 net start mysql 启动 mysql 服务 cmd 中或者其他客户端工具连接 mysql 测试 重置 root 密码,然后退出用新密码再次登录确认
1 |
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; |
其他设置 查看编码 mysql> […]
View Details参考:https://blog.csdn.net/linysuccess/article/details/109223712 配合上篇文章,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebSocket测试</title> <script> function initWebSocket(wsUri) { var websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { console.log('连接建立中... '+wsUri); }; websocket.onclose = function(evt) { console.log('连接关闭中...', evt); }; websocket.onmessage = function(evt) { console.log('收到来自服务端的消息:', evt.data); }; websocket.onerror = function(evt) { console.log('发生错误...', evt); }; return websocket; } // 在此配置 websocket 的地址 var websocket = initWebSocket("ws://localhost:8020/ws"); var msg, i = 0; var loop = setInterval(function(){ msg = "Hello " + (i++); if(websocket.readyState == WebSocket.OPEN) { websocket.send(msg); console.log('已发送消息:' + msg); } else { clearInterval(loop); console.log('连接已关闭,拜拜~'); } }, 3000); </script> </head> <body> 请按 F12 打开控制台查看消息 </body> </html> |
from:http://www.manongjc.com/detail/22-lipyczhcovoolme.html
View Details1、@Autowired默认是根据类型(ByType)注入的,@Resource默认是根据名称(ByName)注入的。
2、@Autowired是Spring提供的注解,@Resource是JDK提供的注解
3、当一个接口存在多个实现类,@Autowired和@Resource都是需要指定Bean的名称才能完成注入,@Autowired可通过@Qualifier来只能Bean的名称进行注入,@Resource则可通过name来完成Bean的注入。
View Details在设计模式中有六大设计原则:
单一职责原则:一个类只做一件事
里式替换原则:子类可以扩展父类
依赖倒置原则:面向接口编程
接口隔离原则:高内聚低耦合
迪米特法则:最少知道原则
开闭原则:关闭修改,开放新增
我认为在这六个原则中开闭原则最为重要,开闭原则是可扩展性的重要基石。
第一个原因是需求变化时应该通过新增而不是修改已有代码实现,这样保证了代码稳定性,避免牵一发而动全身。
第二个原因是可以事先定义代码框架,扩展也是根据框架扩展,体现了用抽象构建框架,用实现扩展细节,保证了稳定性也保证了灵活性。
第三个原因是其它五个原则虽然侧重点各有不同,但是都可以包含于开闭原则。
第四个原因是标准二十三种设计模式最终都是在遵循开闭原则。
既然开闭原则如此重要,我们应该怎么在系统设计时遵循开闭原则呢?
View Details
1 2 3 4 5 6 7 |
// 忽略证书验证 if (AppConfig.HisUrl.StartsWith("https")) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; } |
View Details
这个问题很微妙,可能这位同学内心深处,觉得 Redis 是所有应用缓存的标配。
缓存的世界很广阔,对于应用系统来讲,我们经常将缓存划分为本地缓存和分布式缓存。
本地缓存 :应用中的缓存组件,缓存组件和应用在同一进程中,缓存的读写非常快,没有网络开销。但各应用或集群的各节点都需要维护自己的单独缓存,无法共享缓存。
分布式缓存:和应用分离的缓存组件或服务,与本地应用隔离,多个应用可直接共享缓存。
View DetailsNginx 读作 engine x, 是一个免费的、开源的、高性能的 HTTP 和反向代理服务,主要负责负载一些访问量比较大的站点。 Nginx 可以作为一个独立的 Web 服务,也可以用来给 Apache 或是其他的 Web 服务做反向代理。 相比于 Apache,Nginx 可以处理更多的并发连接,而且每个连接的内存占用的非常小。 本教程将会教您如何在 Centos 7 的服务器上安装和管理 Nginx。 开始前的准备 在开始阅读此教程之前,请确保你是以拥有 sudo 权限的用户来登录的服务器,并且服务器中没有 Apache 或是其他服务正在使用 80(HTTP) 和 443(HTTPS) 端口上,防止端口被占用,造成 Nginx 无法正常启动。 在 CentOS 中安装 Nginx 请按照下面的步骤,在 CentOS 中安装 Nginx。 1、 EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装:
1 |
sudo yum install epel-release |
上面代码的意思是以 sudo 权限运行安装 epel-release,如果你当前登录的用户不是 root,则会提示你输入密码来运行,输入密码时是看不到输入的内容的,所以不用担心,继续输入就行。然后回车继续运行,后面的命令中如果包含 sudo 则都表明是刚提到的意思,不再重复解释。 2、 输入以下命令来安装 Nginx:
1 |
sudo yum install nginx |
如果这是您第一次从 EPEL 仓库中安装软件,yum 可能会提示您导入 EPEL GPG key:
1 2 3 4 5 6 7 |
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Importing GPG key 0x352C64E5: Userid : "Fedora EPEL (7) <epel@fedoraproject.org>" Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5 Package : epel-release-7-9.noarch (@extras) From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Is this ok [y/N]: |
类似于上面的内容,遇到这种情况,输入 y,然后 Enter(回车) 即可继续安装。 3、 等到安装完成以后,可以通过以下命令来设置开机启动和运行 Nginx 服务: 设置 Nginx 开机启动:
1 |
sudo systemctl enable nginx |
运行以上命令以后,会输出类似以下的内容,表示创建了一个软连接来关联 Nginx,不用担心,并不是报错了,下一步就可以启动 Nginx 了。
1 |
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service. |
启动 Nginx:
1 |
sudo systemctl start nginx |
通过运行以下命令,来检查 Nginx 的运行状态:
1 |
sudo systemctl status nginx |
然后会输出类型下面的内容 […]
View Detailsjs获取当前毫秒数(+new date()) 前言 在看视频的时候发现老师获取当前日期的毫秒表示时使用了let t1 = +new date()的写法,起初没有明白代码的含义,经过测试发现为日期的毫秒表示; 详情 代码:
1 2 3 4 5 6 |
<script> let d1 = +new Date(); //1630316745222 let d2 = new Date(); //Mon Aug 30 2021 17:46:28 GMT+0800 (中国标准时间) console.log(typeof d1 +':'+ d1 ) console.log(typeof d1 +':'+ d2) </script> |
解释: 经测试和查阅后得知**+new Date ()**相当于调用 Date.prototype.valueOf ()方法,返回的是当下的时间距离1970年1月1日0时0分0秒的毫秒数 获取当前时间毫秒数的方法 +new Date() new Date().valueOf() new Date().getTime() Date.parse(new Date()) 注意:精确到秒,会将后三位舍弃为0
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<script> //new Date().valueOf() let d1= new Date().valueOf(); console.log(d1) //1630318883445 // new Date().getTime() let d2= new Date().getTime(); console.log(d2) //1630318883445 //Date.parse(new Date()) let d3 = Date.parse(new Date()); console.log(d3) //1630318883000 </script> |
from:https://blog.csdn.net/Ldcrle/article/details/120002457
View Details