所有由zhufenghua发布的文章

php验证邮箱的简单实现

使用 php 自带的 filter_var 函数

<?php
$email = "someone@exa mple.com";

if(!filter_var($email, FILTER_VALIDATE_EMAIL))
{
echo "E-mail is not valid";
}
else
{
echo "E-mail is valid";
}
?>

或者,使用正则表达式:

<?php
$mail = 'some@example.com';  //邮箱地址
$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";
preg_match($pattern, $mail, $matches);
var_dump($matches);  //输出匹配结果
?>

网站数据删除与 del 字段

在国内环境下,要求记录用户的行为日志,并且不可删除数据。(在一定期限内要保留)

给所有的表,设计一个 del 字段。

在删除时,实际是 update 表 set `del`=1 where `id`=xxx

还有另外一个作用。比如一个表涉及了多个用户。

用户 a 投递简历 给 商家 b

商家不想看这个简历了,点击”删除“,此时商家看不到。

但用户应该能看到它的投递信息,所以用户仍然可见,这也是 del 字段的好处之一。

另外值得一提,是 logstash ,对 ELK 技术熟悉的,都知道 logstash 在同步数据时,如果删除数据是无法同步删除记录到es的,也就是es中的数据只增不减。这用 del 字段也很符合。

基于此,对用户的所有数据,全部加上 del 字段,非管理员操作均不可删除,在特定情况下,管理员可真正删除数据。

最后,是数据库的定时触发器,比如清除半年、或一年、3年以上的旧数据,按需求进行定时清理。

数据库批量更新多条记录逻辑

从前端传递所有的记录数

首先,从数据库查询出所有的记录 id

比较新旧记录id:

  • 如果旧记录有,但新记录没有,说明是删除,归类到删除
  • 如果新记录有,旧记录没有,说明为新增(还有一种方法,就是新增时前端不传递id,后端判断记录无id即新增)
  • 其余全部为更新

批量插入 insert into xxx values(),(),()…

批量更新:update xxx set xxx case … when

批量删除:delete from xxx where id in(x, x, x)

加上前面的查询,通常情况下需要4条sql。

数据库冗余字段的好处与设计。

冗余字段,虽然在标准情况下,应该是没有冗余的。

但是在实际中,如果表与表的关系,需要关联太多。那么适当的冗余一些字段是非常好的。

举个例子:

一个人有多个简历,userid 对应多个 resume id

一个公司,有多个职位,一个 company id 对应 多个 post id

那么问题来了,在关系表:简历投递 “delivery” 中,正常应该是这样:

一个  简历id  对应一个 职位id

那么表中,应该有  rid  和  pid

看起来很标准的关系,实际用起来非常不方便,例如:

我是一个招聘公司,我需要找出所有投递到我公司的简历

(一个很基本的需求)

那么至少,你得关联两张表,也就是 :简历投递表( pid ) + 职位表 ( pid , cid )

如果使用冗余字段存储,可以这么设计:在简历投递表,记录 pid 和 cid,也就是在插入投递信息时,就把 cid 记录下来,这样可以不用关联职位表。

这里只是一个两表关联,对于3表关联以上,冗余存储就会更加实用。

综上,我们可以发现,在一些表中(特别是关系表中),冗余字段是有一定好处的,但这里所说的冗余是:有设计性的字段冗余,如果没有必要的冗余就真的是多余。

(如果关系会变动,则容易出问题,比如投递时把 cid 记录下来不关联职位表,而 pid 和 cid 如果可以发生转移,则会带来相当大的麻烦,因此要考虑到是否有主体转换问题)

gitee webhook 配合 宝塔hook实现网站代码的自动更新

本地开发完毕,提交 git ,自动触发 gitee webhook,

gitee webhook对线上服务器发起请求,触发服务器上的宝塔hook,接下来宝塔请求git同步,从而把gitee最新代码通过git同步到网站。

实现了本地开发完毕,提交git,线上就自动更新的过程。

为什么使用 gitee ?主要是速度快,github (或gitlab,gitea等)也有 webhook

