centos7.x 安装 MySQL 5.5

centos7默认自带的是mariadb,有些旧业务需要老版本的mysql
卸载原有mariadb

// 检索是否安装了mariadb
# rpm -qa | grep mariadb
mariadb-5.5.56-2.el7.x86_64
mariadb-devel-5.5.56-2.el7.x86_64
mariadb-libs-5.5.56-2.el7.x86_64
mariadb-server-5.5.56-2.el7.x86_64
// 卸载mariadb
# rpm -e --nodeps mariadb-5.5.56-2.el7.x86_64 mariadb-devel-5.5.56-2.el7.x86_64 
mariadb-libs-5.5.56-2.el7.x86_64 mariadb-server-5.5.56-2.el7.x86_64
// 设置rmp 
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
# rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm
// 下载安装MySql client and server
# yum install mysql55w mysql55w-server
// 启动MySql
# service mysqld start
// 修改密码(初始密码为空)
# mysqladmin -u root password 'root'
// 登录
# mysql -u root -p

vmware虚拟机的centos密码重置

centos里面的密码忘记了,需要重置密码,如果是物理机,此篇文章不适用,此篇文章适合vmware里面安装的centos忘记密码,总共有如下几步:
1:启动虚拟机,出现下面的倒计时界面时,按键盘上的e键.
e1.png
2:进入如下后界面,再按e键
e2.png
3:进入如下界面后,使用键盘上的上下键,选中第二项以kernel开头的项。选中后,再次按e键。
e3.png
4:进入以下界面后,在最后面输入空格和s,然后回车。
e4.png
5:接着会回到如下界面,然后按下b键(b代表boot启动)
e5.png
6:进入如下界面:
e6.png
7:此时输入passwd root回车, 重置密码
8:输入密码,回车,确认密码,回车,输入reboot,回车

参考:
https://blog.csdn.net/wyx_wyl/article/details/78246907

echarts添加水印

用echats做的一张图表需要添加水印,一般有两种做法:
1:直接用dom决定定位盖上去,这种方式缺陷比较大
2:用echats官方指定的做法,在options里面添加图片作为背景,但也有一些小缺陷,容易被上层的一些东西遮住。

var waterMarkText = 'ciika';
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = 100;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.globalAlpha = 0.1;
ctx.font = '20px Microsoft Yahei';
ctx.translate(50, 50);
ctx.rotate(-Math.PI / 4);
ctx.fillText(waterMarkText, 0, 0);

然后在通过参数配置进去

backgroundColor: {
 type: 'pattern',
 image: canvas,
 repeat: 'repeat'
}

cc.png

参考官方链接为
https://www.echartsjs.com/gallery/editor.html?c=watermark

浏览器缓存详细解释[转]

转自:浏览器缓存看这一篇就够了 https://segmentfault.com/a/1190000018717463

浏览器缓存作为性能优化的重要一环,对于前端而言,重要性不言而喻。以前总是一知半解的,所以这次好好整理总结了一下。

1、缓存机制

首先我们来总体感知一下它的匹配流程,如下:

浏览器发送请求前,根据请求头的expires和cache-control判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步。
没有命中强缓存规则,浏览器会发送请求,根据请求头的last-modified和etag判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。
如果前两步都没有命中,则直接从服务端获取资源。
11.png

2、强缓存

强缓存:不会向服务器发送请求,直接从缓存中读取资源。

2.1 强缓存原理
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种(暂不分析协商缓存过程),如下:

第一次请求,不存在缓存结果和缓存标识,直接向服务器发送请求
12.png

存在缓存标识和缓存结果,但是已经失效,强制缓存是啊比,则使用协商缓存(暂不分析)
14.png

存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
15.png

那么强制缓存的缓存规则是什么?
当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control优先级比Expires高。

2.1.1、 Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
2.1.2、 Cache-Control
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存,主要取值为:

public:所有内容都将被缓存(客户端和代理服务器都可缓存)
private:所有内容只有客户端可以缓存,Cache-Control的默认取值
no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
max-age=xxx (xxx is numeric):缓存内容将在xxx秒后失效
需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致,也就是协商缓存。而no-store才表示不会被缓存,即不使用强制缓存,也不使用协商缓存
2.1.3、设置
强缓存需要服务端设置expires和cache-control。
nginx代码参考,设置了一年的缓存时间:

location ~ .*\.(ico|svg|ttf|eot|woff)(.*) {
  proxy_cache               pnc;
  proxy_cache_valid         200 304 1y;
  proxy_cache_valid         any 1m;
  proxy_cache_lock          on;
  proxy_cache_lock_timeout  5s;
  proxy_cache_use_stale     updating error timeout invalid_header http_500 http_502;
  expires                   1y;
}

浏览器的缓存存放在哪里,如何在浏览器中判断强制缓存是否生效?这就是下面我们要讲到的from disk cache和from memory cache。

2.2、from disk cache和from memory cache
细心地同学在开发的时候应该注意到了Chrome的网络请求的Size会出现三种情况from disk cache(磁盘缓存)、from memory cache(内存缓存)、以及资源大小数值。

状态 类型 说明
200 form memory cache 不请求网络资源,资源在内存当中,一般脚本、字体、图片会存在内存当中
200 form disk ceche 不请求网络资源,在磁盘当中,一般非脚本会存在内存当中,如css等
200 资源大小数值 从服务器下载最新资源
304 报文大小 请求服务端发现资源没有更新,使用本地资源
浏览器读取缓存的顺序为memory –> disk。
以访问https://github.com/xiangxingchen/blog为例
我们第一次访问时https://github.com/xiangxingchen/blog
16.png

关闭标签页,再此打开https://github.com/xiangxingchen/blog时
17.png

F5刷新时
18.png

简单的对比一下
19.png

3、协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:

协商缓存生效,返回304和Not Modified
20.png

协商缓存失效,返回200和请求结果
21.png

3.1、Last-Modified和If-Modified-Since
浏览器首先发送一个请求,让服务端在response header中返回请求的资源上次更新时间,就是last-modified,浏览器会缓存下这个时间。
然后浏览器再下次请求中,request header中带上if-modified-since:[保存的last-modified的值]。根据浏览器发送的修改时间和服务端的修改时间进行比对,一致的话代表资源没有改变,服务端返回正文为空的响应,让浏览器中缓存中读取资源,这就大大减小了请求的消耗。
由于last-modified依赖的是保存的绝对时间,还是会出现误差的情况:

保存的时间是以秒为单位的,1秒内多次修改是无法捕捉到的;
各机器读取到的时间不一致,就有出现误差的可能性。为了改善这个问题,提出了使用etag。
3.2、ETag和If-None-Match
etag是http协议提供的若干机制中的一种Web缓存验证机制,并且允许客户端进行缓存协商。生成etag常用的方法包括对资源内容使用抗碰撞散列函数,使用最近修改的时间戳的哈希值,甚至只是一个版本号。 和last-modified一样.

浏览器会先发送一个请求得到etag的值,然后再下一次请求在request header中带上if-none-match:[保存的etag的值]。
通过发送的etag的值和服务端重新生成的etag的值进行比对,如果一致代表资源没有改变,服务端返回正文为空的响应,告诉浏览器从缓存中读取资源。
etag能够解决last-modified的一些缺点,但是etag每次服务端生成都需要进行读写操作,而last-modified只需要读取操作,从这方面来看,etag的消耗是更大的。
二者对比

精确度上:Etag要优于Last-Modified。
优先级上:服务器校验优先考虑Etag。
性能上:Etag要逊于Last-Modified

4、用户行为对浏览器缓存的影响

打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control:no-cache(为了兼容,还带了 Pragma:no-cache),服务器直接返回 200 和最新内容。

5、总结

22.png

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。

java图片转换成base64

有时候不比避免了使用了一些侵权图片,避免被AI图像识别,可把图片转成base64加载,在经过一些其它的处理,能相对比较有效的减少这类问题。
利用java把图片转成base64的代码片段为:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Base64;
import java.util.Base64.Encoder;

/**
 * 利用Java把图片转成base64
 * @author ciika.com
 */
public class Image2Base64 {
    
    
    public static String getImageBase64String(String imgFile) throws IOException {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Encoder encoder = Base64.getEncoder();
        //图片转成base64后一定要加上头部的信息,不然前端Html里面没办法使用
        return String.format("data:%s;base64,%s",appendHead(imgFile),encoder.encodeToString(data));
    }
    /**
     * 根据文件内容获取文件类型
     * @param path 图片地址
     * @return 前缀
     * @throws IOException
     */
    private static String appendHead(String path) throws IOException {
        return Files.probeContentType(new File(path).toPath());
    }
}