Commit e41c121e authored by duanledexianxianxian's avatar duanledexianxianxian 😁

feat: redis lua

parent 82ae83e2
<?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>demo-parent</artifactId>
<groupId>com.duanledexianxianxian.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
package com.duanledexianxianxian.example.exception;
public class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
userService.getName();
}
}
package com.duanledexianxianxian.example.exception;
/**
* @author duanledexianxianxian
*/
public class NotFindException extends RuntimeException {
public NotFindException(String s) {
super(s);
}
}
package com.duanledexianxianxian.example.exception;
public interface UserService {
String getName() throws NotFindException;
}
package com.duanledexianxianxian.example.exception;
/**
* @author duanledexianxianxian
*/
public class UserServiceImpl implements UserService {
@Override
public String getName() throws NotFindException {
throw new IllegalStateException("name 不存在");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.kafka:spring-kafka:2.2.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-messaging:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.retry:spring-retry:1.2.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.kafka:kafka-clients:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.lz4:lz4-java:1.4.1" level="project" />
<orderEntry type="library" name="Maven: org.xerial.snappy:snappy-java:1.1.7.1" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.56" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.8" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.kafka:spring-kafka-test:2.2.7.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.1.8.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apache.kafka:kafka-clients:test:2.0.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apache.kafka:kafka_2.11:2.0.1" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.9" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.sf.jopt-simple:jopt-simple:5.0.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.yammer.metrics:metrics-core:2.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.scala-lang:scala-library:2.11.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.scala-lang:scala-reflect:2.11.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.typesafe.scala-logging:scala-logging_2.11:3.9.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.101tec:zkclient:0.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apache.zookeeper:zookeeper:3.4.13" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apache.yetus:audience-annotations:0.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apache.kafka:kafka_2.11:test:2.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.9" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.26" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.21" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.21" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.21" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.17.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.1.8.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.11.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.23.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.9.13" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.9.13" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.8.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: javax.xml.bind:jaxb-api:2.3.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.26" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:23.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.0.18" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
</component>
</module>
\ No newline at end of file
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.56</version> <version>1.2.79</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
...@@ -12,12 +12,14 @@ ...@@ -12,12 +12,14 @@
<module>kafka</module> <module>kafka</module>
<module>menu</module> <module>menu</module>
<module>mongo</module> <module>mongo</module>
<module>example</module>
<module>redis</module>
</modules> </modules>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version> <version>2.6.4</version>
</parent> </parent>
<dependencies> <dependencies>
...@@ -28,7 +30,6 @@ ...@@ -28,7 +30,6 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
...@@ -63,4 +64,4 @@ ...@@ -63,4 +64,4 @@
</plugins> </plugins>
</build> </build>
</project> </project>
\ No newline at end of file
<?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>demo-parent</artifactId>
<groupId>com.duanledexianxianxian.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>redis</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
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);
}
}
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<String, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//
// RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// RedisSerializer<String> 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<String> checkAndSetScript() {
return RedisScript.of(new ClassPathResource("META-INF/scripts/checkandset.lua"), String.class);
}
}
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<String, Object> testRedis() {
return null;
}
}
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<String> checkAndSetScript;
private <T> T carriedLuaScript(Class resultCls, String script, List<String> keys, Object... args) {
DefaultRedisScript<T> 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();
}
/**
* 批量检查某个数值并且减去相应值
* <p>
* todo 现在参数类型写死的,需使用泛型进行通用处理
*
* @param paramsMap
* @return
*/
public Map<String, String> batchCheckNum(Map<String, String> paramsMap) {
if (paramsMap.isEmpty()) {
return null;
}
// 将map转成list
List<String> keys = Lists.newArrayList(paramsMap.keySet());
List<String> values = Lists.newArrayList(paramsMap.values());
String result = StringRedisTemplate.execute(checkAndSetScript, keys, values.toArray());
if (StringUtils.isNotBlank(result)) {
// todo 此处优化
return JSONObject.parseObject(result,new TypeReference<Map<String,String>>() {});
}
return Maps.newHashMap();
}
}
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 <T> the type parameter
* @param beanName the bean name
* @return the bean
*/
public static <T> T getBean(String beanName) {
return (T) context.getBean(beanName);
}
/**
* Gets bean.
*
* @param <T> the type parameter
* @param className the class name
* @return the bean
*/
public static <T> T getBean(Class<T> 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];
}
}
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<String, String> redisTemplate;
private <T> T carriedLuaScript(Class resultCls, String script, List<String> keys, Object... args) {
DefaultRedisScript<T> 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);
}
/**
* 测试有参数的情况
* <p>
* 在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<String, Long> testRedis3(Map<String, String> paramsMap) {
// 初始化数据
Map<String, String> 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<String> keys = Lists.newArrayList(paramsMap.keySet());
List<String> 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<String, Long> map = JSONObject.parseObject(result, Map.class);
return map;
}
/**
* 调用封装之后的批量操作
* 关于集群
* 方法一:slot需要自己通过key控制
* redis中只需要{}中值一样,则会分配到相同的slots
* 方法二:使用一个batchId作为key value:{key1:value1,key2:value2...}
* 方法很多
*
* @param paramsMap
* @return
*/
public Map<String, String> testRedis4(Map<String, String> paramsMap) {
return RedisHelper.getInstance().batchCheckNum(paramsMap);
}
}
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);
spring:
redis:
host: 119.97.172.140
port: 6379
password: '!dev!dev!'
database: 10
debug: true
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<String, String> paramsMap = Maps.newHashMap();
paramsMap.put("stock:1", "20");
paramsMap.put("stock:2", "300");
paramsMap.put("stock:3", "300");
Map<String, Long> result = redisService.testRedis3(paramsMap);
System.out.println("result:" + result);
}
@Test
void testTestRedis6() {
// 初始化数据
Map<String, String> 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<String, String> paramsMap = Maps.newHashMap();
paramsMap.put("stock:1", "20");
paramsMap.put("stock:2", "300");
paramsMap.put("stock:3", "300");
paramsMap.put("stock:4", "2");
Map<String, String> 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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment