前言
之前一直在找一些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();
}
最后,附上一个下载地址吧
下载
如果这个下载不了,请告诉我。我写博客的时候才上传,需要审核