Commit 108f8f8c047654cfb4ae56fb7bba85ffa17ef30d
Merge branch 'dev'
Showing
17 changed files
with
772 additions
and
14 deletions
.gitignore
README.md
| 1 | -sass-common-lib:公共项目库 | 1 | +## sass-common-lib:公共项目库 |
| 2 | + | ||
| 3 | +### v 1.2.0版本更新记录 | ||
| 4 | +- 利用redis和ehcache增加了缓存支持,redis为L2级缓存,ehcache为L1级cache; | ||
| 5 | +> application.yml基本配置如下: | ||
| 6 | +```json | ||
| 7 | +#开启ehcache和redis两级缓存 | ||
| 8 | +springext: | ||
| 9 | + cache: | ||
| 10 | + enable: true | ||
| 11 | + cacheL1: | ||
| 12 | + enable: true | ||
| 13 | + topic: cache #同步L1缓存的topic | ||
| 14 | + key: "keys" | ||
| 15 | +``` | ||
| 16 | +```json | ||
| 17 | +#redis配置 | ||
| 18 | +spring: | ||
| 19 | + redis: | ||
| 20 | + database: 10 | ||
| 21 | + host: 192.168.2.252 | ||
| 22 | + port: 6379 | ||
| 23 | +# password: zhnf@123 | ||
| 24 | + pool: | ||
| 25 | + max-wait: 1 | ||
| 26 | +``` | ||
| 27 | + | ||
| 28 | +### v1.2.1 | ||
| 29 | +- 增加了KeyGenerator实现类,实现类中使用className.methodName:params拼接成key | ||
| 30 | + | ||
| 31 | +### v1.2.2 | ||
| 32 | +- 增加了对@CacheEvict(allEntries = true)的支持 | ||
| 2 | \ No newline at end of file | 33 | \ No newline at end of file |
pom.xml
| @@ -6,19 +6,22 @@ | @@ -6,19 +6,22 @@ | ||
| 6 | 6 | ||
| 7 | <groupId>com.irrigation</groupId> | 7 | <groupId>com.irrigation</groupId> |
| 8 | <artifactId>common-lib</artifactId> | 8 | <artifactId>common-lib</artifactId> |
| 9 | - <version>1.0-SNAPSHOT</version> | 9 | + <version>1.2.4</version> |
| 10 | 10 | ||
| 11 | <properties> | 11 | <properties> |
| 12 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | 12 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| 13 | <java.version>1.8</java.version> | 13 | <java.version>1.8</java.version> |
| 14 | + <spring-boot.version>1.5.10.RELEASE</spring-boot.version> | ||
| 14 | <swagger.version>2.7.0</swagger.version> | 15 | <swagger.version>2.7.0</swagger.version> |
| 15 | <lombok.version>1.16.20</lombok.version> | 16 | <lombok.version>1.16.20</lombok.version> |
| 16 | <commons-codec.version>1.11</commons-codec.version> | 17 | <commons-codec.version>1.11</commons-codec.version> |
| 17 | <guava.vsersion>20.0</guava.vsersion> | 18 | <guava.vsersion>20.0</guava.vsersion> |
| 18 | <slf4j.version>1.7.24</slf4j.version> | 19 | <slf4j.version>1.7.24</slf4j.version> |
| 19 | - <fastjson.version>1.2.46</fastjson.version> | 20 | + <fastjson.version>1.2.49</fastjson.version> |
| 20 | <spring-web.version>4.3.14.RELEASE</spring-web.version> | 21 | <spring-web.version>4.3.14.RELEASE</spring-web.version> |
| 21 | <spring-security-core.version>4.2.4.RELEASE</spring-security-core.version> | 22 | <spring-security-core.version>4.2.4.RELEASE</spring-security-core.version> |
| 23 | + <ehcache.version>2.6.11</ehcache.version> | ||
| 24 | + | ||
| 22 | </properties> | 25 | </properties> |
| 23 | 26 | ||
| 24 | 27 | ||
| @@ -83,6 +86,36 @@ | @@ -83,6 +86,36 @@ | ||
| 83 | <version>${spring-security-core.version}</version> | 86 | <version>${spring-security-core.version}</version> |
| 84 | <scope>provided</scope> | 87 | <scope>provided</scope> |
| 85 | </dependency> | 88 | </dependency> |
| 89 | + <dependency> | ||
| 90 | + <groupId>net.sf.ehcache</groupId> | ||
| 91 | + <artifactId>ehcache-core</artifactId> | ||
| 92 | + <version>${ehcache.version}</version> | ||
| 93 | + <exclusions> | ||
| 94 | + <exclusion> | ||
| 95 | + <groupId>org.slf4j</groupId> | ||
| 96 | + <artifactId>slf4j-api</artifactId> | ||
| 97 | + </exclusion> | ||
| 98 | + </exclusions> | ||
| 99 | + <!--<scope>provided</scope>--> | ||
| 100 | + </dependency> | ||
| 101 | + <dependency> | ||
| 102 | + <groupId>org.springframework.boot</groupId> | ||
| 103 | + <artifactId>spring-boot-starter-cache</artifactId> | ||
| 104 | + <version>${spring-boot.version}</version> | ||
| 105 | + <!--<scope>provided</scope>--> | ||
| 106 | + </dependency> | ||
| 107 | + <dependency> | ||
| 108 | + <groupId>org.springframework.boot</groupId> | ||
| 109 | + <artifactId>spring-boot-starter-data-redis</artifactId> | ||
| 110 | + <version>${spring-boot.version}</version> | ||
| 111 | + <!--<scope>provided</scope>--> | ||
| 112 | + </dependency> | ||
| 113 | + <dependency> | ||
| 114 | + <groupId>org.springframework.boot</groupId> | ||
| 115 | + <artifactId>spring-boot-configuration-processor</artifactId> | ||
| 116 | + <version>${spring-boot.version}</version> | ||
| 117 | + <!--<scope>provided</scope>--> | ||
| 118 | + </dependency> | ||
| 86 | 119 | ||
| 87 | </dependencies> | 120 | </dependencies> |
| 88 | <build> | 121 | <build> |
src/main/java/com/irrigation/icl/cache/Command.java
0 → 100644
| 1 | +package com.irrigation.icl.cache; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.io.Serializable; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * Command | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +public class Command implements Serializable { | ||
| 12 | + | ||
| 13 | + private static final long serialVersionUID = 7126530485423286910L; | ||
| 14 | + | ||
| 15 | + // 设置本地缓存 | ||
| 16 | + public final static byte OPT_SET = 0x01; | ||
| 17 | + // 删除本地缓存Key | ||
| 18 | + public final static byte OPT_DEL = 0x02; | ||
| 19 | + // 删除本地缓存 | ||
| 20 | + public final static byte OPT_REM = 0x03; | ||
| 21 | + | ||
| 22 | + public byte oper; | ||
| 23 | + public String name; | ||
| 24 | + public String key; | ||
| 25 | + public String src; | ||
| 26 | + | ||
| 27 | + public Command() { | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public Command(String src, byte oper, String name, String key) { | ||
| 31 | + this.src = src; | ||
| 32 | + this.oper = oper; | ||
| 33 | + this.name = name; | ||
| 34 | + this.key = key; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 更新本地缓存 | ||
| 39 | + * | ||
| 40 | + * @param cacheName | ||
| 41 | + * @param key | ||
| 42 | + * @return | ||
| 43 | + */ | ||
| 44 | + public static Command set(String src, String cacheName, String key) { | ||
| 45 | + return new Command(src, OPT_SET, cacheName, key); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 删除本地缓存Key | ||
| 50 | + * | ||
| 51 | + * @param cacheName | ||
| 52 | + * @param key | ||
| 53 | + * @return | ||
| 54 | + */ | ||
| 55 | + public static Command del(String src, String cacheName, String key) { | ||
| 56 | + return new Command(src, OPT_DEL, cacheName, key); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * 删除本地缓存 | ||
| 61 | + * | ||
| 62 | + * @param cacheName | ||
| 63 | + * @return | ||
| 64 | + */ | ||
| 65 | + public static Command rem(String src, String cacheName) { | ||
| 66 | + return new Command(src, OPT_REM, cacheName, null); | ||
| 67 | + } | ||
| 68 | +} | ||
| 0 | \ No newline at end of file | 69 | \ No newline at end of file |
src/main/java/com/irrigation/icl/cache/LayeringCacheAutoFactory.java
0 → 100644
| 1 | +package com.irrigation.icl.cache; | ||
| 2 | + | ||
| 3 | +import com.irrigation.icl.cache.core.LayeringCacheLoadCondition; | ||
| 4 | +import com.irrigation.icl.cache.core.LayeringCacheManager; | ||
| 5 | +import com.irrigation.icl.cache.core.LayeringCacheProperties; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| 8 | +import org.springframework.cache.CacheManager; | ||
| 9 | +import org.springframework.context.annotation.Bean; | ||
| 10 | +import org.springframework.context.annotation.Conditional; | ||
| 11 | +import org.springframework.context.annotation.Configuration; | ||
| 12 | +import org.springframework.data.redis.connection.Message; | ||
| 13 | +import org.springframework.data.redis.connection.MessageListener; | ||
| 14 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
| 15 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 16 | +import org.springframework.data.redis.listener.PatternTopic; | ||
| 17 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | ||
| 18 | +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * @Author: boni | ||
| 22 | + * @Date: 2018/8/24-下午2:37 | ||
| 23 | + */ | ||
| 24 | +@Configuration | ||
| 25 | +@Conditional(LayeringCacheLoadCondition.class) | ||
| 26 | +@EnableConfigurationProperties(LayeringCacheProperties.class) | ||
| 27 | +@Slf4j | ||
| 28 | +public class LayeringCacheAutoFactory { | ||
| 29 | + @Bean | ||
| 30 | + public LayeringCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate, | ||
| 31 | + LayeringCacheProperties layeringCacheProperties) { | ||
| 32 | + LayeringCacheManager cacheManager = new LayeringCacheManager(redisTemplate, layeringCacheProperties); | ||
| 33 | + cacheManager.setUsePrefix(true); | ||
| 34 | + long expire = layeringCacheProperties.getExpire() > 0L ? layeringCacheProperties.getExpire() : 120L; | ||
| 35 | + cacheManager.setExpires(layeringCacheProperties.getExpires()); | ||
| 36 | + cacheManager.setDefaultExpiration(expire); | ||
| 37 | + return cacheManager; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @Bean | ||
| 41 | + RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, | ||
| 42 | + LayeringCacheProperties layeringCacheProperties, | ||
| 43 | + MessageListenerAdapter listenerAdapter) { | ||
| 44 | + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); | ||
| 45 | + container.setConnectionFactory(connectionFactory); | ||
| 46 | + container.addMessageListener(listenerAdapter, new PatternTopic(layeringCacheProperties.getCacheL1().getTopic())); | ||
| 47 | + | ||
| 48 | + return container; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + @Bean | ||
| 52 | + LayeringCacheSyncCommandHandler layeringCacheSyncCommandHandler(CacheManager cacheManager) { | ||
| 53 | + LayeringCacheSyncCommandHandler handler = new LayeringCacheSyncCommandHandler(cacheManager); | ||
| 54 | + return handler; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Bean | ||
| 58 | + MessageListenerAdapter listenerAdapter(LayeringCacheSyncCommandHandler handler, | ||
| 59 | + RedisTemplate<Object, Object> redisTemplate) { | ||
| 60 | + | ||
| 61 | + return new MessageListenerAdapter(new MessageListener() { | ||
| 62 | + @Override | ||
| 63 | + public void onMessage(Message message, byte[] pattern) { | ||
| 64 | + byte[] content = message.getBody(); | ||
| 65 | + if (content != null) { | ||
| 66 | +// String commandString = new String(content, Charset.defaultCharset()); | ||
| 67 | +// Command command = JSON.parseObject(commandString, Command.class); | ||
| 68 | + Command command = (Command) redisTemplate.getValueSerializer().deserialize(content); | ||
| 69 | + if (command != null) { | ||
| 70 | + log.debug(command.toString()); | ||
| 71 | + handler.handle(command); | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + }); | ||
| 77 | + } | ||
| 78 | +} | ||
| 0 | \ No newline at end of file | 79 | \ No newline at end of file |
src/main/java/com/irrigation/icl/cache/LayeringCacheSyncCommandHandler.java
0 → 100644
| 1 | +package com.irrigation.icl.cache; | ||
| 2 | + | ||
| 3 | +import com.irrigation.icl.cache.core.LayeringCache; | ||
| 4 | +import lombok.Getter; | ||
| 5 | +import lombok.extern.slf4j.Slf4j; | ||
| 6 | +import org.springframework.cache.CacheManager; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @Author: boni | ||
| 10 | + * @Date: 2018/8/29-下午5:44 | ||
| 11 | + */ | ||
| 12 | +@Slf4j | ||
| 13 | +@Getter | ||
| 14 | +public class LayeringCacheSyncCommandHandler { | ||
| 15 | + CacheManager cacheManager; | ||
| 16 | + | ||
| 17 | + public LayeringCacheSyncCommandHandler(CacheManager cacheManager) { | ||
| 18 | + this.cacheManager = cacheManager; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + public void handle(Command command) { | ||
| 22 | + if (cacheManager != null) { | ||
| 23 | + LayeringCache layeringCache = (LayeringCache) cacheManager.getCache(command.getName()); | ||
| 24 | + if (layeringCache == null) { | ||
| 25 | + return; | ||
| 26 | + } | ||
| 27 | + layeringCache.updateL1Cache(command); | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | +} |
src/main/java/com/irrigation/icl/cache/config/CacheConfig.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.config; | ||
| 2 | + | ||
| 3 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | ||
| 7 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 8 | +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; | ||
| 9 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * @Author: boni | ||
| 13 | + * @Date: 2018/8/24-下午2:03 | ||
| 14 | + */ | ||
| 15 | +@Configuration | ||
| 16 | +public class CacheConfig { | ||
| 17 | + | ||
| 18 | + @ConditionalOnMissingBean(RedisTemplate.class) | ||
| 19 | + @Bean | ||
| 20 | + public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { | ||
| 21 | + RedisTemplate<Object, Object> template = new RedisTemplate<>(); | ||
| 22 | + template.setConnectionFactory(connectionFactory); | ||
| 23 | +// Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); | ||
| 24 | +// ObjectMapper om = new ObjectMapper(); | ||
| 25 | +// om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); | ||
| 26 | +// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); | ||
| 27 | +// jackson2JsonRedisSerializer.setObjectMapper(om); | ||
| 28 | +// | ||
| 29 | + template.setValueSerializer(new JdkSerializationRedisSerializer()); | ||
| 30 | + //使用StringRedisSerializer来序列化和反序列化redis的key值 | ||
| 31 | + template.setKeySerializer(new StringRedisSerializer()); | ||
| 32 | + template.afterPropertiesSet(); | ||
| 33 | + return template; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} |
src/main/java/com/irrigation/icl/cache/core/CustomCacheKeyGenerator.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.core; | ||
| 2 | + | ||
| 3 | +import lombok.extern.slf4j.Slf4j; | ||
| 4 | +import org.springframework.cache.interceptor.KeyGenerator; | ||
| 5 | +import org.springframework.util.StringUtils; | ||
| 6 | + | ||
| 7 | +import java.lang.reflect.Method; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * @Author: boni | ||
| 11 | + * @Date: 2018/9/4-下午3:20 | ||
| 12 | + */ | ||
| 13 | +@Slf4j | ||
| 14 | +public class CustomCacheKeyGenerator implements KeyGenerator { | ||
| 15 | + public static final int NO_PARAM_KEY = 0; | ||
| 16 | + | ||
| 17 | + @Override | ||
| 18 | + public Object generate(Object target, Method method, Object... params) { | ||
| 19 | + StringBuilder key = new StringBuilder(); | ||
| 20 | + key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":"); | ||
| 21 | + if (params.length == 0) { | ||
| 22 | + return key.append(NO_PARAM_KEY).toString(); | ||
| 23 | + } | ||
| 24 | + key.append(StringUtils.arrayToCommaDelimitedString(params)); | ||
| 25 | + //String finalKey = key.toString(); | ||
| 26 | + //log.debug("using cache key={}", finalKey); | ||
| 27 | + return key.toString(); | ||
| 28 | + } | ||
| 29 | +} |
src/main/java/com/irrigation/icl/cache/core/LayeringCache.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.core; | ||
| 2 | + | ||
| 3 | +import com.irrigation.icl.cache.Command; | ||
| 4 | +import lombok.extern.slf4j.Slf4j; | ||
| 5 | +import net.sf.ehcache.CacheException; | ||
| 6 | +import net.sf.ehcache.CacheManager; | ||
| 7 | +import net.sf.ehcache.Ehcache; | ||
| 8 | +import net.sf.ehcache.Element; | ||
| 9 | +import net.sf.ehcache.config.CacheConfiguration; | ||
| 10 | +import net.sf.ehcache.config.Configuration; | ||
| 11 | +import net.sf.ehcache.config.DiskStoreConfiguration; | ||
| 12 | +import net.sf.ehcache.config.PersistenceConfiguration; | ||
| 13 | +import net.sf.ehcache.store.MemoryStoreEvictionPolicy; | ||
| 14 | +import org.springframework.cache.Cache; | ||
| 15 | +import org.springframework.cache.support.SimpleValueWrapper; | ||
| 16 | +import org.springframework.data.redis.cache.RedisCache; | ||
| 17 | +import org.springframework.data.redis.core.RedisOperations; | ||
| 18 | +import org.springframework.util.StopWatch; | ||
| 19 | + | ||
| 20 | +import java.text.SimpleDateFormat; | ||
| 21 | +import java.util.Date; | ||
| 22 | +import java.util.concurrent.Callable; | ||
| 23 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 24 | +import java.util.concurrent.Future; | ||
| 25 | +import java.util.concurrent.FutureTask; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * @Author: boni | ||
| 29 | + * @Date: 2018/8/24-下午2:27 | ||
| 30 | + */ | ||
| 31 | +@Slf4j | ||
| 32 | +public class LayeringCache extends RedisCache { | ||
| 33 | + private final ConcurrentHashMap<String, Future<Ehcache>> layeringL1CacheContainer = new ConcurrentHashMap<>(); | ||
| 34 | + private LayeringCacheProperties layeringCacheProperties; | ||
| 35 | + private LayeringCacheManager layeringCacheManager; | ||
| 36 | + private CacheManager layeringL1CacheManager; | ||
| 37 | + private boolean layerL1Enable; | ||
| 38 | + private String ID; | ||
| 39 | +// private String HOST; | ||
| 40 | +// private String CACHE_STORE; | ||
| 41 | +// private String CACHE_STORE_SYNC; | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + public LayeringCache(LayeringCacheManager layeringCacheManager, String name, byte[] prefix, | ||
| 45 | + RedisOperations<? extends Object, ? extends Object> redisOperations, long expiration) { | ||
| 46 | + super(name, prefix, redisOperations, expiration); | ||
| 47 | + this.layeringCacheManager = layeringCacheManager; | ||
| 48 | + this.layeringCacheProperties = layeringCacheManager.getLayeringCacheProperties(); | ||
| 49 | + this.layerL1Enable = layeringCacheProperties.getCacheL1().isEnable(); | ||
| 50 | + initEhcache(); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Override | ||
| 54 | + public Cache.ValueWrapper get(Object key) { | ||
| 55 | + StopWatch stopWatch = new StopWatch(); | ||
| 56 | + stopWatch.start(); | ||
| 57 | + Ehcache ehCache = null; | ||
| 58 | + if (layerL1Enable) { | ||
| 59 | + ehCache = getL1Cache(super.getName()); | ||
| 60 | + Element value = ehCache.get(key); | ||
| 61 | + if (value != null) { | ||
| 62 | + log.debug("Hit Cache L1 (ehcache) :{}={}", key, value); | ||
| 63 | + return new SimpleValueWrapper(value.getObjectValue()); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + Cache.ValueWrapper wrapper = super.get(key); | ||
| 67 | + if (layerL1Enable && ehCache != null && wrapper != null) { | ||
| 68 | + ehCache.put(new Element(key, wrapper.get())); | ||
| 69 | + log.debug("Hit Cache L2 (redis) :{}={}", key, wrapper); | ||
| 70 | + } | ||
| 71 | + stopWatch.stop(); | ||
| 72 | + log.debug("get use {} ms", stopWatch.getTotalTimeMillis()); | ||
| 73 | + return wrapper; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 77 | + public void put(final Object key, final Object value) { | ||
| 78 | + StopWatch stopWatch = new StopWatch(); | ||
| 79 | + stopWatch.start(); | ||
| 80 | + // 先更新1级然后再更新2级;允许短时间内的数据不一致 | ||
| 81 | + if (layerL1Enable) { | ||
| 82 | + Ehcache ehCache = getL1Cache(super.getName()); | ||
| 83 | + ehCache.put(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties.getCacheL1() | ||
| 84 | + .getLocalTimeToLiveSeconds())); | ||
| 85 | + layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key))); | ||
| 86 | + } | ||
| 87 | + super.put(key, value); | ||
| 88 | + stopWatch.stop(); | ||
| 89 | + log.debug("put use {} ms", stopWatch.getTotalTimeMillis()); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @Override | ||
| 93 | + public void evict(Object key) { | ||
| 94 | + // 先删除2级缓存,然后再删除1级缓存; | ||
| 95 | + super.evict(key); | ||
| 96 | + if (layerL1Enable) { | ||
| 97 | + Ehcache ehCache = getL1Cache(super.getName()); | ||
| 98 | + ehCache.remove(key); | ||
| 99 | + layeringCacheManager.publishMessage(Command.del(this.ID, super.getName(), String.valueOf(key))); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @Override | ||
| 104 | + public Cache.ValueWrapper putIfAbsent(Object key, final Object value) { | ||
| 105 | + if (layerL1Enable) { | ||
| 106 | + Ehcache ehCache = getL1Cache(super.getName()); | ||
| 107 | + ehCache.putIfAbsent(new Element(key, value, false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), layeringCacheProperties | ||
| 108 | + .getCacheL1().getLocalTimeToLiveSeconds())); | ||
| 109 | + layeringCacheManager.publishMessage(Command.set(this.ID, super.getName(), String.valueOf(key))); | ||
| 110 | + } | ||
| 111 | + Cache.ValueWrapper wrapper = super.putIfAbsent(key, value); | ||
| 112 | + return wrapper; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public void clear() { | ||
| 117 | + super.clear(); | ||
| 118 | + if (layerL1Enable) { | ||
| 119 | + Ehcache ehCache = getL1Cache(super.getName()); | ||
| 120 | + ehCache.removeAll(); | ||
| 121 | + layeringCacheManager.publishMessage(Command.rem(this.ID, super.getName())); | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + public void updateL1Cache(Command command) { | ||
| 126 | + if (layerL1Enable && command != null && !this.ID.equals(command.getSrc())) { | ||
| 127 | + switch (command.getOper()) { | ||
| 128 | + case Command.OPT_DEL: | ||
| 129 | + getL1Cache(command.getName()).remove(command.getKey()); | ||
| 130 | + log.debug("Remove Cache L1 {} - {}", command.getName(), command.getKey()); | ||
| 131 | + break; | ||
| 132 | + case Command.OPT_REM: | ||
| 133 | + getL1Cache(command.getName()).removeAll(); | ||
| 134 | + log.debug("Clear Cache L1 {}", command.getName()); | ||
| 135 | + break; | ||
| 136 | + case Command.OPT_SET: | ||
| 137 | + Cache.ValueWrapper wrapper = super.get(command.getKey()); | ||
| 138 | + if (wrapper != null) { | ||
| 139 | + Ehcache ehCache = getL1Cache(super.getName()); | ||
| 140 | + ehCache.put(new Element(command.getKey(), wrapper.get(), false, layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds(), | ||
| 141 | + layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds())); | ||
| 142 | + log.debug("Update Cache L1 {} - {}", command.getKey(), wrapper.get()); | ||
| 143 | + } | ||
| 144 | + break; | ||
| 145 | + default: | ||
| 146 | + break; | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + /** | ||
| 152 | + * 创建本地缓存 | ||
| 153 | + */ | ||
| 154 | + private Ehcache getL1Cache(final String name) { | ||
| 155 | + Future<Ehcache> future = this.layeringL1CacheContainer.get(name); | ||
| 156 | + if (future == null) { | ||
| 157 | + Callable<Ehcache> callable = () -> { | ||
| 158 | + Ehcache cache = layeringL1CacheManager.getCache(name); | ||
| 159 | + if (cache == null) { | ||
| 160 | + CacheConfiguration cacheConfiguration = getCacheConfiguration(); | ||
| 161 | + cacheConfiguration.setName(name); | ||
| 162 | + Ehcache ehcache = new net.sf.ehcache.Cache(cacheConfiguration); | ||
| 163 | + layeringL1CacheManager.addCache(ehcache); | ||
| 164 | + cache = layeringL1CacheManager.getEhcache(name); | ||
| 165 | + } | ||
| 166 | + return cache; | ||
| 167 | + }; | ||
| 168 | + FutureTask<Ehcache> task = new FutureTask<>(callable); | ||
| 169 | + future = this.layeringL1CacheContainer.putIfAbsent(name, task); | ||
| 170 | + if (future == null) { | ||
| 171 | + future = task; | ||
| 172 | + task.run(); | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | + try { | ||
| 176 | + return future.get(); | ||
| 177 | + } catch (Exception e) { | ||
| 178 | + this.layeringL1CacheContainer.remove(name); | ||
| 179 | + throw new CacheException(e); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + | ||
| 185 | + private String getDate() { | ||
| 186 | + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); | ||
| 187 | + | ||
| 188 | + return simpleDateFormat.format(new Date()); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + private CacheConfiguration getCacheConfiguration() { | ||
| 192 | + // Cache | ||
| 193 | + CacheConfiguration cacheConfiguration = new CacheConfiguration(); | ||
| 194 | + cacheConfiguration.setEternal(false); | ||
| 195 | + | ||
| 196 | + PersistenceConfiguration persistenceConfiguration = new PersistenceConfiguration(); | ||
| 197 | + persistenceConfiguration.setStrategy(PersistenceConfiguration.Strategy.NONE.name()); | ||
| 198 | + | ||
| 199 | + cacheConfiguration.persistence(persistenceConfiguration); | ||
| 200 | + cacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU); | ||
| 201 | + cacheConfiguration.setDiskExpiryThreadIntervalSeconds(layeringCacheProperties.getCacheL1().getLocalDiskExpiryThreadIntervalSeconds()); | ||
| 202 | + // 默认false,使用引用.设置为true,避免外部代码修改了缓存对象.造成EhCache的缓存对象也随之改变 | ||
| 203 | + // 但是设置为true后,将引起element的tti不自动刷新.如果直接新建element去覆盖原值.则本地ttl和远程ttl会产生一定的误差. | ||
| 204 | + // 因此,使用时放弃手动覆盖方式刷新本地tti,当本地tti过期后,自动从Redis中再获取即可. | ||
| 205 | + cacheConfiguration.copyOnRead(true); | ||
| 206 | + cacheConfiguration.copyOnWrite(true); | ||
| 207 | + | ||
| 208 | +// CopyStrategyConfiguration copyStrategyConfiguration = new CopyStrategyConfiguration(); | ||
| 209 | +// copyStrategyConfiguration.setClass(MyCopyStrategy.class.getName()); | ||
| 210 | +// copyStrategyConfiguration.setCopyStrategyInstance(new MyCopyStrategy()); | ||
| 211 | + | ||
| 212 | +// cacheConfiguration.addCopyStrategy(copyStrategyConfiguration); | ||
| 213 | + | ||
| 214 | + cacheConfiguration.setTimeToIdleSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToIdleSeconds()); | ||
| 215 | + cacheConfiguration.setTimeToLiveSeconds(layeringCacheProperties.getCacheL1().getLocalTimeToLiveSeconds()); | ||
| 216 | + | ||
| 217 | + return cacheConfiguration; | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + private void initEhcache() { | ||
| 221 | + if (layerL1Enable) { | ||
| 222 | + this.ID = layeringCacheProperties.getCacheL1().getKey() + "." + getDate(); | ||
| 223 | +// this.HOST = Utils.getLocalHostIP(); | ||
| 224 | +// this.CACHE_STORE = layeringCacheProperties.getCacheL1().getKey() | ||
| 225 | +// + layeringCacheProperties.getCacheL1().getSeparator() | ||
| 226 | +// + "cache" | ||
| 227 | +// + layeringCacheProperties.getCacheL1().getSeparator() | ||
| 228 | +// + "store"; | ||
| 229 | +// this.CACHE_STORE_SYNC = this.CACHE_STORE + layeringCacheProperties.getCacheL1().getSeparator() + "sync"; | ||
| 230 | + | ||
| 231 | + Configuration configuration = new Configuration(); | ||
| 232 | + configuration.setName(this.ID); | ||
| 233 | + configuration.setMaxBytesLocalHeap(layeringCacheProperties.getCacheL1().getLocalMaxBytesLocalHeap()); | ||
| 234 | + configuration.setMaxBytesLocalDisk(layeringCacheProperties.getCacheL1().getLocalMaxBytesLocalDisk()); | ||
| 235 | + // DiskStore | ||
| 236 | + // 每次启动设置新的文件地址,以避免重启期间一级缓存未同步,以及单机多应用启动造成EhcacheManager重复的问题. | ||
| 237 | + DiskStoreConfiguration dsc = new DiskStoreConfiguration(); | ||
| 238 | + dsc.setPath(layeringCacheProperties.getCacheL1().getLocalStoreLocation() + this.ID); | ||
| 239 | + configuration.diskStore(dsc); | ||
| 240 | + | ||
| 241 | + CacheConfiguration cacheConfiguration = getCacheConfiguration(); | ||
| 242 | + | ||
| 243 | + configuration.setDefaultCacheConfiguration(cacheConfiguration); | ||
| 244 | + configuration.setDynamicConfig(false); | ||
| 245 | + configuration.setUpdateCheck(false); | ||
| 246 | + | ||
| 247 | + | ||
| 248 | + layeringL1CacheManager = new CacheManager(configuration); | ||
| 249 | + } | ||
| 250 | + } | ||
| 251 | +// | ||
| 252 | +// class MyCopyStrategy implements ReadWriteCopyStrategy<Element> { | ||
| 253 | +// @Override | ||
| 254 | +// public Element copyForWrite(Element value) { | ||
| 255 | +// if (value != null) { | ||
| 256 | +// Object temp = (Serializable) value.getObjectValue(); | ||
| 257 | +// return new Element(value.getObjectKey(), temp); | ||
| 258 | +// } | ||
| 259 | +// return value; | ||
| 260 | +// } | ||
| 261 | +// | ||
| 262 | +// @Override | ||
| 263 | +// public Element copyForRead(Element storedValue) { | ||
| 264 | +// if (storedValue != null) { | ||
| 265 | +// Object temp = (Serializable) storedValue.getObjectValue(); | ||
| 266 | +// return new Element(storedValue.getObjectKey(), temp); | ||
| 267 | +// } | ||
| 268 | +// return storedValue; | ||
| 269 | +// | ||
| 270 | +// } | ||
| 271 | +// } | ||
| 272 | +} |
src/main/java/com/irrigation/icl/cache/core/LayeringCacheLoadCondition.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.core; | ||
| 2 | + | ||
| 3 | +import org.springframework.boot.bind.RelaxedPropertyResolver; | ||
| 4 | +import org.springframework.context.annotation.Condition; | ||
| 5 | +import org.springframework.context.annotation.ConditionContext; | ||
| 6 | +import org.springframework.core.type.AnnotatedTypeMetadata; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @Author: boni | ||
| 10 | + * @Date: 2018/8/24-下午2:52 | ||
| 11 | + */ | ||
| 12 | +public class LayeringCacheLoadCondition implements Condition { | ||
| 13 | + @Override | ||
| 14 | + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { | ||
| 15 | + RelaxedPropertyResolver resolver = new RelaxedPropertyResolver( | ||
| 16 | + context.getEnvironment(), "springext.cache."); | ||
| 17 | + | ||
| 18 | + Boolean enable = resolver.getProperty("enable",Boolean.class); | ||
| 19 | + if(enable == null){ | ||
| 20 | + return false; | ||
| 21 | + } | ||
| 22 | + return enable.booleanValue(); | ||
| 23 | + | ||
| 24 | + } | ||
| 25 | +} |
src/main/java/com/irrigation/icl/cache/core/LayeringCacheManager.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.core; | ||
| 2 | + | ||
| 3 | +import com.irrigation.icl.cache.Command; | ||
| 4 | +import org.springframework.data.redis.cache.RedisCache; | ||
| 5 | +import org.springframework.data.redis.cache.RedisCacheManager; | ||
| 6 | +import org.springframework.data.redis.core.RedisOperations; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @Author: boni | ||
| 10 | + * @Date: 2018/8/24-下午2:29 | ||
| 11 | + */ | ||
| 12 | +public class LayeringCacheManager extends RedisCacheManager { | ||
| 13 | + | ||
| 14 | + private LayeringCacheProperties layeringCacheProperties; | ||
| 15 | + | ||
| 16 | + public LayeringCacheProperties getLayeringCacheProperties() { | ||
| 17 | + return layeringCacheProperties; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public void setLayeringCacheProperties(LayeringCacheProperties layeringCacheProperties) { | ||
| 21 | + this.layeringCacheProperties = layeringCacheProperties; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + public LayeringCacheManager(RedisOperations redisOperations, LayeringCacheProperties layeringCacheProperties) { | ||
| 25 | + super(redisOperations); | ||
| 26 | + this.layeringCacheProperties = layeringCacheProperties; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @SuppressWarnings("unchecked") | ||
| 30 | + @Override | ||
| 31 | + protected RedisCache createCache(String cacheName) { | ||
| 32 | + long expiration = computeExpiration(cacheName); | ||
| 33 | + return new LayeringCache( | ||
| 34 | + this, | ||
| 35 | + cacheName, | ||
| 36 | + (this.isUsePrefix() ? this.getCachePrefix().prefix(cacheName) : null), | ||
| 37 | + this.getRedisOperations(), | ||
| 38 | + expiration); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + //notify other redis clent to update L1 | ||
| 43 | + public void publishMessage(Command command) { | ||
| 44 | + this.getRedisOperations().convertAndSend(this.getLayeringCacheProperties().getCacheL1().getTopic(), command); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +} |
src/main/java/com/irrigation/icl/cache/core/LayeringCacheProperties.java
0 → 100644
| 1 | +package com.irrigation.icl.cache.core; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 5 | + | ||
| 6 | +import java.util.Map; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @Author: boni | ||
| 10 | + * @Date: 2018/8/24-下午2:59 | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +@Data | ||
| 14 | +@ConfigurationProperties(prefix = "springext.cache") | ||
| 15 | +public class LayeringCacheProperties { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * L1缓存配置 | ||
| 19 | + */ | ||
| 20 | + private L1 cacheL1; | ||
| 21 | + /** | ||
| 22 | + * 是否启用缓存 | ||
| 23 | + */ | ||
| 24 | + private boolean enable = true; | ||
| 25 | + /** | ||
| 26 | + * L2级缓存的过期时间,单位秒 | ||
| 27 | + */ | ||
| 28 | + private long expire; | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * L2级缓存的过期时间,name :time | ||
| 33 | + */ | ||
| 34 | + private Map<String, Long> expires; | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + @Data | ||
| 38 | + // ehcache设置 | ||
| 39 | + public static class L1 { | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 是否启用L1缓存 | ||
| 43 | + */ | ||
| 44 | + private boolean enable = false; | ||
| 45 | + /** | ||
| 46 | + * 启用L1缓存后同步的topic | ||
| 47 | + */ | ||
| 48 | + private String topic = "default_L1_sync_topic"; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * cache中使用的key前缀 | ||
| 52 | + */ | ||
| 53 | + private String key = "L1"; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * key分隔符 | ||
| 57 | + */ | ||
| 58 | + private String separator = ":"; | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * L1缓存存储磁盘位置 | ||
| 62 | + */ | ||
| 63 | + private String localStoreLocation = "./cache/"; | ||
| 64 | + /** | ||
| 65 | + * 本地缓存最大内存大小 | ||
| 66 | + */ | ||
| 67 | + private String localMaxBytesLocalHeap = "128M"; | ||
| 68 | + /** | ||
| 69 | + * 本地缓存最大磁盘大小 | ||
| 70 | + */ | ||
| 71 | + private String localMaxBytesLocalDisk = "1024M"; | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 本地缓存过期时间,单位秒,默认10分钟 | ||
| 75 | + */ | ||
| 76 | + private int localTimeToLiveSeconds = 1 * 60; | ||
| 77 | + private int localTimeToIdleSeconds = 0; | ||
| 78 | + /** | ||
| 79 | + * 本地缓存清理周期,单位秒,默认3分钟 | ||
| 80 | + */ | ||
| 81 | + private int localDiskExpiryThreadIntervalSeconds = 90; | ||
| 82 | + } | ||
| 83 | +} |
src/main/java/com/irrigation/icl/entity/PageList.java
| @@ -9,10 +9,14 @@ import lombok.NoArgsConstructor; | @@ -9,10 +9,14 @@ import lombok.NoArgsConstructor; | ||
| 9 | 9 | ||
| 10 | import java.util.List; | 10 | import java.util.List; |
| 11 | 11 | ||
| 12 | +/** | ||
| 13 | + * 分页返回类 | ||
| 14 | + * @param <E> | ||
| 15 | + */ | ||
| 12 | @Data | 16 | @Data |
| 13 | @NoArgsConstructor | 17 | @NoArgsConstructor |
| 14 | @AllArgsConstructor | 18 | @AllArgsConstructor |
| 15 | -@ApiModel(value = "分页返回类") | 19 | +@ApiModel(value = "PageList") |
| 16 | public class PageList<E> { | 20 | public class PageList<E> { |
| 17 | 21 | ||
| 18 | @ApiModelProperty(value = "总页数") | 22 | @ApiModelProperty(value = "总页数") |
src/main/java/com/irrigation/icl/entity/PageParam.java
| @@ -6,10 +6,13 @@ import lombok.AllArgsConstructor; | @@ -6,10 +6,13 @@ import lombok.AllArgsConstructor; | ||
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | import lombok.NoArgsConstructor; | 7 | import lombok.NoArgsConstructor; |
| 8 | 8 | ||
| 9 | +/** | ||
| 10 | + * 分页参数类 | ||
| 11 | + */ | ||
| 9 | @Data | 12 | @Data |
| 10 | @NoArgsConstructor | 13 | @NoArgsConstructor |
| 11 | @AllArgsConstructor | 14 | @AllArgsConstructor |
| 12 | -@ApiModel(value = "分页参数类") | 15 | +@ApiModel(value = "PageParam") |
| 13 | public class PageParam { | 16 | public class PageParam { |
| 14 | 17 | ||
| 15 | @ApiModelProperty(value = "当前页") | 18 | @ApiModelProperty(value = "当前页") |
src/main/java/com/irrigation/icl/entity/RestResult.java
| @@ -10,14 +10,18 @@ import lombok.AllArgsConstructor; | @@ -10,14 +10,18 @@ import lombok.AllArgsConstructor; | ||
| 10 | import lombok.Data; | 10 | import lombok.Data; |
| 11 | import lombok.NoArgsConstructor; | 11 | import lombok.NoArgsConstructor; |
| 12 | 12 | ||
| 13 | +/** | ||
| 14 | + * 公共返回类 | ||
| 15 | + * @param <T> | ||
| 16 | + */ | ||
| 13 | @Data | 17 | @Data |
| 14 | @AllArgsConstructor | 18 | @AllArgsConstructor |
| 15 | @NoArgsConstructor | 19 | @NoArgsConstructor |
| 16 | -@ApiModel(value = "公共返回类") | 20 | +@ApiModel(value = "RestResult") |
| 17 | public class RestResult<T> { | 21 | public class RestResult<T> { |
| 18 | - @ApiModelProperty(value = "返回编码类型") | 22 | + @ApiModelProperty(value = "返回编码类型",example = "200",allowableValues = "200,400") |
| 19 | private int code; | 23 | private int code; |
| 20 | - @ApiModelProperty(value = "返回提示消息") | 24 | + @ApiModelProperty(value = "返回提示消息",example = "成功") |
| 21 | private String message; | 25 | private String message; |
| 22 | @ApiModelProperty(value = "返回请求数据对象") | 26 | @ApiModelProperty(value = "返回请求数据对象") |
| 23 | private T data; | 27 | private T data; |
src/main/java/com/irrigation/icl/enums/ResultEnum.java
| @@ -26,7 +26,7 @@ public enum ResultEnum { | @@ -26,7 +26,7 @@ public enum ResultEnum { | ||
| 26 | private final int code; | 26 | private final int code; |
| 27 | private final String message; | 27 | private final String message; |
| 28 | 28 | ||
| 29 | - private ResultEnum(int code, String message) { | 29 | + ResultEnum(int code, String message) { |
| 30 | this.code = code; | 30 | this.code = code; |
| 31 | this.message = message; | 31 | this.message = message; |
| 32 | } | 32 | } |
src/main/java/com/irrigation/icl/utils/RestResultGeneratorUtil.java
| @@ -11,23 +11,35 @@ public class RestResultGeneratorUtil { | @@ -11,23 +11,35 @@ public class RestResultGeneratorUtil { | ||
| 11 | return result; | 11 | return result; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | + public static <T> RestResult<T> getSuccessResult() { | ||
| 15 | + return getResult(ResultEnum.SUCCESS.getCode(), null, ResultEnum.SUCCESS.getMessage()); | ||
| 16 | + } | ||
| 14 | public static <T> RestResult<T> getSuccessResult(T data) { | 17 | public static <T> RestResult<T> getSuccessResult(T data) { |
| 15 | return getResult(ResultEnum.SUCCESS.getCode(), data, ResultEnum.SUCCESS.getMessage()); | 18 | return getResult(ResultEnum.SUCCESS.getCode(), data, ResultEnum.SUCCESS.getMessage()); |
| 16 | } | 19 | } |
| 17 | 20 | ||
| 18 | - public static RestResult<String> getSuccessResult() { | ||
| 19 | - return getResult(ResultEnum.SUCCESS.getCode(), null, ResultEnum.SUCCESS.getMessage()); | 21 | + public static <T> RestResult<T> getSuccessResult(T data,String message) { |
| 22 | + return getResult(ResultEnum.SUCCESS.getCode(), data, message); | ||
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | - public static RestResult<String> getErrorResult(String message) { | 25 | + public static <T> RestResult<T> getSuccessResultMsg(String message) { |
| 26 | + return getResult(ResultEnum.SUCCESS.getCode(), null, message); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +// public static RestResult<String> getErrorResult(String message) { | ||
| 31 | +// return getResult(ResultEnum.ERROR.getCode(), null, message); | ||
| 32 | +// } | ||
| 33 | + | ||
| 34 | + public static <T> RestResult<T> getErrorResult(String message) { | ||
| 23 | return getResult(ResultEnum.ERROR.getCode(), null, message); | 35 | return getResult(ResultEnum.ERROR.getCode(), null, message); |
| 24 | } | 36 | } |
| 25 | 37 | ||
| 26 | - public static RestResult<String> getErrorResult(int code, String message) { | 38 | + public static <T> RestResult<T> getErrorResult(int code, String message) { |
| 27 | return getResult(code, null, message); | 39 | return getResult(code, null, message); |
| 28 | } | 40 | } |
| 29 | 41 | ||
| 30 | - public static RestResult<String> getErrorResult(ResultEnum resultEnum) { | 42 | + public static <T> RestResult<T> getErrorResult(ResultEnum resultEnum) { |
| 31 | return getResult(resultEnum.getCode(), null, resultEnum.getMessage()); | 43 | return getResult(resultEnum.getCode(), null, resultEnum.getMessage()); |
| 32 | } | 44 | } |
| 33 | } | 45 | } |