diff --git a/README.md b/README.md index f4ec9e9..0ed84f9 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,7 @@ utils.response.VoResult ### 根据实体类属性获取getAndSet方法 - utils.MethodGetAndSet 可能有bug,待测试 \ No newline at end of file + utils.MethodGetAndSet 可能有bug,待测试 + +### redis工具 + utils.redis.RedisCacheUtils \ No newline at end of file diff --git a/pom.xml b/pom.xml index e5b589c..8653097 100644 --- a/pom.xml +++ b/pom.xml @@ -21,19 +21,21 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-redis + com.alibaba fastjson 2.0.26 - cn.hutool hutool-all 5.8.16 - org.projectlombok lombok diff --git a/src/main/java/utils/Base64Utils.java b/src/main/java/utils/Base64Utils.java new file mode 100644 index 0000000..d63b101 --- /dev/null +++ b/src/main/java/utils/Base64Utils.java @@ -0,0 +1,112 @@ +package utils; + +import org.apache.commons.codec.binary.Base64; + +import java.io.*; + +public class Base64Utils { + + /** + * BASE64编码解码工具包 + * 依赖javabase64-1.3.1.jar + * + * @date 2012-5-19 + * @version 1.0 + */ + + /** + * 文件读取缓冲区大小 + */ + private static final int CACHE_SIZE = 1024; + + /** + * BASE64字符串解码为二进制数据 + * @param base64 + * @throws Exception + */ + public static byte[] decode(String base64) throws Exception { + return Base64.decodeBase64(base64.getBytes()); + // return Base64.decode(base64.getBytes()); + } + + /** + * 二进制数据编码为BASE64字符串 + * @param bytes + * @throws Exception + */ + public static String encode(byte[] bytes) throws Exception { + return new String(Base64.encodeBase64(bytes)); + // return new String(Base64.encode(bytes)); + } + + /** + * 将文件编码为BASE64字符串 + * 大文件慎用,可能会导致内存溢出 + * + * @param filePath 文件绝对路径 + * @throws Exception + */ + public static String encodeFile(String filePath) throws Exception { + byte[] bytes = fileToByte(filePath); + return encode(bytes); + } + + /** + * BASE64字符串转回文件 + * @param filePath 文件绝对路径 + * @param base64 编码字符串 + * @throws Exception + */ + public static void decodeToFile(String filePath, String base64) throws Exception { + byte[] bytes = decode(base64); + byteArrayToFile(bytes, filePath); + } + + /** + * 文件转换为二进制数组 + * @param filePath 文件路径 + * @return + * @throws Exception + */ + public static byte[] fileToByte(String filePath) throws Exception { + byte[] data = new byte[0]; + File file = new File(filePath); + if (file.exists()) { + FileInputStream in = new FileInputStream(file); + ByteArrayOutputStream out = new ByteArrayOutputStream(2048); + byte[] cache = new byte[CACHE_SIZE]; + int nRead = 0; + while ((nRead = in.read(cache)) != -1) { + out.write(cache, 0, nRead); + out.flush(); + } + out.close(); + in.close(); + data = out.toByteArray(); + } + return data; + } + + /** + * 二进制数据写文件 + * @param bytes 二进制数据 + * @param filePath 文件生成目录 + */ + public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { + InputStream in = new ByteArrayInputStream(bytes); + File destFile = new File(filePath); + if (!destFile.getParentFile().exists()) { + destFile.getParentFile().mkdirs(); + } + destFile.createNewFile(); + OutputStream out = new FileOutputStream(destFile); + byte[] cache = new byte[CACHE_SIZE]; + int nRead = 0; + while ((nRead = in.read(cache)) != -1) { + out.write(cache, 0, nRead); + out.flush(); + } + out.close(); + in.close(); + } +} diff --git a/src/main/java/utils/redis/RedisCacheUtils.java b/src/main/java/utils/redis/RedisCacheUtils.java new file mode 100644 index 0000000..b0f335c --- /dev/null +++ b/src/main/java/utils/redis/RedisCacheUtils.java @@ -0,0 +1,129 @@ +package utils.redis; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * @author fuhouyin + * @time 2023/4/11 9:30 + */ +@Component +public class RedisCacheUtils { + + @Autowired + private RedisTemplateProvider redisTemplateProvider; + private final StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + + public void setValue(String key, Object value){ + RedisTemplate redisTemplate = getRedisTemplate(); + redisTemplate.opsForValue().set(key,value); + } + + public void setValue(String key, Object value,Long timeout, TimeUnit timeUnit){ + RedisTemplate redisTemplate = getRedisTemplate(); + redisTemplate.opsForValue().set(key,value,timeout, timeUnit); + } + + public Object getValue(String key){ + RedisTemplate redisTemplate = getRedisTemplate(); + return redisTemplate.opsForValue().get(key); + } + + public String getCacheKey(Object... keys) { + return StringUtils.join(Arrays.asList(keys), ":"); + } + + public Long hashIncrement(String key, String hashKey){ + RedisTemplate redisTemplate = getRedisTemplate(); + Long increment = redisTemplate.opsForHash().increment(key, hashKey, 1); + return increment; + } + + public boolean hasKey(String key){ + return getRedisTemplate().hasKey(key); + } + + public boolean delKey(String key){ + if (StringUtils.isEmpty(key)) { + return Boolean.FALSE; + } + RedisTemplate redisTemplate = getRedisTemplate(); + if (redisTemplate.hasKey(key)) { + return redisTemplate.delete(key); + } + return Boolean.TRUE; + } + + public boolean hashHasKey(String key, String hashKey){ + return getRedisTemplate().opsForHash().hasKey(key, hashKey); + } + + public Object hashGet(String key, String hashKey){ + return getRedisTemplate().opsForHash().get(key, hashKey); + } + + private RedisTemplate getRedisTemplate(){ + RedisTemplate template = redisTemplateProvider.getTemplate(stringRedisSerializer); + return template; + } + + public void hashPut(String key,String hashKey, String value){ + getRedisTemplate().opsForHash().put(key,hashKey,value); + } + + public void hashPutIfAbsent(String key, String hashKey, String value) { + getRedisTemplate().opsForHash().putIfAbsent(key,hashKey,value); + } + + public Boolean expire(String key, long time, TimeUnit timeUnit){ + Boolean result = getRedisTemplate().expire(key, time, timeUnit); + return result; + } + + public Boolean lock(String key){ + return getRedisTemplate().opsForValue().setIfAbsent(key, BigDecimal.ZERO.intValue()); + } + + public Boolean tryLock(String key){ + try { + for (int i = 0; i < 3; i++) { + if (lock(key)) { + return Boolean.TRUE; + } + Thread.sleep(100L); + } + } catch (InterruptedException e) { + return Boolean.FALSE; + } + return Boolean.FALSE; + } + + public void unlock(String key){ + getRedisTemplate().delete(key); + } + + + public Long increment(String key, Long delta){ + return getRedisTemplate().opsForValue().increment(key,delta); + } + + public Boolean setIfAbsent(String key, Object value){ + return getRedisTemplate().opsForValue().setIfAbsent(key,value); + } + + public Set keys(String keyPattern) { + return getRedisTemplate().keys(keyPattern); + } + + public Object getAndSet(String key, Object value){ + return getRedisTemplate().opsForValue().getAndSet(key,value); + } +} diff --git a/src/main/java/utils/redis/RedisTemplateProvider.java b/src/main/java/utils/redis/RedisTemplateProvider.java new file mode 100644 index 0000000..0811b35 --- /dev/null +++ b/src/main/java/utils/redis/RedisTemplateProvider.java @@ -0,0 +1,14 @@ +package utils.redis; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; + +/** + * @author fuhouyin + * @time 2023/4/11 9:30 + */ +public interface RedisTemplateProvider { + RedisTemplate getTemplate(); + + RedisTemplate getTemplate(RedisSerializer valueSerializer); +} diff --git a/src/main/java/utils/redis/RedisTemplateProviderImpl.java b/src/main/java/utils/redis/RedisTemplateProviderImpl.java new file mode 100644 index 0000000..e2e554c --- /dev/null +++ b/src/main/java/utils/redis/RedisTemplateProviderImpl.java @@ -0,0 +1,95 @@ +package utils.redis; + +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * @author fuhouyin + * @time 2023/4/11 9:30 + */ +@Component +public class RedisTemplateProviderImpl implements RedisTemplateProvider { + public static final RedisSerializer JDK_SERIALIZER = new JdkSerializationRedisSerializer(); + public static final RedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); + private final Map> redisTemplateMap = new HashMap(); + private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private final Lock r; + private final Lock w; + private final RedisConnectionFactory redisStoreConnectionFactory; + + public RedisTemplateProviderImpl(RedisConnectionFactory redisStoreConnectionFactory) { + this.r = this.rwl.readLock(); + this.w = this.rwl.writeLock(); + this.redisStoreConnectionFactory = redisStoreConnectionFactory; + } + + public RedisTemplate getTemplate() { + return this.getTemplate(STRING_SERIALIZER); + } + + public RedisTemplate getTemplate(RedisSerializer valueSerializer) { + return this.getTemplate(STRING_SERIALIZER, valueSerializer); + } + + private RedisTemplate getTemplate(RedisSerializer keySerializer, RedisSerializer valueSerializer) { + String cacheKey = this.getTemplateCacheKey(keySerializer, valueSerializer); + + try { + this.r.lock(); + RedisTemplate template = (RedisTemplate)this.redisTemplateMap.get(cacheKey); + if (template != null) { + RedisTemplate var5 = template; + return var5; + } + } finally { + this.r.unlock(); + } + + return this.createAndPut(keySerializer, valueSerializer, cacheKey); + } + + private RedisTemplate createAndPut(RedisSerializer keySerializer, RedisSerializer valueSerializer, String cacheKey) { + RedisTemplate var5; + try { + this.w.lock(); + RedisTemplate template = (RedisTemplate)this.redisTemplateMap.get(cacheKey); + if (template == null) { + template = this.createRedisTemplate(keySerializer, valueSerializer); + this.redisTemplateMap.put(cacheKey, template); + } + + var5 = template; + } finally { + this.w.unlock(); + } + + return var5; + } + + private RedisTemplate createRedisTemplate(RedisSerializer keySerializer, RedisSerializer valueSerializer) { + RedisTemplate template = new RedisTemplate(); + template.setKeySerializer(keySerializer); + template.setHashKeySerializer(keySerializer); + template.setHashValueSerializer(valueSerializer); + template.setValueSerializer(valueSerializer); + template.setConnectionFactory(this.redisStoreConnectionFactory); + template.afterPropertiesSet(); + return template; + } + + private String getTemplateCacheKey(RedisSerializer keySerializer, RedisSerializer valueSerializer) { + Assert.notNull(keySerializer, "keySerializer should not null"); + Assert.notNull(valueSerializer, "valueSerializer should not null"); + return keySerializer.getClass().getName() + "-" + valueSerializer.getClass().getName(); + } +}