0%

查看

show variables like '%max_connections%';

数值过小会经常出现ERROR 1040: Too many connections错误

show global status like 'Max_used_connections';

-- Threads_connected: 打开的连接数,Threads_running:激活的 正在使用的连接数
show status like 'Threads%';

-- 查看最大缓存的连接数量,可以适当增加
show variables like 'thread_cache_size';

设置

  1. 临时设置
set global max_connections=1024;

重启失效.

  1. 永久设置
-- 修改mysql配置文件my.cnf,在[mysqld]段中添加或修改max_connections值:
max_connections=512

重启生效.

引入依赖

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.0</version>
</dependency>

编写工具类

public class QRCodeUtil {
    // 设置二维码长宽
    private static int width = 400;
    private static int height = 400;
    private static String format = "png";

    // 将文本信息封装到二维码中,并返回图片的Base64编码后的字符串
    public static String encodeQRCode(String text) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        String result = null;
        try {
            Map<EncodeHintType, Object> hints = new HashMap<>();
            // 设置字符集编码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
            // 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            // 设置二维码边距,单位像素,值越小,二维码距离四周越近
            hints.put(EncodeHintType.MARGIN, 1);
            // 生成二维码矩阵
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            // 写入文件
            MatrixToImageWriter.writeToStream(bitMatrix, format, outputStream);
            bitMatrix.clear();
            result = "data:image/png;base64," + Base64.getEncoder().encodeToString(outputStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
            }
        }
        return result;

    }

    // 通过base64编码后的图片,解析出二维码中的文本信息
    public static String decodeQRCode(String base64) {
        Result result = null;
        BufferedImage image = null;
        ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64));
        try {
            // 读取图片
            image = ImageIO.read(inputStream);
            // 多步解析
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            // 设置字符集编码
            Map<DecodeHintType, String> hints = new HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            // 对图像进行解码
            result = new MultiFormatReader().decode(binaryBitmap, hints);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            image.getGraphics().dispose();
            try {
                inputStream.close();
            } catch (IOException e) {
            }
        }
        return result.getText();
    }
}

测试

    // 测试准确率还是非常高的
    public static void main(String[] args) {
        // 生成二维码
        System.out.println(encodeQRCode("我叫XX勇~~~"));
        // 解码二维码
        // 注意:需要去掉data:image/png;base64,
        System.out.println(decodeQRCode("xxxxxxxxxx.....xxxxxxxx"));
    }

问题

  • openjdkoracle jdk一些情况下并不兼容;
  • openjdk镜像很小只有一百朵兆,但是oracle jdk搜到的镜像都很大.

步骤

  1. 下载最新的oracle jre 8
https://javadl.oracle.com/webapps/download/AutoDL?BundleId=242050_3d5a2bb8f8d4428bbe94aed7ec7ae784
  1. 上传到linux并解压
[root@node1 jdk8]# tar -xvzf jre-8u251-linux-x64.tar.gz 
[root@node1 jdk8]# pwd
/root/jdk8
[root@node1 jdk8]# ll
总用量 85492
drwxr-xr-x 5 10143 10143       76 7月   9 14:04 jre1.8.0_251
-rw-r--r-- 1 root  root  87543611 7月   9 13:55 jre-8u251-linux-x64.tar.gz
  1. 删除一些说明文档和无用包
[root@node1 jdk8]# cd jre1.8.0_251/