为什么使用 宝塔hook?使用 php 简单写两句 git clone 也可以,但是 php服务器状态不一定正常,比如有时候502需要重启,而宝塔进程相对更加稳定。

服务器配置git

一般来说,已经安装了git,查看已安装版本号:

git --version

如果没有安装:

yum install git

配置git密钥

查看是否有密钥

cd ~/.ssh
ls
cat id_rsa.pub

如果没有,生成一个:(按前一个步骤查看)

ssh-keygen -t rsa 

把得到的公钥,放在 gitee 指定仓库 (管理 –> 公钥管理)中(添加一个)

添加 giteehook

在宝塔商城里 webhook ,

安装完毕后,添加一个 hook,名称随意,代码如下:

#!/bin/bash
echo ""
#输出当前时间
date --date='0 days ago' "+%Y-%m-%d %H:%M:%S"
echo "Start"
#判断宝塔WebHook参数是否存在
if [ ! -n "$1" ];
then
          echo "param参数错误"
          echo "End"
          exit
fi
#git项目路径
gitPath="/www/wwwroot/huaz"
#git 网址
gitHttp="git@gitee.com:zhufenghua1998/huaz.git"

echo "Web站点路径:$gitPath"
 
#判断项目路径是否存在
if [ -d "$gitPath" ]; then
        cd $gitPath
        #判断是否存在git目录
        if [ ! -d ".git" ]; then
                echo "在该目录下克隆 git"
                git clone $gitHttp gittemp
                mv gittemp/.git .
rm -rf gittemp
        fi
        #拉取最新的项目文件
        #git reset --hard origin/master
        git pull
        #设置目录权限
        #chown -R www:www $gitPath
        echo "End"
        exit
else
        echo "该项目路径不存在"
        echo "End"
        exit
fi

修改 git 路径,以及 url 两个参数。

重启一下 宝塔面板:(先切换 root )

/etc/init.d/bt restart

配置 git

git config --global user.name "用户名"
git config --global user.email "邮箱"
git config --global credential.helper store //会生成.gitconfig 的文件
cat .gitconfig   //如果报错: No such file or directory,就用下一行的代码
cat ~/.gitconfig  //显示内容

尝试克隆代码,到本地,检测git环境:

git clone https://gitee.com/XXX/XXX.git  //clone后面是下载链接

(假设 git 已经正常。。。)

点击 宝塔 的webhook,刚才添加的一个项目。查看密钥

宝塔WebHook使用方法:
GET/POST:
http://fewfewf.com:8888/hook?access_key=xxxxxxxxxxxxxxx&param=aaa
@param access_key string HOOK密钥
@param param string 自定义参数(在hook脚本中使用$1接收)

除了顶部的直接复制密钥外,也可以复制 url 的 access_key 参数,它们是一模一样的。

在 gitee 的 webhook (项目–> 管理 –> webhook)中,添加一个,均使用默认即可(也就是密码验证)

其中 URL 是前面宝塔的 webhook 给出的 url,最后的aaa参数,换成仓库名。

webhook密码,也就是宝塔hook的密码。

填完这两个参数,理论上已经完全ok,但实际可能有问题。

错误排查

宝塔的 webhook ,是否正常?它需要写一段代码,虽然前面已经复制粘贴了,但是会有错误。

我们点击一下测试宝塔的 webhook,如果提示:

2022-08-23 23:16:30
Start
param参数错误
End

则说明代码正常,如果仅有一个 Star,就说明文件格式出了问题。(你可能是从网页里复制过来的,所以乱码)

随意新建一个 .sh 或其他文件,然后粘贴上面的代码,接下来打开命令终端:

vim test.sh 打开文件,执行:set ff=unix设置文件为unix,然后执行:wq,保存成unix格式。

转换格式后,再打开该文件,复制转换后的代码,粘贴到宝塔的 webhook 中,看看是否正常了,如果输出 xxx 参数错误则说明文件格式 ok。

gitee的webhook是否正常?点击测试,并刷新页面,查看响应日志,

如果响应体如下,则说明正常:

{
  "code": 1
}

