Redis工具类 一篇就足够(Java版本)

前言

之前一直在找一些redis相关的操作类/工具类相关的文章,奈何各种参差不齐,不甚满意。于是,就自己动手来写一个。

基础操作类,这个是最最最基本的

RedisUtils.java 以下直接附上代码(奇怪,为啥我的代码不是黑底的,总觉得黑底的比较帅)
思维导图啥的,我也不说了,毕竟真的认真看,真的需要的人会自己仔细看,这代码也就看看就懂。(可能我这里的hashObject的保存有点绕,要多看下)。那我这里就简单说下,HashObject对应的java类,就是IRedisObject (里面只有一个返回string的redisKey()的抽象方法),保存的时候,在redis中产生一个数值的地址(address),然后以这个地址作为一个key来存放。实在看不懂的,就留言或者加我(QQ 420713155 )


import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

import javax.persistence.Column;
import javax.persistence.Table;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * redis操作
 *
 * @Autor Tricky
 * @Date 2020-05-27 15:29:19
 */
public abstract class RedisUtils {
    
    
	/**
	 * 对象地址的key存储
	 */
	private static final String OBJECT_ADDR_PATTERN = "ADDR_%s";
	private static final String OBJECT_KEY_PATTERN = "OBJ_%s_%s";
	private static final String ADDR_INCREASE_KEY = "INCR_ADDRESS";
	private static final String LOCK_KEY = "LOCK_%s_%s";
	private static final String SET_KEY = "SET_%s";
	private static Logger LOGGER = LoggerFactory.getLogger(RedisUtils.class);
	private static ConcurrentHashMap<Class<?>, String> TABLE_FLAG_MAP = new ConcurrentHashMap<>();

	/**
	 * 获取自增长值
	 *
	 * @param increaseKey key
	 * @return
	 */
	public static Long getAndIncr(RedisTemplate template, String increaseKey) {
    
    
		RedisAtomicLong entityIdCounter = new RedisAtomicLong(increaseKey, template.getConnectionFactory());
		Long increment = entityIdCounter.incrementAndGet();
		return increment;
	}

	/**
	 * 获取对应的tableFlag
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public static <T extends IRedisObject> String getTableFlag(Class<T> clazz) {
    
    
		return TABLE_FLAG_MAP.computeIfAbsent(clazz, (k) -> {
    
    
			RedisTable anno = k.getAnnotation(RedisTable.class);
			if (anno == null) {
    
    
				Table tAnno = k.getAnnotation(Table.class);
				if (tAnno == null) {
    
    
					throw new IllegalArgumentException("Redis对象必须包含注解 " + RedisTable.class.getName() + " or " + Column.class.getName());
				}
				return tAnno.name();
			}
			return anno.name();
		});
	}

	/**
	 * 相当于关系数据库的表名
	 *
	 * @param tableFlag
	 * @return
	 */
	private static String getTableKey(String tableFlag) {
    
    
		if (StringUtils.isEmpty(tableFlag)) {
    
    
			throw new IllegalArgumentException("传入的参数不可为空值");
		}
		return String.format(OBJECT_ADDR_PATTERN, tableFlag);
	}

	/**
	 * 加入地址
	 *
	 * @param template
	 * @param tableKey
	 * @param objKey
	 * @param value
	 * @return
	 */
	private static boolean addAddress(RedisTemplate template, String tableKey, String objKey, String value) {
    
    
		return template.opsForHash().putIfAbsent(tableKey, objKey, value);
	}

	private static String getAddress(RedisTemplate template, String tableKey, String objKey) {
    
    
		return (String) template.opsForHash().get(tableKey, objKey);
	}

	/**
	 * 获取地址的key
	 *
	 * @param tableFlag
	 * @param redisKey
	 * @return
	 */
	private static String getObjectKey(String tableFlag, String redisKey) {
    
    
		if (StringUtils.isEmpty(tableFlag)) {
    
    
			throw new IllegalArgumentException("传入的参数tableFlag不可为空值");
		}
		if (StringUtils.isEmpty(redisKey)) {
    
    
			throw new IllegalArgumentException("传入的参数redisKey不可为空值");
		}
		return String.format(OBJECT_KEY_PATTERN, tableFlag, redisKey);
	}


	/**
	 * 获取一个redis对象
	 *
	 * @param template
	 * @param clazz
	 * @param key
	 * @param <T>
	 * @return
	 */
	public static <T extends IRedisObject> T query(RedisTemplate template, Class<T> clazz, String key) {
    
    
		String tableFlag = getTableFlag(clazz);
		if (StringUtils.isEmpty(tableFlag)) {
    
    
			throw new IllegalArgumentException(String.format("%s 的tableFlag不可为空", clazz.getSimpleName()));
		}
		String tableKey = getTableKey(tableFlag);
		String objectKey = getObjectKey(tableFlag, key);
		String addr = getAddress(template, tableKey, objectKey);
		if (addr == null) {
    
    
			return null;
		}
		return getHashObjByAddress(template, clazz, addr);
	}

	/**
	 * 删除一个hash数据
	 *
	 * @param redisTemplate
	 * @param clazz
	 * @param redisKey
	 * @param <T>
	 * @return
	 */
	public static <T extends IRedisObject> T delete(RedisTemplate redisTemplate, Class<T> clazz, String redisKey) {
    
    
		String tableFlag = getTableFlag(clazz);
		String tableKey = getTableKey(tableFlag);
		String objKey = getObjectKey(tableFlag, redisKey);
		String address = getAddress(redisTemplate, tableKey, objKey);
		if (address == null) {
    
    
			return null;
		}
		T obj = null;
		try {
    
    
			Map entries = redisTemplate.opsForHash().entries(address);
			obj = clazz.getConstructor().newInstance();
			RedisObjWrapper.wrapper(obj, entries);
			redisTemplate.opsForHash().delete(address, RedisObjWrapper.keys(clazz));
		} catch (Throwable t) {
    
    
			LOGGER.error(t.getMessage(), t);
		}
		return obj;

	}

	/**
	 * 放到redis中
	 *
	 * @param redisTemplate
	 * @param redisObj
	 * @param <T>
	 */
	public static <T extends IRedisObject> boolean insert(RedisTemplate redisTemplate, T redisObj) {
    
    
		Map<String, Object> map = RedisObjWrapper.fieldValues(redisObj);
		if (map != null && map.size() > 0) {
    
    
			String tableFlag = getTableFlag(redisObj.getClass());
			String tableKey = getTableKey(tableFlag);
			String objKey = getObjectKey(tableFlag, redisObj.redisKey());
			String address = getAddress(redisTemplate, tableKey, objKey);
			if (address != null) {
    
    
				return false;
			}
			Long addr = getAndIncr(redisTemplate, ADDR_INCREASE_KEY);
			redisTemplate.opsForHash().putAll(addr + "", map);
			addAddress(redisTemplate, tableKey, objKey, addr + "");
			return true;
		}
		return false;
	}

	public static <T extends IRedisObject> List listHashKeys(RedisTemplate redisTemplate, Class<T> clazz) {
    
    
		List values = redisTemplate.opsForHash().values(String.format(OBJECT_ADDR_PATTERN, getTableFlag(clazz)));
		return values;
	}

	/**
	 * 更新数据
	 *
	 * @param redisTemplate
	 * @param redisObject
	 * @param fieldName
	 * @param <T>
	 */
	public static <T extends IRedisObject> void update(RedisTemplate redisTemplate, T redisObject, String fieldName) {
    
    
		if (redisObject == null || StringUtils.isEmpty(fieldName)) {
    
    
			throw new IllegalArgumentException("出入的值不可为空");
		}
		Object fieldValue = RedisObjWrapper.getFieldValue(redisObject, fieldName);
		String tableFlag = getTableFlag(redisObject.getClass());
		if (StringUtils.isEmpty(tableFlag)) {
    
    
			throw new IllegalArgumentException(String.format("%s 的tableFlag不可为空", redisObject.getClass().getSimpleName()));
		}
		String tableKey = getTableKey(tableFlag);
		String objectKey = getObjectKey(tableFlag, redisObject.redisKey());
		String addr = getAddress(redisTemplate, tableKey, objectKey);
		if (addr == null) {
    
    
			return;
		}
		if (fieldValue != null) {
    
    
			redisTemplate.opsForHash().put(addr, fieldName, fieldValue);
		} else {
    
    
			redisTemplate.opsForHash().delete(addr, fieldName);
		}
	}

