集成EhCache缓存 - 可做热点数据缓存

v1.4.1
Parker 5 years ago
parent 4db991dfb8
commit d1067d93dd

@ -0,0 +1,30 @@
package org.opsli.common.annotation;
import org.opsli.common.constants.CacheConstants;
import java.lang.annotation.*;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.annotation
* @Author: Parker
* @CreateTime: 2020-09-16 16:36
* @Description: - Get
*
* Service get keyid
*
*
* BaseEntity
*
* 访
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface HotDataDel {
/** 缓存源名字 */
String name() default CacheConstants.HOT_DATA;
}

@ -0,0 +1,30 @@
package org.opsli.common.annotation;
import org.opsli.common.constants.CacheConstants;
import java.lang.annotation.*;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.annotation
* @Author: Parker
* @CreateTime: 2020-09-16 16:36
* @Description: - Get
*
* Service get keyid
*
*
* BaseEntity
*
* 访
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface HotDataPut {
/** 缓存源名字 */
String name() default CacheConstants.HOT_DATA;
}

@ -1,6 +1,8 @@
package org.opsli.common.api;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
@ -15,6 +17,8 @@ import java.util.Map;
* @author Parker
*
*/
@ApiModel(value="视图层返回Api对象",
description="视图层返回Api对象 success:成功状态 code:编号 msg:信息 datatime:时间戳")
public class ResultVo extends HashMap<String,Object> implements Serializable {
@ -22,6 +26,7 @@ public class ResultVo extends HashMap<String,Object> implements Serializable {
this.put("success", true);
this.put("code", HttpStatus.OK.value());
this.put("msg", "操作成功");
this.put("datatime", System.currentTimeMillis());
}
/** get/set

@ -1,18 +1,56 @@
package org.opsli.common.base.entity;
import com.baomidou.mybatisplus.annotation.Version;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.base.entity
* @Author: Parker
* @CreateTime: 2020-09-14 17:29
* @Description: Entity
*
* Entity
*
* @author Parker
* @date 2019-05-11
*
*/
public class BaseEntity {
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** ID */
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "ID")
private String id;
/** 创建人 */
@ApiModelProperty(value = "创建人")
private String createBy;
/** 创建时间 */
@ApiModelProperty(value = "创建时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新人 */
@ApiModelProperty(value = "修改人")
private String updateBy;
/** 更新时间 */
@ApiModelProperty(value = "修改时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 乐观锁 */
@Version
private Integer version;
/** 乐观锁 版本 */
private Integer version;
}

@ -0,0 +1,18 @@
package org.opsli.common.constants;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.constants
* @Author: Parker
* @CreateTime: 2020-09-16 17:42
* @Description:
*/
public interface CacheConstants {
/** 热点数据 */
String HOT_DATA = "hotData";
/** 系统常量 */
String SYSTEM_DATA = "systemData";
}

@ -0,0 +1,19 @@
package org.opsli.common.constants;
/**
* Order
* @author parker
* @date 2020-09-16
*/
public interface OrderConstants {
/** 热点数据加载顺序 */
int HOT_DATA_ORDER = 180;
/** Controller异常拦截顺序 */
int EXCEPTION_HANDLER_ORDER = 260;
/** 参数非法验证顺序 */
int PARAM_VALIDATE_AOP_SORT = 500;
}

@ -25,12 +25,21 @@
<version>${version}</version>
</dependency>
<!-- 引入Redis模块 -->
<!-- 引入Redis插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-redis</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入EhCache插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-ehcache</artifactId>
<version>${plugins.version}</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,153 @@
package org.opsli.core.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.common.annotation.HotDataDel;
import org.opsli.common.annotation.HotDataPut;
import org.opsli.common.base.entity.BaseEntity;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.cache.pushsub.msgs.CacheDataMsgFactory;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import static org.opsli.common.constants.OrderConstants.HOT_DATA_ORDER;
/**
*
*
* @author parker
* @date 2020-09-16
*/
@Slf4j
@Order(HOT_DATA_ORDER)
@Aspect
@Component
public class CacheDataAop {
/** 热点数据前缀 */
public static final String PREFIX_NAME = "opsli:";
@Autowired
private RedisPlugin redisPlugin;
@Pointcut("@annotation(org.opsli.common.annotation.HotDataPut)")
public void hotDataPut() {
}
@Pointcut("@annotation(org.opsli.common.annotation.HotDataDel)")
public void hotDataDel() {
}
@Around("hotDataPut()")
public Object hotDataPutProcess(ProceedingJoinPoint point) throws Throwable {
Object[] args= point.getArgs();
Object returnValue = point.proceed(args);
// 将
if(returnValue != null){
String methodName= point.getSignature().getName();
Class<?> classTarget= point.getTarget().getClass();
Class<?>[] par=((MethodSignature) point.getSignature()).getParameterTypes();
Method objMethod = classTarget.getMethod(methodName, par);
// 获取注解参数
HotDataPut aCache= objMethod.getAnnotation(HotDataPut.class);
if(aCache != null){
// 类型
PushSubType type;
// key 前缀
StringBuilder keyBuf = new StringBuilder(PREFIX_NAME);
// 热点数据
if(CacheConstants.HOT_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.HOT_DATA).append(":");
type = PushSubType.HOT_DATA;
}
// 系统数据
else if(CacheConstants.SYSTEM_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.SYSTEM_DATA).append(":");
type = PushSubType.SYSTEM_DATA;
} else {
// 如果都不是 则直接退出 不走缓存
return returnValue;
}
try {
// 这里 只对 继承了 BaseEntity 的类做处理
BaseEntity baseEntity = (BaseEntity) returnValue;
// key 存储ID
String key = keyBuf.append(baseEntity.getId()).toString();
// 广播数据
redisPlugin.sendMessage(
CacheDataMsgFactory.createMsg(type, key, returnValue, CacheType.UPDATE)
);
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
}
return returnValue;
}
@Around("hotDataDel()")
public Object hotDataDelProcess(ProceedingJoinPoint point) throws Throwable {
Object[] args= point.getArgs();
Object returnValue = point.proceed(args);
// 将
if(returnValue != null){
String methodName= point.getSignature().getName();
Class<?> classTarget= point.getTarget().getClass();
Class<?>[] par=((MethodSignature) point.getSignature()).getParameterTypes();
Method objMethod = classTarget.getMethod(methodName, par);
// 获取注解参数
HotDataDel aCache= objMethod.getAnnotation(HotDataDel.class);
if(aCache != null){
// 类型
PushSubType type;
// key 前缀
StringBuilder keyBuf = new StringBuilder(PREFIX_NAME);
// 热点数据
if(CacheConstants.HOT_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.HOT_DATA).append(":");
type = PushSubType.HOT_DATA;
}
// 系统数据
else if(CacheConstants.SYSTEM_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.SYSTEM_DATA).append(":");
type = PushSubType.SYSTEM_DATA;
} else {
// 如果都不是 则直接退出 不走缓存
return returnValue;
}
try {
// 这里 只对 继承了 BaseEntity 的类做处理
BaseEntity baseEntity = (BaseEntity) returnValue;
// key 存储ID
String key = keyBuf.append(baseEntity.getId()).toString();
// 广播数据
redisPlugin.sendMessage(
CacheDataMsgFactory.createMsg(type, key, returnValue, CacheType.DELETE)
);
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
}
return returnValue;
}
}

@ -0,0 +1,76 @@
package org.opsli.core.cache.local;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.aspect.CacheDataAop;
import org.opsli.plugins.cache.EhCachePlugin;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.local
* @Author: Parker
* @CreateTime: 2020-09-16 16:20
* @Description:
*/
@Slf4j
@Component
public class CacheUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** EhCache插件 */
private static EhCachePlugin ehCachePlugin;
public static <V> V get(String key, Class<V> vClass){
return CacheUtil.get(CacheConstants.HOT_DATA,key,vClass,true);
}
public static <V> V getByKeyOriginal(String key, Class<V> vClass){
return CacheUtil.get(CacheConstants.HOT_DATA,key,vClass,false);
}
private static <V> V get(String cacheName, String key, Class<V> vClass,boolean keyFlag){
// 自动处理 key
if(keyFlag){
StringBuilder keyBuf = new StringBuilder(CacheDataAop.PREFIX_NAME);
keyBuf.append(cacheName).append(":");
keyBuf.append(key);
key = keyBuf.toString();
}
V v = null;
try {
JSONObject jsonObject;
jsonObject = ehCachePlugin.get(cacheName, key, JSONObject.class);
// 如果本地缓存为空 则去Redis中 再去取一次
if(jsonObject != null){
v = jsonObject.toJavaObject(vClass);
}else{
jsonObject = (JSONObject) redisPlugin.get(key);
if(jsonObject != null){
v = jsonObject.toJavaObject(vClass);
}
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
return v;
}
// ================================
@Autowired
public void setRedisPlugin(RedisPlugin redisPlugin) {
CacheUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setEhCachePlugin(EhCachePlugin ehCachePlugin) {
CacheUtil.ehCachePlugin = ehCachePlugin;
}
}

@ -0,0 +1,20 @@
package org.opsli.core.cache.pushsub.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.enums
* @Author: Parker
* @CreateTime: 2020-09-16 22:28
* @Description:
*/
public enum CacheType {
/** 更新 */
UPDATE,
/** 删除 */
DELETE,
;
}

@ -15,7 +15,15 @@ public enum MsgArgsType {
DICT_FIELD,
/** 字典Value */
DICT_VALUE,
/** 字典Value */
DICT_TYPE,
/** 缓存数据Key */
CACHE_DATA_KEY,
/** 缓存数据Value */
CACHE_DATA_VALUE,
/** 缓存数据Type */
CACHE_DATA_TYPE,
;
}

@ -12,12 +12,13 @@ public enum PushSubType {
/** 字典类型 */
DICT,
;
/** 热点数据 */
HOT_DATA,
/** 系统数据 */
SYSTEM_DATA
PushSubType(){
;
}
}

@ -0,0 +1,61 @@
package org.opsli.core.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.plugins.cache.EhCachePlugin;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.handler
* @Author: Parker
* @CreateTime: 2020-09-15 16:24
* @Description:
*/
@Slf4j
public class HotDataHandler implements RedisPushSubHandler{
/** 热点数据缓存时间 */
@Value("${cache.ttl-hot-data}")
private int ttlHotData;
@Autowired
private RedisPlugin redisPlugin;
@Autowired
private EhCachePlugin cachePlugin;
@Override
public PushSubType getType() {
return PushSubType.HOT_DATA;
}
@Override
public void handler(JSONObject msgJson) {
String key = (String) msgJson.get(MsgArgsType.CACHE_DATA_KEY.toString());
Object value = msgJson.get(MsgArgsType.CACHE_DATA_VALUE.toString());
CacheType type = CacheType.valueOf((String )msgJson.get(MsgArgsType.CACHE_DATA_TYPE.toString()));
// 缓存更新
if(CacheType.UPDATE == type){
// 存入EhCache
cachePlugin.put(CacheConstants.HOT_DATA,key, value);
// 存入Redis
redisPlugin.put(key, value, ttlHotData);
}
// 缓存删除
else if(CacheType.DELETE == type){
// 存入EhCache
cachePlugin.delete(CacheConstants.HOT_DATA,key);
// 存入Redis
redisPlugin.del(key);
}
}
}

@ -0,0 +1,61 @@
package org.opsli.core.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.plugins.cache.EhCachePlugin;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.handler
* @Author: Parker
* @CreateTime: 2020-09-15 16:24
* @Description:
*/
@Slf4j
public class SystemDataHandler implements RedisPushSubHandler{
/** 热点数据缓存时间 */
@Value("${cache.ttl-system-data}")
private int ttlSystemData;
@Autowired
private RedisPlugin redisPlugin;
@Autowired
private EhCachePlugin cachePlugin;
@Override
public PushSubType getType() {
return PushSubType.SYSTEM_DATA;
}
@Override
public void handler(JSONObject msgJson) {
String key = (String) msgJson.get(MsgArgsType.CACHE_DATA_KEY.toString());
Object value = msgJson.get(MsgArgsType.CACHE_DATA_VALUE.toString());
CacheType type = CacheType.valueOf((String )msgJson.get(MsgArgsType.CACHE_DATA_TYPE.toString()));
// 缓存更新
if(CacheType.UPDATE == type){
// 存入EhCache
cachePlugin.put(CacheConstants.SYSTEM_DATA,key, value);
// 存入Redis
redisPlugin.put(key, value, ttlSystemData);
}
// 缓存删除
else if(CacheType.DELETE == type){
// 存入EhCache
cachePlugin.delete(CacheConstants.SYSTEM_DATA,key);
// 存入Redis
redisPlugin.del(key);
}
}
}

@ -0,0 +1,45 @@
package org.opsli.core.cache.pushsub.msgs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver;
import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.msgs
* @Author: Parker
* @CreateTime: 2020-09-15 16:50
* @Description:
*/
@Data
@Accessors(chain = true)
public final class CacheDataMsgFactory extends BaseSubMessage{
/** 通道 */
private static final String CHANNEL = RedisPushSubReceiver.BASE_CHANNEL+RedisPushSubReceiver.CHANNEL;
private CacheDataMsgFactory(){}
/**
*
*/
public static BaseSubMessage createMsg(PushSubType py,String key, Object value, CacheType cacheType){
BaseSubMessage baseSubMessage = new BaseSubMessage();
// 数据
JSONObject jsonObj = new JSONObject();
jsonObj.put(MsgArgsType.CACHE_DATA_KEY.toString(),key);
jsonObj.put(MsgArgsType.CACHE_DATA_VALUE.toString(),value);
jsonObj.put(MsgArgsType.CACHE_DATA_TYPE.toString(),cacheType.toString());
// 热点数据 - 系统数据
baseSubMessage.build(CHANNEL,py.toString(),jsonObj);
return baseSubMessage;
}
}

@ -3,6 +3,7 @@ package org.opsli.core.cache.pushsub.msgs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver;
@ -28,13 +29,14 @@ public final class DictMsgFactory extends BaseSubMessage{
/**
*
*/
public static BaseSubMessage createMsg(String key, String field, Object value){
public static BaseSubMessage createMsg(String key, String field, Object value, CacheType cacheType){
BaseSubMessage baseSubMessage = new BaseSubMessage();
// 数据
JSONObject jsonObj = new JSONObject();
jsonObj.put(MsgArgsType.DICT_KEY.toString(),key);
jsonObj.put(MsgArgsType.DICT_FIELD.toString(),field);
jsonObj.put(MsgArgsType.DICT_VALUE.toString(),value);
jsonObj.put(MsgArgsType.DICT_TYPE.toString(),cacheType.toString());
// DICT 字典
baseSubMessage.build(CHANNEL,PushSubType.DICT.toString(),jsonObj);

@ -8,6 +8,11 @@ import org.opsli.core.cache.pushsub.handler.RedisPushSubHandler;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage;
import org.opsli.plugins.redis.pushsub.receiver.BaseReceiver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Modifier;
import java.util.Set;
@ -25,6 +30,7 @@ import java.util.concurrent.ConcurrentMap;
*
*/
@Slf4j
@Configuration
public class RedisPushSubReceiver extends BaseReceiver {
/** 监听信道 */
@ -33,13 +39,26 @@ public class RedisPushSubReceiver extends BaseReceiver {
/** 处理方法集合 */
private static final ConcurrentMap<PushSubType, RedisPushSubHandler> HANDLER_MAP = new ConcurrentHashMap<>();
static {
@Autowired
private AutowireCapableBeanFactory beanFactory;
@Autowired
DefaultListableBeanFactory defaultListableBeanFactory;
public RedisPushSubReceiver() {
super(CHANNEL);
}
@Bean
public void initRedisPushSubHandler(){
// 拿到state包下 实现了 SystemEventState 接口的,所有子类
Set<Class<?>> clazzSet = PackageUtil.listSubClazz(RedisPushSubHandler.class.getPackage().getName(),
true,
RedisPushSubHandler.class
);
int count = 0;
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
@ -47,27 +66,33 @@ public class RedisPushSubReceiver extends BaseReceiver {
}
try {
RedisPushSubHandler handler = (RedisPushSubHandler) aClass.newInstance();
Object obj = aClass.newInstance();
RedisPushSubHandler handler = (RedisPushSubHandler) obj;
// 加入集合
HANDLER_MAP.put(handler.getType(),handler);
//将new出的对象放入Spring容器中
defaultListableBeanFactory.registerSingleton("redisPushSubHandler"+count,obj);
//自动注入依赖
beanFactory.autowireBean(obj);
} catch (Exception e){
log.error(CoreMsg.REDIS_EXCEPTION_PUSH_SUB.getMessage());
}
count ++;
}
}
public RedisPushSubReceiver() {
super(CHANNEL);
}
@Override
public void receiveMessage(String msg) {
if(msg == null || "".equals(msg)){
return;
}
long beginTime = System.currentTimeMillis();
// 替换 转意符
String replaceAll = msg.replaceAll("\\\\", "");
String substring = replaceAll.substring(1, replaceAll.length() - 1);
@ -79,6 +104,8 @@ public class RedisPushSubReceiver extends BaseReceiver {
return;
}
redisPushSubHandler.handler(msgJson);
long endTime = System.currentTimeMillis();
log.info("订阅节点更新缓存 耗时(毫秒):{}",(endTime-beginTime));
}
}

@ -23,7 +23,7 @@ import javax.annotation.Resource;
@Slf4j
@Configuration
@ConditionalOnProperty(name = "spring.redis.pushsub.enable", havingValue = "true")
public class RedisMessageListener {
public class RedisMessageListenerConfig {
@Resource
private LettuceConnectionFactory factory;

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import static org.opsli.common.constants.OrderConstants.EXCEPTION_HANDLER_ORDER;
/**
* @author parker
@ -17,11 +18,11 @@ import org.springframework.web.bind.annotation.ResponseStatus;
*/
@Slf4j
@ControllerAdvice
@Order(-1)
@Order(EXCEPTION_HANDLER_ORDER)
public class GlobalExceptionHandler {
/**
*
*
*/
@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ -34,12 +35,24 @@ public class GlobalExceptionHandler {
}
/**
*
*
*/
@ExceptionHandler(EmptyException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo emptyException(EmptyException e) {
ResultVo errorR = ResultVo.error(e.getMessage());
errorR.setCode(e.getCode());
return errorR;
}
/**
*
*/
@ExceptionHandler(NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo bussinessException(EmptyException e) {
public ResultVo nullPointerException(EmptyException e) {
ResultVo errorR = ResultVo.error(e.getMessage());
errorR.setCode(e.getCode());
return errorR;

@ -0,0 +1,23 @@
package org.opsli.modulars.test.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.opsli.common.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description:
*/
@Data
public class TestEntity extends BaseEntity {
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "备注")
private String remark;
}

@ -0,0 +1,45 @@
package org.opsli.modulars.test.service;
import org.opsli.common.annotation.HotDataDel;
import org.opsli.common.annotation.HotDataPut;
import org.opsli.modulars.test.entity.TestEntity;
import org.springframework.stereotype.Service;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.service
* @Author: Parker
* @CreateTime: 2020-09-16 17:34
* @Description:
*/
@Service
public class TestService {
/**
*
* @param testEntity
* @return
*/
@HotDataPut
public TestEntity save(TestEntity testEntity){
return testEntity;
}
/**
*
* @param id
* @return
*/
@HotDataDel
public TestEntity del(String id){
TestEntity t = new TestEntity();
t.setId(id);
return t;
}
}

@ -1,9 +1,15 @@
package org.opsli.modulars.test.web;
import cn.hutool.core.thread.ThreadUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.opsli.common.api.ResultVo;
import org.opsli.common.base.concroller.BaseController;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.msgs.DictMsgFactory;
import org.opsli.modulars.test.entity.TestEntity;
import org.opsli.modulars.test.service.TestService;
import org.opsli.plugins.mail.MailPlugin;
import org.opsli.plugins.mail.model.MailModel;
import org.opsli.plugins.redis.RedisLockPlugins;
@ -15,6 +21,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
@ -28,6 +35,9 @@ import java.util.concurrent.TimeUnit;
@RequestMapping("/{opsli.prefix}/{opsli.version}/test")
public class TestRestController extends BaseController {
private Random random = new Random();
@Autowired
private MailPlugin mailPlugin;
@ -37,6 +47,10 @@ public class TestRestController extends BaseController {
@Autowired
private RedisLockPlugins redisLockPlugins;
@Autowired
private TestService testService;
@GetMapping("/sendMail")
public ResultVo sendMail(){
MailModel mailModel = new MailModel();
@ -55,7 +69,7 @@ public class TestRestController extends BaseController {
@GetMapping("/sendMsg")
public ResultVo sendMsg(){
BaseSubMessage msg = DictMsgFactory.createMsg("test", "aaa", 123213);
BaseSubMessage msg = DictMsgFactory.createMsg("test", "aaa", 123213, CacheType.UPDATE);
boolean ret = redisPlugin.sendMessage(msg);
if(ret){
@ -112,6 +126,56 @@ public class TestRestController extends BaseController {
return success;
}
/**
* Redis
* @return
*/
@GetMapping("/save")
public ResultVo save(String id){
if(StringUtils.isEmpty(id)){
id = String.valueOf(random.nextLong());
}
TestEntity testEntity = new TestEntity();
testEntity.setId(id);
testEntity.setName("测试名称"+random.nextInt());
testEntity.setRemark("测试备注"+random.nextInt());
TestEntity saveObj = testService.save(testEntity);
if(saveObj == null){
ResultVo success = ResultVo.error("保存对象失败!");
success.put("object",testEntity);
return success;
}
TestEntity o = CacheUtil.get(id, TestEntity.class);
ResultVo success = ResultVo.success("保存对象成功!");
success.put("object",o);
return success;
}
/**
* Redis
* @return
*/
@GetMapping("/del")
public ResultVo del(String id){
TestEntity ret = testService.del(id);
if(ret == null){
ResultVo success = ResultVo.error("删除对象失败!");
success.put("object",ret);
return success;
}
TestEntity o = CacheUtil.get(id, TestEntity.class);
ResultVo success = ResultVo.success("删除对象成功!");
success.put("object",o);
return success;
}
}

@ -9,7 +9,10 @@ opsli:
server:
port: 8080
spring:
#redis 配置
redis:
database: 0
@ -49,11 +52,9 @@ spring:
#password: 12345678
#driver-class-name: com.mysql.jdbc.Driver
#Mybatis输出sql日志
#logging:
# level:
# org.opsli.modulars.system.mapper : debug
# swagger 配置
swagger:
production: false

@ -54,6 +54,10 @@ spring:
# 默认编码
default-encoding: UTF-8
# EhCache 配置
cache:
jcache:
config: classpath:config/ehcache-opsli.xml
#redis 配置
redis:
# 开启消息订阅
@ -128,3 +132,10 @@ mybatis-plus:
call-setters-on-nulls: true
# 打印SQL 开发测试使用 生产关闭 ***
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 缓存设置
cache:
# 热点数据 缓存时间 600秒 10分钟
ttl-hot-data: 600
# 系统数据 缓存时间 60000秒 6小时
ttl-system-data: 60000

@ -0,0 +1,38 @@
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd">
<!-- http://www.ehcache.org/documentation/3.8/xml.html -->
<!--指定缓存持久化目录-->
<persistence directory="${java.io.tmpdir}/opsli-ehcache-data"/>
<!-- <cache-template>可以让你创建一个抽象的<cache>配置文件,该配置文件可以进一步的被扩展。-->
<!-- 默认缓存模版 -->
<cache-template name="opsliDefaults">
<!--键值对被声明为字符串类型如果没有指明默认是Object类型。-->
<key-type>java.lang.String</key-type>
<value-type>java.lang.Object</value-type>
<resources>
<heap unit="entries">2000</heap> <!--配置堆储存-->
<offheap unit="MB">300</offheap> <!--配置堆外储存-->
</resources>
</cache-template>
<!-- hotData 热点数据它使用名为myDefaults的<cache-template>,并将其主键覆盖到更广泛的类型 -->
<cache alias="hotData" uses-template="opsliDefaults">
<!--缓存到期配置-->
<expiry>
<ttl unit="minutes">10</ttl> <!-- 使用 TTL(time to leave)策略 -->
</expiry>
</cache>
<!-- 系统数据 -->
<cache alias="systemData" uses-template="opsliDefaults">
<!--缓存到期配置-->
<expiry>
<ttl unit="minutes">600</ttl> <!-- 使用 TTL(time to leave)策略 -->
<!-- <tti unit="minutes">600</tti> &lt;!&ndash; 使用 TTI(time to idle) 策略 &ndash;&gt;-->
</expiry>
</cache>
</config>

@ -10,7 +10,7 @@
<!-- ****************************************************************************************** -->
<!-- ****************************** 本地开发只在控制台打印日志 ************************************ -->
<!-- ****************************************************************************************** -->
<springProfile name="local">
<springProfile name="dev">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
@ -32,7 +32,7 @@
<!-- ********************************************************************************************** -->
<!-- **** 放到服务器上不管在什么环境都只在文件记录日志控制台catalina.out打印logback捕获不到的日志 **** -->
<!-- ********************************************************************************************** -->
<springProfile name="!local">
<springProfile name="!dev">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>

@ -1,2 +0,0 @@
## 统一异常类
02001=请求数据不完整或格式错误!

@ -12,7 +12,7 @@
<developers>
<!--项目开发者的信息 -->
<developer>
<!--SCM里项目开发者的唯一标识符 -->
<!--项目开发者的唯一标识符 -->
<id>parker</id>
<!--项目开发者的全名 -->
<name>Parker Chou</name>
@ -75,6 +75,7 @@
<commons.io.version>2.8.0</commons.io.version>
<guava.version>29.0-jre</guava.version>
<hutool.version>5.4.2</hutool.version>
<ehcache.version>3.9.0</ehcache.version>
<!-- <aliyun-java-sdk-core.version>3.2.3</aliyun-java-sdk-core.version>-->
<!-- <aliyun-java-sdk-dysmsapi.version>1.0.0</aliyun-java-sdk-dysmsapi.version>-->

Loading…
Cancel
Save