xingyuv / captcha-plus

行为验证码(滑动拼图、点选文字),前后端(java)交互,包含vue/h5/Android/IOS/flutter/uni-app/react/php/go/微信小程序的源码和实现
http://admin.x-surge.com/
Apache License 2.0
108 stars 23 forks source link

CaptchaCacheServiceRedisImpl自动注入redisService的问题 #7

Open pengsasai opened 9 months ago

pengsasai commented 9 months ago

不要使用自动注入,而是用private static final StringRedisTemplate stringRedisTemplate = SpringContextUtils .getBean("stringRedisTemplate", StringRedisTemplate.class);注入的方式,否则请求验证码会报npe

wenkesong-li commented 4 weeks ago

import com.xingyuv.captcha.properties.AjCaptchaProperties;
import com.xingyuv.captcha.service.CaptchaCacheService;
import com.xingyuv.captcha.service.impl.CaptchaServiceFactory;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 基于 Redis 实现验证码的存储
 *
 * @author wenkesong
 */
@Slf4j
@Configuration
@ConditionalOnProperty(name = AjCaptchaProperties.PREFIX + ".cache-type", havingValue = "redis")
public class RedisCaptchaServiceImpl implements CaptchaCacheService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String type() {
        return "redis";
    }

    @Override
    public void set(String key, String value, long expiresInSeconds) {
        stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
    }

    @Override
    public boolean exists(String key) {
        return Boolean.TRUE.equals(stringRedisTemplate.hasKey(key));
    }

    @Override
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    @Override
    public Long increment(String key, long val) {
        return stringRedisTemplate.opsForValue().increment(key, val);
    }

    @Bean
    public CaptchaCacheService initRedisCaptchaCache() {
        log.info("初始化Redis验证码.....");
        Map<String, CaptchaCacheService> cacheService = CaptchaServiceFactory.cacheService;
        synchronized (cacheService) {
            cacheService.put("redis", this);
        }
        return this;
    }

}
jymxx commented 1 week ago

import com.xingyuv.captcha.properties.AjCaptchaProperties;
import com.xingyuv.captcha.service.CaptchaCacheService;
import com.xingyuv.captcha.service.impl.CaptchaServiceFactory;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 基于 Redis 实现验证码的存储
 *
 * @author wenkesong
 */
@Slf4j
@Configuration
@ConditionalOnProperty(name = AjCaptchaProperties.PREFIX + ".cache-type", havingValue = "redis")
public class RedisCaptchaServiceImpl implements CaptchaCacheService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public String type() {
        return "redis";
    }

    @Override
    public void set(String key, String value, long expiresInSeconds) {
        stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
    }

    @Override
    public boolean exists(String key) {
        return Boolean.TRUE.equals(stringRedisTemplate.hasKey(key));
    }

    @Override
    public void delete(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    @Override
    public Long increment(String key, long val) {
        return stringRedisTemplate.opsForValue().increment(key, val);
    }

    @Bean
    public CaptchaCacheService initRedisCaptchaCache() {
        log.info("初始化Redis验证码.....");
        Map<String, CaptchaCacheService> cacheService = CaptchaServiceFactory.cacheService;
        synchronized (cacheService) {
            cacheService.put("redis", this);
        }
        return this;
    }

}

默认设置下可以使用,但在开启接口请求次数限制时,captcha-plus的加载优先级总是比我的代码要高,导致limitHandler = new FrequencyLimitHandler.DefaultLimitHandler(config, getCacheService(cacheType));提前去获取了空的bean然后报错