	/**
	 * 根据redis存放的地址,加载对应的clazz对象
	 *
	 * @param redisTemplate
	 * @param clazz
	 * @param address
	 * @param <T>
	 * @return
	 */
	public static <T extends IRedisObject> T getHashObjByAddress(RedisTemplate redisTemplate, Class<T> clazz, String address) {
    
    
		try {
    
    
//			String tableFlag = getTableFlag(clazz);
//			String tableKey = getTableKey(tableFlag);
//			String objKey = getObjectKey(tableFlag, addr);
//			String address = getAddress(redisTemplate, tableKey, objKey);
//			if (address == null) {
    
    
//				return null;
//			}
			Map entries = redisTemplate.opsForHash().entries(address);
			if (entries.size() <= 0) {
    
    
				return null;
			}
			T obj = clazz.getConstructor().newInstance();
			RedisObjWrapper.wrapper(obj, entries);
			return obj;
		} catch (Throwable t) {
    
    
			LOGGER.error(t.getMessage(), t);
		}
		return null;
	}

	private static String getLockKey(IRedisLock lock) {
    
    
		return String.format(LOCK_KEY, lock.getClass().getName(), lock.lockKey());
	}

	/**
	 * 加锁
	 *
	 * @param redisTemplate
	 * @param lock
	 * @param timeOut
	 * @param timeUnit
	 * @return
	 */
	public static boolean lock(RedisTemplate redisTemplate, IRedisLock lock, int timeOut, TimeUnit timeUnit) {
    
    
		try {
    
    
			if (lock == null || timeUnit == null || redisTemplate == null) {
    
    
				throw new NullPointerException("参数不可为空");
			}
			if (timeOut <= 0) {
    
    
				throw new IllegalArgumentException("传入timeout必须大于0 :" + timeOut);
			}
			String lockKey = getLockKey(lock);
			return redisTemplate.opsForValue().setIfAbsent(lockKey, lock.lockData() == null ? "LOCK" : lock.lockData(), timeOut, timeUnit);
		} catch (Throwable t) {
    
    
			LOGGER.error(t.getMessage(), t);
		}
		return false;
	}


	/**
	 * 移除锁
	 *
	 * @param redisTemplate
	 * @param lock
	 */
	public static void unlock(RedisTemplate redisTemplate, IRedisLock lock) {
    
    
		try {
    
    
			String lockKey = getLockKey(lock);
			redisTemplate.delete(lockKey);
		} catch (Throwable t) {
    
    
			LOGGER.error(t.getMessage(), t);
		}
	}


	/**
	 * 添加到set中去
	 *
	 * @param redisTemplate
	 * @param setKey
	 * @param setData
	 * @param <T>
	 */
	public static <T> void insertToSet(RedisTemplate redisTemplate, String setKey, T setData) {
    
    
		String key = String.format(SET_KEY, setKey);
		redisTemplate.opsForSet().add(key, setData);
	}


	/**
	 * 从set中移除
	 *
	 * @param redisTemplate
	 * @param setKey
	 * @param setData
	 * @param <T>
	 */
	public static <T> void removeFromSet(RedisTemplate redisTemplate, String setKey, T setData) {
    
    
		String key = String.format(SET_KEY, setKey);
		redisTemplate.opsForSet().remove(key, setData);
	}


	/**
	 * 列出set中的元素
	 *
	 * @param redisTemplate
	 * @param setKey
	 */
	public static Set membersOfSet(RedisTemplate redisTemplate, String setKey) {
    
    
		String key = String.format(SET_KEY, setKey);
		return redisTemplate.opsForSet().members(key);
	}


