From 9a6d2687ca89b3d781efba6ed400db3f8a27bb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E7=88=B1=E6=9C=89=E6=83=85?= Date: Mon, 25 Apr 2022 11:01:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/CacheImageCaptchaGenerator.java | 65 ++++++++++++++----- .../StandardRotateCaptchaGeneratorTest.java | 12 +++- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java index 4c9318a..0f33eef 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java @@ -25,18 +25,20 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { protected final ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("slider-captcha-queue")); protected Map> queueMap = new ConcurrentHashMap<>(8); protected Map posMap = new ConcurrentHashMap<>(8); + protected Map lastUpdateMap = new ConcurrentHashMap<>(8); protected ImageCaptchaGenerator target; protected int size; /** 等待时间,一般报错或者拉取为空时会休眠一段时间再试. */ protected int waitTime = 1000; /** 调度器检查缓存的间隔时间. */ - protected int period = 100; - + protected int period = 5000; + /** 10天内没有任何操作就删除已缓存的数据. */ + protected long expireTime = TimeUnit.DAYS.toMillis(10); @Getter @Setter protected boolean requiredGetCaptcha = true; - public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size) { + public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size) { this.target = target; this.size = size; } @@ -48,6 +50,14 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { this.period = period; } + public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size, int waitTime, int period, Long expireTime) { + this.target = target; + this.size = size; + this.waitTime = waitTime; + this.period = period; + this.expireTime = expireTime; + } + /** * 记的初始化调度器 */ @@ -62,6 +72,7 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { queueMap.forEach((k, queue) -> { try { AtomicInteger pos = posMap.computeIfAbsent(k, k1 -> new AtomicInteger(0)); + int addCount = 0; while (pos.get() < this.size) { if (pos.get() >= size) { return; @@ -69,6 +80,7 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { ImageCaptchaInfo slideImageInfo = target.generateCaptchaImage(k); if (slideImageInfo != null) { boolean addStatus = queue.offer(slideImageInfo); + addCount++; if (addStatus) { // 添加记录 pos.incrementAndGet(); @@ -77,11 +89,22 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { sleep(); } } + if (addCount == 0) { + // 没有添加,检测最新更新时间 如果时间过长,直接清除数据 + Long lastUpdate = lastUpdateMap.get(k); + if (lastUpdate != null && System.currentTimeMillis() - lastUpdate > expireTime) { + queueMap.remove(k); + posMap.remove(k); + lastUpdateMap.remove(k); + } + } } catch (Exception e) { // cache所有 log.error("缓存队列扫描时出错, ex", e); // 删掉它 queueMap.remove(k); + posMap.remove(k); + lastUpdateMap.remove(k); // 休眠 sleep(); } @@ -107,21 +130,31 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator { @SneakyThrows public ImageCaptchaInfo generateCaptchaImage(GenerateParam generateParam, boolean requiredGetCaptcha) { - ConcurrentLinkedQueue queue = queueMap.computeIfAbsent(generateParam, g -> new ConcurrentLinkedQueue<>()); - ImageCaptchaInfo poll = queue.poll(); - if (poll == null && requiredGetCaptcha) { - log.warn("滑块验证码缓存不足, genParam:{}", generateParam); - // 如果池内没数据, 则直接生成 - return target.generateCaptchaImage(generateParam); - } - // 减1 - if (poll != null) { - AtomicInteger pos = posMap.get(generateParam); - if (pos != null) { - pos.decrementAndGet(); + ConcurrentLinkedQueue queue = queueMap.get(generateParam); + ImageCaptchaInfo captchaInfo = null; + if (queue != null) { + captchaInfo = queue.poll(); + if (captchaInfo == null) { + log.warn("滑块验证码缓存不足, genParam:{}", generateParam); + }else { + AtomicInteger pos = posMap.get(generateParam); + if (pos != null) { + pos.decrementAndGet(); + } } + }else { + queueMap.putIfAbsent(generateParam, new ConcurrentLinkedQueue<>()); + posMap.putIfAbsent(generateParam, new AtomicInteger(0)); } - return poll; + if (captchaInfo == null && requiredGetCaptcha) { + // 直接生成 不走缓存 + captchaInfo = target.generateCaptchaImage(generateParam); + } + if (captchaInfo != null){ + // 记录最新时间 + lastUpdateMap.put(generateParam, System.currentTimeMillis()); + } + return captchaInfo; } @Override diff --git a/src/main/test/java/example/StandardRotateCaptchaGeneratorTest.java b/src/main/test/java/example/StandardRotateCaptchaGeneratorTest.java index e882a8f..d310386 100644 --- a/src/main/test/java/example/StandardRotateCaptchaGeneratorTest.java +++ b/src/main/test/java/example/StandardRotateCaptchaGeneratorTest.java @@ -1,17 +1,21 @@ package example; +import cloud.tianai.captcha.template.slider.generator.ImageCaptchaGenerator; import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo; import cloud.tianai.captcha.template.slider.generator.common.model.dto.RotateImageCaptchaInfo; +import cloud.tianai.captcha.template.slider.generator.impl.CacheImageCaptchaGenerator; import cloud.tianai.captcha.template.slider.generator.impl.StandardRotateImageCaptchaGenerator; import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager; import cloud.tianai.captcha.template.slider.resource.ResourceStore; import cloud.tianai.captcha.template.slider.resource.impl.DefaultImageCaptchaResourceManager; import cloud.tianai.captcha.template.slider.resource.impl.DefaultResourceStore; +import java.util.concurrent.TimeUnit; + public class StandardRotateCaptchaGeneratorTest { - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { ResourceStore resourceStore = new DefaultResourceStore(); // Map template = new HashMap<>(); // template.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource("file", "C:\\Users\\Thinkpad\\Desktop\\a.png")); @@ -22,11 +26,15 @@ public class StandardRotateCaptchaGeneratorTest { ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager(resourceStore); - StandardRotateImageCaptchaGenerator standardRotateImageCaptchaGenerator = new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, true); + CacheImageCaptchaGenerator standardRotateImageCaptchaGenerator = new CacheImageCaptchaGenerator(new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, true), + 20, 1000, 100, TimeUnit.MINUTES.toMillis(3)); + standardRotateImageCaptchaGenerator.initSchedule(); ImageCaptchaInfo imageCaptchaInfo = standardRotateImageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.ROTATE); System.out.println("backgroundImage:" + imageCaptchaInfo.getBackgroundImage()); System.out.println("sliderImage:" + imageCaptchaInfo.getSliderImage()); System.out.println(((RotateImageCaptchaInfo)imageCaptchaInfo).getDegree()); + TimeUnit.DAYS.sleep(1); + } }