增加Redis插件

v1.4.1
Parker 4 years ago
parent 2ef96ad31b
commit 3f71c2c0d7

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>opsli-plugins</artifactId>
<groupId>org.opsliframework.boot</groupId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>opsli-plugins-redis</artifactId>
<version>${project.parent.version}</version>
<dependencies>
<!-- 集成Redis缓存 BEGIN -->
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 集成Redis缓存 END -->
</dependencies>
</project>

@ -0,0 +1,102 @@
package org.opsli.plugins.redis.conf;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.utils.PackageUtil;
import org.opsli.plugins.redis.msg.RedisMsg;
import org.opsli.plugins.redis.scripts.RedisPluginScript;
import org.opsli.plugins.redis.scripts.RedisScriptCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource;
import java.lang.reflect.Modifier;
import java.util.Set;
/**
* @Author parker
*
* Redis
*
*/
@Slf4j
@Configuration
public class RedisPluginConfig {
@Resource
private LettuceConnectionFactory factory;
/**
* RedisTemplate
*
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
// 开启事务
template.setEnableTransactionSupport(true);
return template;
}
/**
*
*
*
*
* @return
*/
@Bean
public RedisScriptCache loadScripts() {
RedisScriptCache redisScriptCache = new RedisScriptCache();
// 拿到state包下 实现了 SystemEventState 接口的,所有子类
Set<Class<?>> clazzSet = PackageUtil.listSubClazz(RedisPluginScript.class.getPackage().getName(),
true,
RedisPluginScript.class
);
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
continue;
}
// 通过反射 加载所有的 脚本
try {
RedisPluginScript redisPluginScript = (RedisPluginScript) aClass.newInstance();
redisScriptCache.putScript(redisPluginScript);
} catch (Exception e) {
log.error(RedisMsg.EXCEPTION_REFLEX.getMessage());
}
}
return redisScriptCache;
}
}

@ -0,0 +1,11 @@
package org.opsli.plugins.redis.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.enums
* @Author: Parker
* @CreateTime: 2020-09-15 14:51
* @Description: Redis
*/
public enum RedisPushSubMsgType {
}

@ -0,0 +1,22 @@
package org.opsli.plugins.redis.exception;
import org.opsli.common.base.msg.BaseMsg;
import org.opsli.common.exception.ServiceException;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.exception
* @Author: Parker
* @CreateTime: 2020-09-14 18:44
* @Description: Redis
*/
public class RedisPluginException extends ServiceException {
public RedisPluginException(Integer code, String errorMessage) {
super(code, errorMessage);
}
public RedisPluginException(BaseMsg msg) {
super(msg);
}
}

