RuoYi-Vue 前后端分离版代码浅析-生成验证码

774 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

本节介绍RuoYi-Vue的ruoyi-admin模块中的生成验证码模块CaptchaController 部分的代码

使用的第三方包

我们可以看到使用的直接就是kaptcha这个生成验证码的包。

<dependency>
  <groupId>com.github.penggle</groupId>
  <artifactId>kaptcha</artifactId>
  <version>2.3.2</version>
</dependency>

这个kaptcha的各种属性都可以自定义,非常方便。

生成验证码的流程

需要注意这个控制器中有两个验证码的生成器,

    @Resource(name = "captchaProducer")
    private Producer captchaProducer;

    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

通过配置的ruoyi.captchaType

    // 验证码类型
    @Value("${ruoyi.captchaType}")
    private String captchaType;

来决定是使用哪个

FastByteArrayOutputStream

这里接收image的数据,使用的是 FastByteArrayOutputStream,是org.springframework.util包中的数据,相较java.io中的ByteArrayOutputStream,主要是两者的实现方式不同。

FastByteArrayOutputStreamByteArrayOutputStream 的快速替代方案。 请注意,和ResizableByteArrayOutputStream 不同,本类不是 ByteArrayOutputStream的扩展。 与 ByteArrayOutputStream 不同,此实现由 byte[] 的 LinkedList 支持,而不是 1 个不断调整大小的 byte[]。 它在扩展时不会复制缓冲区。 初始缓冲区仅在首次写入流时创建。 如果使用 writeTo(OutputStream) 方法提取内部缓冲区的内容,则也不会复制内部缓冲区。

ByteArrayOutputStream内部实现为一个数组每一次扩容需要重新分配空间并将数据复制到新数组中,看下面的代码中的Arrays.copyOf可以得出结论。

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = buf.length;
        int newCapacity = oldCapacity << 1;
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        buf = Arrays.copyOf(buf, newCapacity);
    }

而FastByteArrayOutputStream的则是用

private void addBuffer(int minCapacity) {
        if (this.buffers.peekLast() != null) {
            this.alreadyBufferedSize += this.index;
            this.index = 0;
        }

        if (this.nextBlockSize < minCapacity) {
            this.nextBlockSize = nextPowerOf2(minCapacity);
        }

        this.buffers.add(new byte[this.nextBlockSize]);
        this.nextBlockSize *= 2;
    }

每次都是新加new byte[] 到 private final Deque<byte[]> buffers; 里面的,一个每次都要重新copy全部,一个只是在buffers对象中添加,很明显FastByteArrayOutputStream更好一些。
docs.spring.io/spring-fram…