	/**
	 * 尝试执行一个事务,如果该key正在被修改,则不会执行,返回异常
	 *
	 * @param redisTemplate
	 * @param key
	 * @param func
	 * @param <T>
	 * @return
	 */
	public static <T> T runTransaction(RedisTemplate redisTemplate, String key, RedisTransaction<T> func) {
    
    
		return (T) redisTemplate.execute(new SessionCallback() {
    
    
			@Override
			public T execute(RedisOperations operations) throws DataAccessException {
    
    
				operations.watch(key);
				operations.unwatch();
				return (T) func.execute(operations);
			}
		});
	}
}

接着 这个是一个redis的调用类,这个类主要是调用RedisUtils上的接口方法,可以针对自己实际的项目来稍作改动。
JRedisService.java 主要构造方法需要弄一个RedisTemplate进去就好,习惯用spring的话,自己手动初始化就可以


import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis-service
 *
 * @Autor Tricky
 * @Date 2020-05-27 18:42:27
 */
public final class JRedisService {
    
    
	private final RedisTemplate redisTemplate;

	public JRedisService(RedisTemplate redisTemplate) {
    
    
		this.redisTemplate = redisTemplate;
	}

	public RedisTemplate getRedisTemplate() {
    
    
		return redisTemplate;
	}

	/**
	 * 创建一个默认的redis锁
	 *
	 * @param lockKey
	 * @return
	 */
	public IRedisLock createRedisLock(String lockKey) {
    
    
		if (StringUtils.isEmpty(lockKey)) {
    
    
			throw new IllegalArgumentException("LockKey不可为空");
		}
		return new DefaultRedisLock(lockKey);
	}

	/**
	 * 模块名生成一个lockKey
	 *
	 * @param moduleName
	 * @param key
	 * @return
	 */
	public String genRedisLockKey(String moduleName, String key) {
    
    
		return "MODULE-" + moduleName + "@" + key;
	}

	/**
	 * 添加一个对象
	 *
	 * @param hashObj
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> boolean insertHashObj(T hashObj) {
    
    
		return insertHashObj(hashObj, false);
	}

	/**
	 * 添加一个对象
	 *
	 * @param hashObj
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> void insertNotShowError(T hashObj) {
    
    
		RedisUtils.insert(redisTemplate, hashObj);
	}

	/**
	 * 添加一个对象
	 *
	 * @param hashObj
	 * @param errorThrowException 插入失败抛出异常
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> boolean insertHashObj(T hashObj, boolean errorThrowException) {
    
    
		boolean result = RedisUtils.insert(redisTemplate, hashObj);
		if (!result) {
    
    
			if (errorThrowException) {
    
    
				throw new RuntimeException("新增Redis数据失败:" + JSONObject.toJSONString(hashObj));
			}
		}
		return result;
	}


	/**
	 * 查询一个redis数据
	 *
	 * @param clazz
	 * @param key
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> T query(Class<T> clazz, String key) {
    
    
		return RedisUtils.query(redisTemplate, clazz, key);
	}


	/**
	 * 更新hash数据
	 *
	 * @param obj
	 * @param fieldName
	 * @param <T>
	 */
	public <T extends IRedisObject> void update(T obj, String fieldName) {
    
    
		RedisUtils.update(redisTemplate, obj, fieldName);
	}

	public <T extends IRedisObject> T delete(Class<T> clazz, String key) {
    
    
		return RedisUtils.delete(redisTemplate, clazz, key);
	}

	/**
	 * 加锁
	 *
	 * @param lock
	 * @param lockMs
	 * @return
	 */
	public boolean lock(IRedisLock lock, int lockMs) {
    
    
		return RedisUtils.lock(redisTemplate, lock, lockMs, TimeUnit.MILLISECONDS);
	}

	/**
	 * 解锁
	 *
	 * @param lock
	 */
	public void unlock(IRedisLock lock) {
    
    
		RedisUtils.unlock(redisTemplate, lock);
	}


	/**
	 * 添加到set中去
	 *
	 * @param setKey
	 * @param setData
	 * @param <T>
	 */
	public <T> void insertToSet(String setKey, T... setData) {
    
    
		RedisUtils.insertToSet(redisTemplate, setKey, setData);
	}