@ -0,0 +1,40 @@
package org.opsli.plugins.redis.msg;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.msg
* @Author: Parker
* @CreateTime: 2020-09-13 19:54
* @Description: Redis
*/
public enum RedisMsg implements BaseMsg {
/** Redis异常 */
EXCEPTION_KEY_NULL(90100,"Key不可为空"),
EXCEPTION_INCREMENT(90101,"递增值必须大于0"),
EXCEPTION_DECREMENT(90102,"递减值必须大于0"),
EXCEPTION_REFLEX(90103,"反射Redis脚本失败"),
EXCEPTION_PUSH_SUB_NULL(90104,"发布消息体不可为空!"),
;
private int code;
private String message;
RedisMsg(int code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -0,0 +1,34 @@
package org.opsli.plugins.redis.pushsub.entity;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class BaseSubMessage implements RedisPushSubMessage{
public static final String BASE_TYPE = "TYPE";
/** 发布订阅频道名称 */
protected String channel;
protected String json;
/**
* json
* @param channel
* @param type
* @param jsonObj
*/
public void build(String channel, String type, JSONObject jsonObj) {
if(channel == null || type == null || jsonObj == null){
return;
}
jsonObj.put(BASE_TYPE, type);
this.json = jsonObj.toString();
this.channel = channel;
}
}

@ -0,0 +1,15 @@
package org.opsli.plugins.redis.pushsub.entity;
import java.io.Serializable;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.entity
* @Author: Parker
* @CreateTime: 2020-09-15 14:50
* @Description: Redis
*/
public interface RedisPushSubMessage extends Serializable {
}

@ -0,0 +1,36 @@
package org.opsli.plugins.redis.pushsub.receiver;
import com.alibaba.fastjson.JSONObject;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.receiver
* @Author: Parker
* @CreateTime: 2020-09-15 14:49
* @Description: Redis
*/
public abstract class BaseReceiver {
public static final String BASE_CHANNEL = "listener:msg:";
private String channel;
public BaseReceiver(String channel){
this.channel = BASE_CHANNEL+channel;
}
/**
*
* @return
*/
public String getListenerChannel(){
return this.channel;
}
/**
*
* @param msg
*/
public abstract void receiveMessage(String msg);
}

@ -0,0 +1,38 @@
package org.opsli.plugins.redis.scripts;
import org.opsli.plugins.redis.scripts.enums.RedisScriptsEnum;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.scripts
* @Author: Parker
* @CreateTime: 2020-09-14 22:01
* @Description: Redis Lua
*
* Redis 使Redis
*
*/
public class RedisLockScript implements RedisPluginScript {
@Override
public RedisScriptsEnum getEnum() {
return RedisScriptsEnum.REDIS_LOCK;
}
@Override
public String getScript() {
return "local key = KEYS[1]\n" +
"local identifier = ARGV[1]\n" +
"local lockTimeOut = ARGV[2]\n" +
"\n" +
"if redis.call(\"SETNX\", key, identifier) == 1 then\n" +
" redis.call(\"EXPIRE\", key, lockTimeOut)\n" +
" return 1\n" +
"elseif redis.call(\"TTL\", key) == -1 then\n" +
" redis.call(\"EXPIRE\", key, lockTimeOut)\n" +
"end\n" +
"return 0";
}
}

@ -0,0 +1,30 @@
package org.opsli.plugins.redis.scripts;
import org.opsli.plugins.redis.scripts.enums.RedisScriptsEnum;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.scripts
* @Author: Parker
* @CreateTime: 2020-09-14 22:05
* @Description: Redis Lua
*
* Lua 线Redis
*
*/
public interface RedisPluginScript {
/**
*
* @return
*/
RedisScriptsEnum getEnum();
/**
*
* @return
*/
String getScript();
}

@ -0,0 +1,50 @@
package org.opsli.plugins.redis.scripts;
import org.opsli.plugins.redis.scripts.enums.RedisScriptsEnum;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
*
* @author parker
*/
public class RedisScriptCache {
/** 脚本存放容器 */
private final ConcurrentMap<RedisScriptsEnum, RedisPluginScript> scriptCacheMap = new ConcurrentHashMap<>();
/**
*
* @param scriptsEnum Enum
* @return
*/
public RedisPluginScript getScript(RedisScriptsEnum scriptsEnum){
if(scriptsEnum == null){
return null;
}
return scriptCacheMap.get(scriptsEnum);
}
/**
*
* @param redisPluginScript Enum
* @return
*/
public boolean putScript(RedisPluginScript redisPluginScript){
boolean ret = true;
if(redisPluginScript == null || redisPluginScript.getScript() == null || "".equals(redisPluginScript.getScript())
|| redisPluginScript.getEnum() == null
){
return false;
}
try {
scriptCacheMap.put(redisPluginScript.getEnum(),redisPluginScript);
} catch (Exception e) {
ret = false;
e.printStackTrace();
}
return ret;
}
}

@ -0,0 +1,35 @@
package org.opsli.plugins.redis.scripts;
import org.opsli.plugins.redis.scripts.enums.RedisScriptsEnum;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.scripts
* @Author: Parker
* @CreateTime: 2020-09-14 22:01
* @Description: Redis Lua
*
* Redis 使Redis
*
*/
public class RedisUnLockScript implements RedisPluginScript {
@Override
public RedisScriptsEnum getEnum() {
return RedisScriptsEnum.REDIS_UN_LOCK;
}
@Override
public String getScript() {
return "local key = KEYS[1]\n" +
"local identifier = ARGV[1]\n" +
"\n" +
"if redis.call(\"GET\", key) == identifier then\n" +
" redis.call(\"DEL\", key)\n" +
" return 1\n" +
"end\n" +
"return 0";
}
}

@ -0,0 +1,19 @@
package org.opsli.plugins.redis.scripts.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.redis.enums
* @Author: Parker
* @CreateTime: 2020-09-14 21:56
* @Description: Redis
*/
public enum RedisScriptsEnum {
/** Redis加锁脚本 */
REDIS_LOCK,
/** Redis解锁脚本 */
REDIS_UN_LOCK
;
}
Loading…
Cancel
Save