同时,也可以查看宝塔 webhook 的调用次数,观察 gitee 的 webhook ,是否能触发 宝塔的 webhook 。

最后,列出一些正确的日志:

2022-08-23 23:17:38
Start
Web站点路径:/www/wwwroot/huaz
Already up-to-date.
End

2022-08-23 23:18:10
Start
Web站点路径:/www/wwwroot/huaz
Updating d20b2cb..1e91e3f
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
End

如果是测试触发的,会像第一个日志,没有需要同步的文件,如果是更新推送到 gitee 从而导致自动触发更新,则像后面那个,自动同步了文件。

啥也不干还是感觉到很累?

大脑重量只占人体体重的2%,然而其消耗的能量却占人体总能量的20%,并且其中60-80%的能量都被一个叫做“DMN”的脑组织无情消耗。DMN(defaule mode-network)由内侧前额叶皮质、后扣带皮质、楔前叶以及顶下叶组成。即使大脑没有进行有意识的活动,它也会不断运行,执行一些基本的操作。也就是说,即使你在发呆或放空自己,只要DMN持续运行,大脑也会逐渐感到疲累。

越“瘫”越累的症状也许就是DMN消耗太多能量所致。

要想让大脑得到休息,必须抑制DMN对于大脑能量的过度消耗。

正确的思考,可以起到很大的作用。

通常情况下,我们认为工作和生活中的一些琐事,是不得不为,从而很少思考,只想草草了事。

或许我们可以换个想法,如果生活可以选择,你会作何选择?是不满与现状然后奋发图强?或许大部分人都没有那么大的勇气和毅力,所以享受当下才是我们生活的主节奏,说到底是我们选择了自己的生活,而不是生活迫使我们。

为什么编程中大家都喜欢使用int来代表各种状态和类型常量,而不是使用中文或英文单词常量?

省空间和内存。

更少的错误(跨语言、跨平台),如果使用中文,在不同语言开发环境下可能不同,而且不利于国际化(只有中文人员能看懂)

高效的搜索,搜索功能一般都很重要,字符串搜索和数字搜索,明细不同。

switch,在一些语言中,字符串不可以switch。

安全性:一般来说,用户或前端,不需要知道它代表什么意义,如果写得清清楚楚,在一定程序上不利于代码的安全性。

另外,还可以方便得转换字典,只要有一套字典,就可以轻松换成任何字符。

基于以上见解,推荐能使用数字尽量使用数字,如果数字多了感觉混乱,添加一个中间表,记录各个数字对应的中文解释,以便在必要情况下读取。

浏览器http请求并发限制

HTTP0.9、HTTP1.0每个请求单独建立一个TCP连接,请求完成连接断开;

HTTP1.1可以持久连接,TCP建立连接后不会立即关闭,多个请求可以复用同一个TCP连接,同时请求可以并行,但是不同浏览器对并行次数有个数限制,以下是各个浏览器的并发次数;

Broswer24
IE 6,724
IE 866
Firefox66
Safari44
Chrome66
Opera44

HTTP2发送请求时,既不需要排队发送,也不需要排队返回,降低了传输时间;
HTTP3目前还在草案阶段,使用 QUIC 替换 TCP,彻底规避了 TCP 传输的效率问题。

由于并发限制,通常情况下在程序设计时,不要超过6个接口,或不要同时播放超过6个视频(tcp实现),否则会导致卡住。

java(SpringBoot)响应jsonp请求

参考上一篇的 php响应jsonp请求 | 星冇之家 (5252.online) 请求,这里简单说下 java springmvc(或springboot响应jsonp)

实际也非常简单,首先使用 @restController 或者 @responseBody 返回字符串,然后接收 callback并封装成 callback对象即可。

例如:

   @GetMapping(value = "/xxx", produces = {"application/javascript"})
    public String users(@RequestParam String name, ..., @RequestParam String callback) {
        String jsonStr = "{'name':'" + name + "'}";
        return callback + "(" + jsonStr + ")";
    }

对于其他语言,也是如此,也证明了 jsonp 确实在任何语言都易于实现。