diff --git a/example/pom.xml b/example/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..003725f524aa8dbcc43d798512a86e49df45819e --- /dev/null +++ b/example/pom.xml @@ -0,0 +1,19 @@ + + + + demo-parent + com.duanledexianxianxian.demo + 1.0-SNAPSHOT + + 4.0.0 + + example + + + 8 + 8 + + + diff --git a/example/src/main/java/com/duanledexianxianxian/example/exception/Main.java b/example/src/main/java/com/duanledexianxianxian/example/exception/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..e273055856aee5aec172ae89d618a7879138306e --- /dev/null +++ b/example/src/main/java/com/duanledexianxianxian/example/exception/Main.java @@ -0,0 +1,10 @@ +package com.duanledexianxianxian.example.exception; + +public class Main { + + public static void main(String[] args) { + UserService userService = new UserServiceImpl(); + userService.getName(); + + } +} diff --git a/example/src/main/java/com/duanledexianxianxian/example/exception/NotFindException.java b/example/src/main/java/com/duanledexianxianxian/example/exception/NotFindException.java new file mode 100644 index 0000000000000000000000000000000000000000..24bc7c4be37ba613926eb18d5ece6e7ec02b552e --- /dev/null +++ b/example/src/main/java/com/duanledexianxianxian/example/exception/NotFindException.java @@ -0,0 +1,11 @@ +package com.duanledexianxianxian.example.exception; + +/** + * @author duanledexianxianxian + */ +public class NotFindException extends RuntimeException { + + public NotFindException(String s) { + super(s); + } +} diff --git a/example/src/main/java/com/duanledexianxianxian/example/exception/UserService.java b/example/src/main/java/com/duanledexianxianxian/example/exception/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..d545d52e70c7b8adb7889c7e8d3ffbc8012c3c37 --- /dev/null +++ b/example/src/main/java/com/duanledexianxianxian/example/exception/UserService.java @@ -0,0 +1,6 @@ +package com.duanledexianxianxian.example.exception; + +public interface UserService { + + String getName() throws NotFindException; +} diff --git a/example/src/main/java/com/duanledexianxianxian/example/exception/UserServiceImpl.java b/example/src/main/java/com/duanledexianxianxian/example/exception/UserServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e99d636fe8d34a581aa7ebf11b036a7e4a97e947 --- /dev/null +++ b/example/src/main/java/com/duanledexianxianxian/example/exception/UserServiceImpl.java @@ -0,0 +1,11 @@ +package com.duanledexianxianxian.example.exception; + +/** + * @author duanledexianxianxian + */ +public class UserServiceImpl implements UserService { + @Override + public String getName() throws NotFindException { + throw new IllegalStateException("name 不存在"); + } +} diff --git a/kafka/kafka.iml b/kafka/kafka.iml deleted file mode 100644 index 7fa819ab37456d475b9e960a2a2f132eb3727870..0000000000000000000000000000000000000000 --- a/kafka/kafka.iml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/kafka/pom.xml b/kafka/pom.xml index 6210217cb623516db04312bdc2d244cd3e40f0f7..1872429127568d35d4aed3c3d5ad5c0724d29bf2 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -20,7 +20,7 @@ com.alibaba fastjson - 1.2.56 + 1.2.79 org.projectlombok @@ -35,7 +35,6 @@ org.apache.commons commons-lang3 - 3.9 diff --git a/pom.xml b/pom.xml index 2e3f0ee1e23f647ccdab9456bb0fceba0588b9f4..a75525fc0def65ab95c587781d6b57059bf7d7f7 100644 --- a/pom.xml +++ b/pom.xml @@ -12,12 +12,14 @@ kafka menu mongo + example + redis org.springframework.boot spring-boot-starter-parent - 2.1.6.RELEASE + 2.6.4 @@ -28,7 +30,6 @@ org.projectlombok lombok - 1.18.10 provided @@ -63,4 +64,4 @@ - \ No newline at end of file + diff --git a/redis/pom.xml b/redis/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..52dfcc23fb2ee411d9a0d93efc6c1997c15e1478 --- /dev/null +++ b/redis/pom.xml @@ -0,0 +1,39 @@ + + + + demo-parent + com.duanledexianxianxian.demo + 1.0-SNAPSHOT + + 4.0.0 + + redis + + + 8 + 8 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-test + + + com.alibaba + fastjson + 1.2.79 + + + org.apache.commons + commons-lang3 + + + + diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/SpringWebApplication.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/SpringWebApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..8a451d620dbd0ce336007830dab9773f982d7a00 --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/SpringWebApplication.java @@ -0,0 +1,18 @@ +package com.duanledexianxianxian.demo.redis; + +import com.apple.eawt.Application; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author duanledexianxianxian + */ +@SpringBootApplication +public class SpringWebApplication { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} + diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/config/RedisConfiguration.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/config/RedisConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..4702833cd2ccd986a69f09ea4b2c57f8f0a62406 --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/config/RedisConfiguration.java @@ -0,0 +1,55 @@ +package com.duanledexianxianxian.demo.redis.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.scripting.ScriptSource; +import org.springframework.scripting.support.ResourceScriptSource; + + +/** + * @author duanledexianxianxian + */ +@Configuration +@Slf4j +public class RedisConfiguration { + public final static String BEAN_NAME_CHECK_AND_SET_SCRIPT = "checkAndSetScript"; + +// @Bean +// public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { +// +// RedisTemplate redisTemplate = new RedisTemplate(); +// RedisSerializer redisSerializer = new StringRedisSerializer(); +// RedisSerializer jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class); +// // key采用String的序列化方式 +// redisTemplate.setKeySerializer(redisSerializer); +// // value的序列化采用jackson +// redisTemplate.setValueSerializer(jacksonSerializer); +// // hash的key也采用String的序列化 +// redisTemplate.setHashKeySerializer(redisSerializer); +// // hash的value也采用jackson +// redisTemplate.setValueSerializer(jacksonSerializer); +// redisTemplate.setConnectionFactory(redisConnectionFactory); +// log.info("RedisTemplate序列化配置,转化方式:" + jacksonSerializer.getClass().getName()); +// return redisTemplate; +// } + + + /** + * 读取脚本文件的方式有很多种,这里只是其中一种 + * + * @return + */ + @Bean(BEAN_NAME_CHECK_AND_SET_SCRIPT) + public RedisScript checkAndSetScript() { + return RedisScript.of(new ClassPathResource("META-INF/scripts/checkandset.lua"), String.class); + } +} diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/controller/RedisController.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/controller/RedisController.java new file mode 100644 index 0000000000000000000000000000000000000000..74521b5458e7ee10f3e01f62e0096af5a65a05de --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/controller/RedisController.java @@ -0,0 +1,35 @@ +package com.duanledexianxianxian.demo.redis.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +/** + * redis测试相关 + * + * @author duanledexianxianxian + */ +@RestController +@RequestMapping("/api/vi/redis") +@Slf4j +public class RedisController { + + + /** + * Test redis map. + * + * @return the map + */ + @GetMapping("/test1") + public Map testRedis() { + return null; + } +} diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/RedisHelper.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/RedisHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..cc6cf11b2fc6895f97fb4059d1d8db0a5104284c --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/RedisHelper.java @@ -0,0 +1,76 @@ +package com.duanledexianxianxian.demo.redis.helper; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.core.script.RedisScript; + +import java.util.List; +import java.util.Map; + +import static com.duanledexianxianxian.demo.redis.config.RedisConfiguration.BEAN_NAME_CHECK_AND_SET_SCRIPT; +import static java.util.Arrays.asList; + +/** + * @author duanledexianxianxian + */ +public class RedisHelper { + private final StringRedisTemplate StringRedisTemplate; + private final RedisScript checkAndSetScript; + + + private T carriedLuaScript(Class resultCls, String script, List keys, Object... args) { + DefaultRedisScript redisScript = new DefaultRedisScript<>(script, resultCls); + return StringRedisTemplate.execute(redisScript, keys, args); + } + + private RedisHelper() { + // It is ideal to configure a single instance of DefaultRedisScript in your application context to avoid re-calculation of the script’s SHA1 on every script run. + StringRedisTemplate = SpringContextHelper.getBean(StringRedisTemplate.class); + checkAndSetScript = SpringContextHelper.getBean(BEAN_NAME_CHECK_AND_SET_SCRIPT); + } + + public static RedisHelper getInstance() { + return RedisHelperInstance.INSTANCE; + } + + private static class RedisHelperInstance { + /** + * The constant INSTANCE. + */ + private static final RedisHelper INSTANCE = new RedisHelper(); + } + + + /** + * 批量检查某个数值并且减去相应值 + *

+ * todo 现在参数类型写死的,需使用泛型进行通用处理 + * + * @param paramsMap + * @return + */ + public Map batchCheckNum(Map paramsMap) { + if (paramsMap.isEmpty()) { + return null; + } + + // 将map转成list + List keys = Lists.newArrayList(paramsMap.keySet()); + List values = Lists.newArrayList(paramsMap.values()); + + String result = StringRedisTemplate.execute(checkAndSetScript, keys, values.toArray()); + if (StringUtils.isNotBlank(result)) { + // todo 此处优化 + return JSONObject.parseObject(result,new TypeReference>() {}); + } + return Maps.newHashMap(); + + } +} diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/SpringContextHelper.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/SpringContextHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..9f94cbb512861ca94bbfd4c27341a5256ce455dc --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/helper/SpringContextHelper.java @@ -0,0 +1,126 @@ +package com.duanledexianxianxian.demo.redis.helper; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Locale; + +/** + * spring上下文工具类 + * + * @author duanledexianxianxian + */ +@Component +public class SpringContextHelper implements ApplicationContextAware { + + + /** + * The constant invocation. + */ + private static ApplicationContext context = null; + /** + * 是否为开发模式,方便在代码中获取进行判断 + */ + private static boolean isDevModel = false; + + public static boolean isDevModel() { + return isDevModel; + } + + public static void setIsDevModel(boolean isDevModel) { + SpringContextHelper.isDevModel = isDevModel; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context = applicationContext; + } + + /** + * Gets bean. + * 线程中可以使用 + * + * @param the type parameter + * @param beanName the bean name + * @return the bean + */ + public static T getBean(String beanName) { + return (T) context.getBean(beanName); + } + + + /** + * Gets bean. + * + * @param the type parameter + * @param className the class name + * @return the bean + */ + public static T getBean(Class className) { + return context.getBean(className); + } + + /** + * Gets message. + * + * @param key the key + * @return the message + */ + public static String getMessage(String key) { + Locale locale = LocaleContextHolder.getLocale(); + return context.getMessage(key, new Object[]{}, key, locale); + } + + /** + * Gets message. + * 国际化使用 + * + * @param key the key + * @param locale the locale + * @return the message + */ + public static String getMessage(String key, Locale locale) { + return getMessage(key, new Object[]{}, locale); + } + + + /** + * Gets message. + * + * @param key the key + * @param param the param + * @return the message + */ + public static String getMessage(String key, Object[] param) { + Locale locale = LocaleContextHolder.getLocale(); + return context.getMessage(key, param, key, locale); + } + + /** + * Gets message. + * + * @param key the key + * @param param the param + * @param locale the locale + * @return the message + */ + public static String getMessage(String key, Object[] param, Locale locale) { + return context.getMessage(key, param, key, locale); + } + + + /** + * 获取当前环境 + * + * @return the active message + */ + public static String getActiveProfile() { + return context.getEnvironment().getActiveProfiles()[0]; + } + + +} diff --git a/redis/src/main/java/com/duanledexianxianxian/demo/redis/service/RedisService.java b/redis/src/main/java/com/duanledexianxianxian/demo/redis/service/RedisService.java new file mode 100644 index 0000000000000000000000000000000000000000..ad9b452bbba98769e8f75d988c7fabba2e923385 --- /dev/null +++ b/redis/src/main/java/com/duanledexianxianxian/demo/redis/service/RedisService.java @@ -0,0 +1,108 @@ +package com.duanledexianxianxian.demo.redis.service; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.Feature; +import com.duanledexianxianxian.demo.redis.helper.RedisHelper; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Service; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * redis相关测试服务类 + * + * @author duanledexianxianxian + */ +@Service +public class RedisService { + @Autowired + private RedisTemplate redisTemplate; + + private T carriedLuaScript(Class resultCls, String script, List keys, Object... args) { + DefaultRedisScript redisScript = new DefaultRedisScript<>(script, resultCls); + return redisTemplate.execute(redisScript, keys, args); + } + + + /** + * 传说中的狂把子 hello world + * + * @return string string + */ + public String testRedis1() { + return carriedLuaScript(String.class, "return 'Hello Redis' ", null); + } + + + /** + * 测试有参数的情况 + *

+ * 在redis中新建了stock的key为: stock:1=20 + * + * @param num the num + * @return long long + */ + public Long testRedis2(Long num) { + String key = "stock:1"; + redisTemplate.opsForValue().set(key, "20"); + String script = "local stock=tonumber(redis.call('GET',KEYS[1]));" + "local num=tonumber(ARGV[1]);" + "if(stock >= num) then " + "return redis.call('incrby',KEYS[1],0-num);" + "end;" + "return -1;"; + return carriedLuaScript(Long.class, script, Collections.singletonList(key), String.valueOf(num)); + } + + + /** + * 批量操作 + * + * @param paramsMap the params map + * @return long string + */ + public Map testRedis3(Map paramsMap) { + // 初始化数据 + Map initDataMap = Maps.newHashMap(); + initDataMap.put("stock:1", "20"); + initDataMap.put("stock:2", "100"); + initDataMap.put("stock:3", "0"); + redisTemplate.opsForValue().multiSet(initDataMap); + + if (paramsMap.isEmpty()) { + return null; + } + + // 将map转成list + List keys = Lists.newArrayList(paramsMap.keySet()); + List values = Lists.newArrayList(paramsMap.values()); + + String script = "" + "local keys,values = KEYS,ARGV " + "local result = {s='ss'}; " + "for i, v in ipairs(keys) do " + " local stock = tonumber(redis.call('GET', v));" + " local num = tonumber(values[i]);" + " if (stock >= num) then" + " result[v]=redis.call('incrby', v, 0 - num);" + " else " + " result[v]=-1;" + " end " + "end " + "redis.log(redis.LOG_NOTICE,'hello world') " + "for k,v in pairs(result) do\n" + " redis.log(redis.LOG_NOTICE, k,result[k]) " + "end " + "return cjson.encode(result);"; + String result = carriedLuaScript(String.class, script, keys, values.toArray()); + Map map = JSONObject.parseObject(result, Map.class); + return map; + } + + + /** + * 调用封装之后的批量操作 + * 关于集群 + * 方法一:slot需要自己通过key控制 + * redis中只需要{}中值一样,则会分配到相同的slots + * 方法二:使用一个batchId作为key value:{key1:value1,key2:value2...} + * 方法很多 + * + * @param paramsMap + * @return + */ + public Map testRedis4(Map paramsMap) { + return RedisHelper.getInstance().batchCheckNum(paramsMap); + } + + +} diff --git a/redis/src/main/resources/META-INF/scripts/checkandset.lua b/redis/src/main/resources/META-INF/scripts/checkandset.lua new file mode 100644 index 0000000000000000000000000000000000000000..f90b40c90e9ed4130f0038602f07dc3cbae26c77 --- /dev/null +++ b/redis/src/main/resources/META-INF/scripts/checkandset.lua @@ -0,0 +1,17 @@ +local keys, values = KEYS, ARGV +local result = { }; +-- 脚本也可以优化 先mget一次性查询key对应的值,然后在一个个去比对 +for i, v in ipairs(keys) do + local stock = tonumber(redis.call('GET', v)); + local num = tonumber(values[i]); + if (stock >= num) then + result[v] = redis.call('incrby', v, 0 - num); + else + result[v] = -1; + end +end +-- redis.log(redis.LOG_NOTICE, 'hello world') +--for k, v in pairs(result) do +-- redis.log(redis.LOG_NOTICE, k, result[k]) +--end +return cjson.encode(result); diff --git a/redis/src/main/resources/application.yml b/redis/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..731076e3f89b16bda29fa5957602c79f04290065 --- /dev/null +++ b/redis/src/main/resources/application.yml @@ -0,0 +1,7 @@ +spring: + redis: + host: 119.97.172.140 + port: 6379 + password: '!dev!dev!' + database: 10 +debug: true diff --git a/redis/src/test/java/com/duanledexianxianxian/demo/redis/service/RedisServiceTest.java b/redis/src/test/java/com/duanledexianxianxian/demo/redis/service/RedisServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b2e5519fd72b5249fe0d425fa782e7f2f857077f --- /dev/null +++ b/redis/src/test/java/com/duanledexianxianxian/demo/redis/service/RedisServiceTest.java @@ -0,0 +1,87 @@ +package com.duanledexianxianxian.demo.redis.service; + +import com.google.common.collect.Maps; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.Map; + + +// Junit5使用ExtendWith加载Spring测试模块 +@ExtendWith(SpringExtension.class) +@SpringBootTest +class RedisServiceTest { + + @Autowired + RedisService redisService; + @Autowired + StringRedisTemplate redisTemplate; + + @Test + void testTestRedis1() { + String result = redisService.testRedis1(); + Assertions.assertEquals("Hello Redis", result); + } + + @Test + void testTestRedis2() { + Long result = redisService.testRedis2(10L); + Assertions.assertEquals(10L, result); + } + + + @Test + void testTestRedis3() { + Long result = redisService.testRedis2(30L); + Assertions.assertEquals(-1, result); + } + + @Test + void testTestRedis4() { + Long result = redisService.testRedis2(19L); + Assertions.assertEquals(1L, result); + } + + + @Test + void testTestRedis5() { + Map paramsMap = Maps.newHashMap(); + paramsMap.put("stock:1", "20"); + paramsMap.put("stock:2", "300"); + paramsMap.put("stock:3", "300"); + Map result = redisService.testRedis3(paramsMap); + System.out.println("result:" + result); + } + + @Test + void testTestRedis6() { + // 初始化数据 + Map initDataMap = Maps.newHashMap(); + initDataMap.put("stock:1", "20"); + initDataMap.put("stock:2", "100"); + initDataMap.put("stock:3", "0"); + initDataMap.put("stock:4", "40"); + redisTemplate.opsForValue().multiSet(initDataMap); + Map paramsMap = Maps.newHashMap(); + paramsMap.put("stock:1", "20"); + paramsMap.put("stock:2", "300"); + paramsMap.put("stock:3", "300"); + paramsMap.put("stock:4", "2"); + Map result = redisService.testRedis4(paramsMap); + + Assertions.assertEquals(result.get("stock:1"), "0"); + Assertions.assertEquals(result.get("stock:2"), "-1"); + Assertions.assertEquals(result.get("stock:3"), "-1"); + Assertions.assertEquals(result.get("stock:4"), "38"); + } + + +} + +//Generated with love by TestMe :) Please report issues and submit feature requests at: http://weirddev.com/forum#!/testme