	/**
	 * 从set中移除
	 *
	 * @param setKey
	 * @param setData
	 * @param <T>
	 */
	public <T> void removeFromSet(String setKey, T... setData) {
    
    
		RedisUtils.removeFromSet(redisTemplate, setKey, setData);
	}

	/**
	 * 列出set中的元素
	 *
	 * @param setKey
	 */
	public Set membersOfSet(String setKey) {
    
    
		return RedisUtils.membersOfSet(redisTemplate, setKey);
	}

	/**
	 * 默认的redis锁
	 */
	public static class DefaultRedisLock implements IRedisLock {
    
    
		private String lockKey;

		public DefaultRedisLock(String lockKey) {
    
    
			this.lockKey = lockKey;
		}

		@Override
		public String lockKey() {
    
    
			return lockKey;
		}
	}


	/**
	 * 获取该类的所有hash键
	 *
	 * @param clazz
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> List<String> listHashKeys(Class<T> clazz) {
    
    
		return (List<String>) RedisUtils.listHashKeys(redisTemplate, clazz);
	}

	/**
	 * 根据redis中存放的key(address/地址)来获取对应的hash数据
	 *
	 * @param clazz
	 * @param addr  这个不是object的redisKey 而是redis数据库中的hash的key
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> T getHashObjByAddress(Class<T> clazz, String addr) {
    
    
		return RedisUtils.getHashObjByAddress(redisTemplate, clazz, addr);
	}


	/**
	 * 根据hashObject的key(即{@link IRedisObject#redisKey()}来获取对应的object信息
	 *
	 * @param clazz
	 * @param redisKey
	 * @param <T>
	 * @return
	 */
	public <T extends IRedisObject> T queryHashObj(Class<T> clazz, String redisKey) {
    
    
		return RedisUtils.query(redisTemplate, clazz, redisKey);
	}
}

其它一些杂七杂八的类

/**
 * redis锁
 *
 * @Autor Tricky
 * @Date 2020-05-27 18:19:25
 */
public interface IRedisLock {
    
    
	/**
	 * redis键
	 *
	 * @return
	 */
	String lockKey();

	/**
	 * 锁的数据
	 *
	 * @return
	 */
	default Object lockData() {
    
    
		return System.currentTimeMillis();
	}

}
/**
 * redis对象
 *
 * @Autor Tricky
 * @Date 2020-05-27 15:29:48
 */
public interface IRedisObject {
    
    
	/**
	 * redis的主键,
	 *
	 * @return
	 */
	String redisKey();
}
import java.lang.annotation.*;

/**
 * redis-field
 *
 * @Autor Tricky
 * @Date 2020-05-27 17:16:36
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RedisField {
	String name();
}

import java.lang.annotation.*;

/**
 * redis对象
 *
 * @Autor Tricky
 * @Date 2020-05-27 15:30:32
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RedisObj {

	/**
	 * 类的唯一标志,类似数据库中的table名
	 *
	 * @return
	 */
	String tableFlag();
}


import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;

/**
 * redis事务处理内容
 *
 * @Autor Tricky
 * @Date 2020-06-05 16:23:18
 */
@FunctionalInterface
public interface RedisTransaction<T> {

	/**
	 * 事务执行部分
	 *
	 * @param operations
	 * @param <K>
	 * @param <V>
	 * @return
	 * @throws DataAccessException
	 */
	<K, V> T execute(RedisOperations<K, V> operations) throws DataAccessException;
}

import java.lang.annotation.*;

/**
 * redis对象
 *
 * @Autor Tricky
 * @Date 2020-05-27 15:30:32
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RedisTable {

	/**
	 * 类的唯一标志,类似数据库中的table名
	 *
	 * @return
	 */
	String name();
}

最后,附上一个下载地址吧
下载
如果这个下载不了,请告诉我。我写博客的时候才上传,需要审核

猜你喜欢

转载自blog.csdn.net/sail331x/article/details/107799395
今日推荐