rm -rf COPYRIGHT LICENSE README release THIRDPARTYLICENSEREADME-JAVAFX.txt THIRDPARTYLICENSEREADME.txt Welcome.html
rm -rf   lib/plugin.jar \
           lib/ext/jfxrt.jar \
           bin/javaws \
           lib/javaws.jar \
           lib/desktop \
           plugin \
           lib/deploy* \
           lib/*javafx* \
           lib/*jfx* \
           lib/amd64/libdecora_sse.so \
           lib/amd64/libprism_*.so \
           lib/amd64/libfxplugins.so \
           lib/amd64/libglass.so \
           lib/amd64/libgstreamer-lite.so \
           lib/amd64/libjavafx*.so \
           lib/amd64/libjfx*.so

[root@node1 jre1.8.0_251]# ll
总用量 4
drwxr-xr-x  2 10143 10143  208 7月   9 13:56 bin
drwxr-xr-x 13 10143 10143 4096 7月   9 13:56 lib
drwxr-xr-x  4 10143 10143   47 3月  12 14:33 man
  1. 重新打包
[root@node1 jre1.8.0_251]# tar zcvf jre8.tar.gz *
[root@node1 jre1.8.0_251]# ll
总用量 43896
drwxr-xr-x  2 10143 10143      208 7月   9 13:56 bin
-rw-r--r--  1 root  root  44942683 7月   9 14:04 jre8.tar.gz
drwxr-xr-x 13 10143 10143     4096 7月   9 13:56 lib
drwxr-xr-x  4 10143 10143       47 3月  12 14:33 man
  1. 直接在当前目录下创建Dockerfile
[root@node1 jre1.8.0_251]# vim Dockerfile

编写Dockerfile

FROM docker.io/jeanblanchard/alpine-glibc
MAINTAINER wuzhiyong
ADD jre8.tar.gz /usr/java/jdk/
ENV JAVA_HOME /usr/java/jdk
ENV PATH ${PATH}:${JAVA_HOME}/bin
WORKDIR /opt
  1. 生成镜像
# 生成镜像
[root@node1 jre1.8.0_251]# docker build -t wuzhiyong/java8.0_251 .
Sending build context to Docker daemon  161.1MB
Step 1/6 : FROM docker.io/jeanblanchard/alpine-glibc
 ---> c1bfe6541128
Step 2/6 : MAINTAINER wuzhiyong
 ---> Using cache
 ---> 5e4699308c35
Step 3/6 : ADD jre8.tar.gz /usr/java/jdk/
 ---> 8b6b66ec0f68
Step 4/6 : ENV JAVA_HOME /usr/java/jdk
 ---> Running in 26f286188aa8
Removing intermediate container 26f286188aa8
 ---> 7d1501133f4c
Step 5/6 : ENV PATH ${PATH}:${JAVA_HOME}/bin
 ---> Running in 418be370f8b9
Removing intermediate container 418be370f8b9
 ---> 8a920d8285df
Step 6/6 : WORKDIR /opt
 ---> Running in 107687a0007d
Removing intermediate container 107687a0007d
 ---> e7a62387e585
Successfully built e7a62387e585
Successfully tagged wuzhiyong/java8.0_251:latest
#查看镜像大小
[root@node1 jre1.8.0_251]# docker images | grep java8
wuzhiyong/java8.0_251                                            latest                    e7a62387e585        15 seconds ago      133MB
  1. 上传到镜像仓库,可以下载使用
docker pull hub.deri.org.cn/library/oracle_jdk_1.8_251:latest

引入依赖

<!-- 注意版本号,测试2.0.3版本有严重问题,启动失败 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

注册邮箱

  • 163,126,qq都行,这边测试126邮箱;
  • 开启IMAP/SMTP服务;
  • 获取授权密码,注意保存.

配置application.yaml

spring:
  mail:
    # 注册的邮箱
    username: xxxxxx@126.com
    # 密码为授权码
    password: XXXXXXXXXXXXXXX
    # smtp服务器地址
    host: smtp.126.com
    # 安全相关配置,非必须
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

测试发送

@Service
public class MailService {
    // 这个在IDEA中会提示没有bean,注入失败,不用管~
    @Autowired
    JavaMailSender mailSender;

    public void send(){
        // 普通文本邮件
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        //邮件发送方,需要写完整邮箱地址
        simpleMailMessage.setFrom("XXXXX@126.com");
        //邮件接收方邮箱
        simpleMailMessage.setTo("1154365135@qq.com");
        //邮件标题
        simpleMailMessage.setSubject("测试主题~~");
        //邮件内容
        simpleMailMessage.setText("测试内容~~");
        //发送邮件
        mailSender.send(simpleMailMessage);
    }

    public void sendHtml() throws MessagingException {
        // html邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        //邮件发送方
        helper.setFrom("authservice@126.com");
        //邮件接收方邮箱
        helper.setTo("1154365135@qq.com");
        //邮件标题
        helper.setSubject("测试HTML~~");
        //邮件内容
        helper.setText("<html>\n" +
                "<head>\n" +
                "<meta charset=\"utf-8\">\n" +
                "<title>菜鸟教程(runoob.com)</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <h1>我的第一个标题</h1>\n" +
                "    <p style=\"color: blue;\">我的第一个段落。</p>\n" +
                "</body>\n" +
                "</html>", true);
        //发送邮件
        mailSender.send(mimeMessage);
    }

        //附件邮件, 未测试
    public void sendAttachmentMail(String to,String subject,String content,String filePath) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content,true);
        helper.setFrom(form);
        FileSystemResource file=new FileSystemResource(new File(filePath));
        String fileName=file.getFilename();
        helper.addAttachment(fileName,file);
        //helper.addAttachment(fileName+"02",file);  如果是多个附件的话,可以这样写。但是开发中一般都是把filepath做成一个数组,这样在这里遍历就可以了
        //helper.addAttachment(fileName+"03",file);

        mailSender.send(mimeMessage);
    }

    //图片邮件,未测试
    public void sendInlineResourceMail(String to,String subject,String content,String rscPath,String rscId) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content,true);
        helper.setFrom(form);
        FileSystemResource file=new FileSystemResource(new File(rscPath));
        helper.addInline(rscId,file);

        mailSender.send(mimeMessage);
    }
}

验证码EasyCaptcha介绍

使用

<dependency>
    <groupId>com.github.whvcse</groupId>
    <artifactId>easy-captcha</artifactId>
    <version>1.6.2</version>
</dependency>

也许下载不下来,可以直接下载 easy-captcha.jar 包.

使用下面的命令可以将jar包安装到本地仓库.

mvn install:install-file -Dfile=D:/easy-captcha.jar -DgroupId=com.github.whvcse -DartifactId=easy-captcha -Dversion=1.6.2 -Dpackaging=jar

开发

// PNG格式 设置长宽和验证码长度
SpecCaptcha captcha = new SpecCaptcha(180, 40, 6);
// 设置验证码字符类型,数字/大小写字母
captcha.setCharType(Captcha.TYPE_ONLY_NUMBER);

// GIF格式 设置长宽和验证码长度
GifCaptcha captcha = new GifCaptcha(180, 48, 6);

// 中文验证码 设置长宽和验证码长度
ChineseCaptcha captcha = new ChineseCaptcha(180, 48);
// 设置字体, 设置默认字体Captcha.FONT_1...好像有问题,英文可以使用默认字体
captcha.setFont(new Font("楷体", Font.PLAIN, 28));

// 使用算术验证码,设置长宽和几位数运算
ArithmeticCaptcha captcha = new ArithmeticCaptcha(180, 48, 2);
// 获取运算的公式:3+2=?
captcha.getArithmeticString()

// 通用方法
captcha.text();  // 获取验证码的字符
captcha.textChar();  // 获取验证码的字符数组

// 验证码保存到文件
FileOutputStream outputStream = new FileOutputStream(new File("C:/captcha.png"))
captcha.out(outputStream);  // 输出验证码

// 输出base64编码, 返回给前端需要用到
specCaptcha.toBase64();

// 如果不想要base64的头部data:image/png;base64,
specCaptcha.toBase64("");  // 加一个空的参数即可

测试

已知问题

同样的程序本地测试没有问题,部署到docker上测试出现问题.

  • 解决办法: 不要使用openjdk做基础镜像,采用oracle jdk.
  • 这边提供一个能用的: docker pull hub.deri.org.cn/library/oracle_jdk_1.8_131:latest

1955年,卡普耶卡(D.R.Kaprekar)研究了对四位数的一种变换:任给出四位数k0,用它的四个数字由大到小重新排列成一个四位数m,再减去它的反序数rev(m),得出数k1=m-rev(m),然后,继续对k1重复上述变换,得数k2.如此进行下去,卡普耶卡发现,无论k0是多大的四位数,只要四个数字不全相同,最多进行7次上述变换,就会出现四位数6174。因此这项研究在国际数学界又被称为“马丁猜想—6174问题”。

有趣的数字6174

  • 随机生成四个不完全一样的数字(0000,1111,2222,等排除);
  • 四个数字组成一个最大的数 和 一个最小的数,如2,5,7,3组成的最大的数7532,最小的数2357;
  • 最大的数 - 最小的数,如果不等于6174,就按照上一步将差值重新组成一个最大的数 和 一个最小的数;
  • 最后一定有一次能得到差值为6174.俗称数字黑洞.

JAVA实现

public class Test6174 {
    public static void main(String[] args) throws InterruptedException {
        // 无线循环测试
        while (true) {
            // 随机生成四个数字,考虑到出现四个一样的概率非常低 没有处理
            List<Integer> meta = new ArrayList<>();
            for (int i = 0; i < 4; i++) {
                meta.add(new Random().nextInt(10));
            }
            System.out.print("原始数字:" + meta);
            int result = 0, count = 0;
            while (result != 6174) {
                // 获取四个数字组合的最大的数 和 最小的数
                int max = getMax(meta);
                int min = getMin(meta);
                result = Math.abs(max - min);
                count++;
                // 数字为啥是6174?
                if (result == 6174) {
                    System.out.println(",次数:" + count);
                }
                meta = getMeta(result);
            }
            Thread.sleep(1000);
        }
    }

    public static int getMax(List<Integer> meta) {
        List<Integer> tmp = meta.stream().sorted().collect(Collectors.toList());
        return tmp.get(0) * 1000 + tmp.get(1) * 100 + tmp.get(2) * 10 + tmp.get(3);
    }

    public static int getMin(List<Integer> meta) {
        List<Integer> tmp = meta.stream().sorted().collect(Collectors.toList());
        return tmp.get(0) + tmp.get(1) * 10 + tmp.get(2) * 100 + tmp.get(3) * 1000;
    }

    public static List<Integer> getMeta(int num) {
        List<Integer> tmp = new ArrayList<>();
        tmp.add(num / 1000 % 10);
        tmp.add(num / 100 % 10);
        tmp.add(num / 10 % 10);
        tmp.add(num % 10);
        return tmp;
    }
}

同样的黑洞数字还有很多哦

不如写个程序来找出不同位数的黑洞数字吧

public class TestN {
    public static void main(String[] args) throws InterruptedException {
        // 输入几位数就是找几位数的黑洞数字
        int digits = 5;
        List<Integer> meta = new ArrayList<>();
        for (int i = 0; i < digits; i++) {
            meta.add(new Random().nextInt(10));
        }
        if (getMax(meta) - getMin(meta) == 0){
            System.out.println("数字完全一样,不符合要求");
            System.exit(0);
        }
        System.out.println("原始数字:" + meta);
        int result = 0;
        while (true) {
            int max = getMax(meta);
            int min = getMin(meta);
            result = Math.abs(max - min);
            meta = getMeta(result, digits);
            System.out.println(result);
        }
    }

    // 获取数字组合的最大数
    public static int getMax(List<Integer> meta) {
        List<Integer> tmp = meta.stream().sorted().collect(Collectors.toList());
        double result = 0;
        for (int i = 0; i < tmp.size(); i++) {
            result = result + tmp.get(i) * (Math.pow(10.0, (double) (i)));
        }
        return (int) result;
    }

    // 获取数字组合的最小数
    public static int getMin(List<Integer> meta) {
        List<Integer> tmp = meta.stream().sorted().collect(Collectors.toList());
        double result = 0;
        for (int i = 0; i < tmp.size(); i++) {
            result = result + tmp.get(i) * (Math.pow(10.0, (double) (tmp.size() - i - 1)));
        }
        return (int) result;
    }

    // 获取数的各位数
    public static List<Integer> getMeta(int num, int c) {
        List<Integer> tmp = new ArrayList<>();
        for (int i = 0; i < c; i++) {
            tmp.add(num / ((int) Math.pow(10.0, i)) % 10);
        }
        return tmp;
    }
}

如上程序测试运行:

digits(位数) 黑洞数(个) 结果
1 - -
2 5 9,81,63,27,45
3 1 495
4 1 6174
5 4 71973,83952,74943,62964
6 7 840852,860832,862632,642654,...
7 8 9529641,8719722,8649432,7519743,...
8 3 64308654,83208762,86526432
9 14 954197541,883098612,976494321,...