注解使用
DelayQueue有趣的延迟队列
简介
原文介绍:
1 | An unbounded blocking queue of Delayed elements, in which an element can only be taken when its delay has expired. The head of the queue is that Delayed element whose delay expired furthest in the past. If no delay has expired there is no head and poll will return null. Expiration occurs when an element's getDelay(TimeUnit.NANOSECONDS) method returns a value less than or equal to zero. Even though unexpired elements cannot be removed using take or poll, they are otherwise treated as normal elements. For example, the size method returns the count of both expired and unexpired elements. This queue does not permit null elements. |
简单翻译
DelayQueue是一个无界阻塞队列,只有在延迟期满时,才能从中提取元素。
队列的头部,是延迟期满后保存时间最长的delay元素。
MySQL8json特性
起因
最近重构单据中心的数据层,以满足公司业务发展需求。目前用的是MySQL5.4的版本,
公司的单据中心设计方案为:大JSON存储单据内容,再辅助各个子单据小表,达到搜索目的,
但随着单据类型的增多和字段增加,以及业务方越来愈多,这种方案不能很好的满住需求。
单据中心需要能检索json的能力,在技术选项上有ES,MonggoDB,PostgreSQL,MySQL8
为什么选择MySQL8而不是其他MySQL版本?
MySQL对json的支持是在5.7版本开始支持的。而需要使用的JSON_TABLE函数是在8.0版本才支持。
JSON函数
| 函数名 | 描述 |
|---|---|
| JSON_VALID() | JSON值是否是有效的 |
| JSON_UNQUOTE() | JSON值而言 |
| JSON_TYPE() | JSON值类型 |
| JSON_STORAGE_SIZE() | 用于一个JSON文件的二进制表示形式存储空间;一个JSON柱,空间时使用的文档插入到任何部分更新之前, |
| JSON_SET() | 将数据插入到JSON文档 |
| JSON_SEARCH() | 在JSON文件价值路径 |
| JSON_REPLACE() | 在JSON文件的值替换 |
| JSON_REMOVE() | 从JSON文件中删除数据 |
| JSON_QUOTE() | 引用JSON文档 |
| JSON_PRETTY() | 版画在人类可读的格式JSON文档,每个数组元素或对象成员打印在新的行中,缩进两个空格就其母。 |
| JSON_OBJECT() | 创建JSON对象 |
| JSON_MERGE_PRESERVE() | 合并的JSON文件,保存重复键 |
| JSON_MERGE_PATCH() | 合并的JSON文件,免去重复键的值 |
| JSON_MERGE()(废弃的5.7.22) | 合并的JSON文件,保存重复键。不json_merge_preserve()的同义词 |
| JSON_LENGTH() | 在JSON文档中的元素数 |
| JSON_KEYS() | 从JSON文件密钥数组 |
| JSON_INSERT() | 将数据插入到JSON文档 |
| JSON_EXTRACT() | 从JSON文档返回数据 |
| JSON_DEPTH() | JSON文档的最大深度 |
| JSON_CONTAINS_PATH() | 无论是JSON文件包含任何数据路径 |
| JSON_CONTAINS() | 是否包含特定对象的JSON文档路径 |
| JSON_ARRAY_INSERT() | 插入JSON数组 |
| JSON_ARRAY_APPEND() | JSON文件追加数据 |
| JSON_ARRAY() | 创建JSON数组 |
| JSON_APPEND()(废弃的5.7.9) | JSON文件追加数据 |
| ->> | 在评估路径和结束引语结果返回JSON列值;相当于json_unquote(json_extract())。 |
| -> | 在评估路径返回JSON列值;相当于json_extract()。 |
JSON_TABLE函数的应用
读取单据行数据
1 |
|
提高json检索速度
很遗憾mysql原生并不支持json列中的属性索引,
但是我们可以通过mysql的虚拟列(5.7版本支持)间接的为json中的某些属性创建索引
,原理就是为json中的属性创建虚拟列,然后通过给虚拟列建立索引,
从而间接的给属性创建了索引。
建立虚拟列
在MySQL 5.7中,支持两种
- Generated Column,即Virtual Generated Column
- Stored Generated Column
前者只将Generated Column保存在数据字典中(表的元数据),并不会将这一列数据持久化到磁盘上;
后者会将Generated Column持久化到磁盘上,而不是每次读取的时候计算所得。
很明显,后者存放了可以通过已有数据计算而得的数据,需要更多的磁盘空间,
与Virtual Column相比并没有优势
,因此,MySQL 5.7中,不指定Generated Column的类型,默认是Virtual Column。
1 |
|
创建表
1 |
|
添加索引
跟添加一般索引一样
1 |
|
缺点
这种方法只能只能对json的某个单值属性或者给数组中的某一个特定位置上的元素有效,
如果你想给对象数组中的所有元素的某个属性使用索引,
那么最后你只能匹配数组中的所有对象的该属性或者使用like,
但是使用like的话就不能使用索引,也就是说对于这种情况是不可用的。
网页五子棋
SpingBoot2 配置HTTPS,并实现HTTP访问自动转HTTPS访问
SSL证书生成
生产环境是向证书供应商进行购买,在使用工具转换
我们着使用java自带的工具进行生成,可以使用keytool –help查看具体用法
jks证书(java专用)
1 | keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 3650 #生成证书 |
PKCS12
1 | keytool -genkeypair -alias tomcat -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650 #生成证书 |
生成证书都会要求你输入密码,注意,请记住这个密码,后面springboot配置要用到。
JKS迁移成PKCS12证书
1 | keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12 -deststoretype pkcs12 |
证书供应商提供的证书
1 | keytool -import -alias tomcat -file myCertificate.crt -keystore keystore.p12 -storepass password |
Spring Boot 启用https
配置文件
1 | #访问的端口 |
启动服务器 访问https 的 8488端口 应该就能访问了
http重定向到https
spring boot 2.x 版本代码
1 | import org.apache.catalina.Context; |
访问8080端口 会自动跳转到 https 的端口
其他(非必要操作)
获取分发给客户端的证书
1 | keytool -export -keystore keystore.jks -alias tomcat -file myCertificate.crt |
jdk导入证书 方便java程序访问https访问时进行证书的验证
1 | keytool -importcert -file myCertificate.crt -alias tomcat -keystore $JDK_HOME/jre/lib/security/cacerts |
思考❓
浏览器怎么和证书进行关联?通过别名么? 别名设置成域名?
dsupervisor 简单教程
安装supervisor
1 | pip install supervisor |
如果环境没有 pip工具
1 | wget supervisor下载地址 |
使用
生成配置文件
1 | echo_supervisord_conf > /etc/supervisord.conf |
启动supervisor
1 | supervisord -c /etc/supervisord.conf |
检查是否启动成功
可以通过查看进程列表方式进行判断
1 | ps aux | grep supervisord |
配置
/etc/supervisord.conf 文件
1 | ; Sample supervisor config file. |
###自定义配置文件
/etc/supervisor/spring-boot-demo.conf 文件
1 | ; 设置进程的名称,使用 supervisorctl 来管理进程时需要使用该进程名 |
以下是我在网上找的全部的配置说明
1 | ;[program:theprogramname] ;这个就是咱们要管理的子进程了,":"后面的是名字,最好别乱写和实际进程 |
更改了配置文件需要重新加载配置文件,supervisor会重启各个引用
1 | supervisorctl reload |
supervisorctl 使用
1 | supervisord #启动supervisor |
使用浏览器来管理进程
编辑/etc/supervisord.conf 文件
1 | ;配置内部HTTP-SERVER,注意0.0.0.0 是开放给任何IP访问的, |
补充
命令运行不了
有可能是运行命令的权限不够 需要 sudo 命令
浏览器访问不了管理界面
有可能是Linux防火墙不允许访问9001端口
以centos7为例:
1
2firewall-cmd --permanent --add-port=9001/tcp #防火墙加入9001端口
firewall-cmd --reload #重启防火墙 使端口生效
websocket 断线重连方案
起因
最近向海关上报支付单时,加密过程只能用海关提供的websocket服务进行加签。
在使用过程中,由于海关的服务不够稳定 socket经常中断,所以需要对websocket 进行断线重连
解决方案
不停的检查websocket的连接状态,对于已经关闭连接的websocket进行重新初始化(因为断掉的websocket不能进行重新连接)
1 |
|
1 |
|
WebSocketClient只能连接一次的原因
/**
* Initiates the websocket connection. This method does not block.
*/
public void connect() {
if( writeThread != null )
throw new IllegalStateException( "WebSocketClient objects are not reuseable" );
writeThread = new Thread( this );
writeThread.start();
}
···
shell入门
#shell入门
Shell是什么
Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务, Shell脚本(shell script),是一种为Shell编写的脚本程序。我们经常说的shell通常都是指shell脚本。
环境和工具
Shell跟java、php、Python编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Mac OS,Linux 自带了shell解释器,Windows比较麻烦,没有内置shell解释器,可以自行安装
一个cygwin
PHP、Python 也可以作为Shell编程
PHP、Python是属于高级编程语言,但是也可以做Shell编程,因为只要有解释器,也可以用作脚本编程
如下是一个Python Shell Script示例(假设文件名叫op_python_base.py):
1 | #!/usr/bin/env python3 //告诉Python从系统环境中找python |
如下是一个PHP Shell Script示例(假设文件名叫op_php_base.php):
1 | #!/usr/bin/php |
为什么要学习Shell
既然PHP、Python都可以用来写脚本编程,那为什么还要学习陌生、晦涩难懂的Shell,主要有一下几个原因
环境兼容性,因为除了windows,基本其他主流的操作系统都预制了Shell解释器,所以使用sh、bash编写,提供给其他人使用是非常方便的,但是PHP、Python 等等需要安装相应的环境
如果你想做一些定时任务比如说检测进程是否存在,自动备份,或者说自动部署环境、服务器之间的数据同步等等sh、bash会是你最好的选择
sh与bash
sh: Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh
bash: Bash是Bourne shell的替代品,属GNU Project,二进制文件路径通常是/bin/bash
第一个shell脚本
我们先来看一个例子
我相信写过代码的童鞋,应该对下面的代码很熟悉并不陌生,(假设文件名叫op_base.sh):
1 | #!/usr/bin/env bash |
第一行:从系统path中寻找指定脚本的解释程序
第二行:创建 名叫code文件夹
第三行:进入创建的文件夹
第四行:for循环3次
第四行:创建文件
第五行:往创建的文件中写入信息
第六行:结束循环
mkdir, touch,cd,touch,echo都是系统命令,在命令行下可以直接执行
for, do, done 是shell脚本语言 for循环的语法
编写Shell
新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用php,扩展名为php,如果你用Python,扩展名为python
第一行一般是这样:
1 | #!/usr/bin/php |
#!”是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行
/env 是系统的PATH目录中查找
运行 Shell 脚本有两种方法:
作为可执行程序
1 | chmod +x op_base.sh |
第一行设置 op_base.sh可执行权限
第二行执行op_base.sh
作为参数
1 | /bin/sh op_base.sh |
变量
定义变量时,变量名前不需要加符号和Python一样但是在PHP语言中变量需要加$,如:
1 | my_name="jack" |
ps: 变量名和等号之间不能有空格,变量后面不能有;
Shell中的引号和PHP类似,字符串可以用单引号,也可以用双引号
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 单引号字串中不能出现单引号(对单引号使用转义符后也不行
双引号:
- 双引号里可以有变量
- 双引号里可以出现转义字符
但是在Python中单引号和双引号是没有区别,但是Python 还有三个引号,在三个引号内字符都不会被转义
使用变量
对于已经定义过的变量,使用的适合在前面添加$
1 | echo $my_name |
变量名外面的花括号是可选的,加不加都行,建议使用第二种形式
注释
以“#”开头的行就是注释,会被解释器忽略。
多行注释
sh里没有多行注释,只能每一行加一个#号。就像这样:
1 | #-------------------------------------------- |
字符串
字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似
Shell不像其他语言有php、python 有很多数据类型,在Shell中常用的数据类型字符串数字和字符串(ps: 除了数字和字符串,也没啥其它类型好用了,哈哈)
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 单引号字串中不能出现单引号(对单引号使用转义符后也不行
双引号:
- 双引号里可以有变量
- 双引号里可以出现转义字符
字符串操作
拼接字符串
1 | my_name="jack"; |
获取字符串长度
1 | echo ${#my_name} |
截取字符串
1 | echo ${my_name:0:2} |
Shell 数组
定义数组
在Shell中,用括号来表示数组,数组元素用”空格”符号分割开。定义数组的一般形式为:
1 | name=(name1 name2 name3) |
还可以单独定义数组的各个分量:
1 | ary[0]=name1 |
ps: 可以不使用连续的下标,而且下标的范围没有限制
读取数组
读取数组元素值的一般格式是:
1 | ${数组名[下标]} |
例如:
1 | echo ${name[0]} |
使用@符号可以获取数组中的所有元素,例如:
1 | echo ${name[@]} |
获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,例如:
1 | # 取得数组元素的个数 |
Shell 流程控制
和Java、PHP、Python等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法):
1 | <?php |
在sh/bash里可不能这么写,如果else分支没有语句执行,就不要写这个else
if
1 | if condition1 |
例子:
1 | #!/usr/bin/env bash |
for 循环
Shell的for循环和Python 有点类似
Python的for循环
1 | for index in 1,2,3,4,5: |
Shell的for循环,第一种写法
1 | for index in 1 2 3 4 5; do |
Shell的for循环,第二种写法
1 | for ((i=0; i<5; i++)); do |
while 语句
while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。
1 | int=1 |
Shell结合系统命令
sh脚本结合系统命令便有了强大的威力,在字符处理领域,有grep、awk、sed三剑客,grep负责找出特定的行,awk能将行拆分成多个字段,sed则可以实现更新插入删除等写操作。
例如定时检测nginx、mysql是否被关闭
1 | path=/var/log |
解释:检测 nginx、mysql进程是否存在,如果不存在了会自动重新启动。
脚本每次运行会写日志的,没事可以去看看该日志文件,如果进程是不是真的经常性不存在,恐怕就要排查一下深层原因了。
编辑 /etc/crontab 文件
1 | crontab -e |
在文件最后添加一行:
1 | */5 * * * * /xxx/check_nginx.sh > /dev/null 2>&1 |
上表示每 5 分钟,执行一下脚本 /xxx/check_nginx.sh,其中xxx代表路径
/dev/null 2>&1 的意思是该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中。
1 | #cron表达式每个位置的含义 |
添加完配置,重启才能生效
1 | service crond restart |
vue bootstrap 带分页表格
前端渲染分页表格整体解决方案