From 90a8fd4a541e231f44f3c1c8615a221e4a21e953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E9=B9=8F=E8=BE=89?= <18322780655@163.com> Date: Fri, 14 Jun 2024 15:28:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/LimitSubmit.java | 22 + .../controller/PayController.java | 17 + .../exception/GlobalExceptionHandler.java | 42 ++ .../interceptor/LimitSubmitAspect.java | 181 ++++++ .../interceptor/WebAppConfigurer.java | 1 + .../cashierservice/service/PayService.java | 6 +- .../cashierservice/util/RedisConfig.java | 17 + .../cashierservice/util/RedisUtils.java | 587 ++++++++++++++++++ src/main/resources/application-dev.yml | 2 +- .../generator-mapper/generatorConfig.xml | 2 +- 10 files changed, 874 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/annotation/LimitSubmit.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/interceptor/LimitSubmitAspect.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/util/RedisUtils.java diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/annotation/LimitSubmit.java b/src/main/java/com/chaozhanggui/system/cashierservice/annotation/LimitSubmit.java new file mode 100644 index 0000000..2a367fa --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/annotation/LimitSubmit.java @@ -0,0 +1,22 @@ +package com.chaozhanggui.system.cashierservice.annotation; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface LimitSubmit { + String key() ; + /** + * 默认 10s + */ + int limit() default 30; + + /** + * 请求完成后 是否一直等待 + * true则等待 + * @return + */ + boolean needAllWait() default true; +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java index a830c83..96d10d9 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java @@ -1,8 +1,10 @@ package com.chaozhanggui.system.cashierservice.controller; +import com.chaozhanggui.system.cashierservice.annotation.LimitSubmit; import com.chaozhanggui.system.cashierservice.entity.TbOrderDetail; import com.chaozhanggui.system.cashierservice.entity.dto.ReturnGroupOrderDto; import com.chaozhanggui.system.cashierservice.service.PayService; +import com.chaozhanggui.system.cashierservice.sign.CodeEnum; import com.chaozhanggui.system.cashierservice.sign.Result; import com.chaozhanggui.system.cashierservice.util.IpUtil; import lombok.extern.slf4j.Slf4j; @@ -47,6 +49,7 @@ public class PayController { * @return */ @RequestMapping("scanpay") + @LimitSubmit(key = "scanpay:%s") public Result scanpay(HttpServletRequest request, @RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @@ -68,7 +71,9 @@ public class PayController { * @param memberId * @return */ + @GetMapping("accountPay") + @LimitSubmit(key = "accountPay:%s") public Result accountPay(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -91,6 +96,7 @@ public class PayController { * @return */ @GetMapping("quickPay") + @LimitSubmit(key = "quickPay:%s") public Result quickPay(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -153,6 +159,7 @@ public class PayController { * @return */ @GetMapping("memberScanPay") + @LimitSubmit(key = "memberScanPay:%s") public Result memberScanPay(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -173,6 +180,7 @@ public class PayController { * @return */ @GetMapping("cashPay") + @LimitSubmit(key = "cashPay:%s") public Result cashPay(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -192,6 +200,7 @@ public class PayController { * @return */ @GetMapping("bankPay") + @LimitSubmit(key = "bankPay:%s") public Result bankPay(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -202,6 +211,7 @@ public class PayController { @RequestMapping("returnOrder") + @LimitSubmit(key = "returnOrder:%s") public Result returnOrder(@RequestHeader("token") String token, @RequestHeader("loginName") String loginName, @RequestHeader("clientType") String clientType, @@ -223,4 +233,11 @@ public class PayController { public Result returnOrder(@RequestBody ReturnGroupOrderDto param){ return payService.returnGroupOrder(param); } + + + @RequestMapping("test") + @LimitSubmit(key = "testOrder:%s") + public Result testOrder( @RequestParam("orderId") String orderId){ + return Result.success(CodeEnum.SUCCESS); + } } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/exception/GlobalExceptionHandler.java b/src/main/java/com/chaozhanggui/system/cashierservice/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..4a9e39c --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/exception/GlobalExceptionHandler.java @@ -0,0 +1,42 @@ +package com.chaozhanggui.system.cashierservice.exception; + + +import com.chaozhanggui.system.cashierservice.sign.Result; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * 统一异常处理 + * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来 + */ +@ControllerAdvice +public class GlobalExceptionHandler { + + /** + * 使用ExceptionHandler注解声明处理Exception异常 + * + */ + @ResponseBody + @ExceptionHandler(Exception.class) + public Result exception(Exception e) { + // 控制台打印异常 + e.printStackTrace(); + // 返回错误格式信息 + return Result.fail("系统内部错误"); + } + + /** + * 使用ExceptionHandler注解声明处理TestException异常 + * + */ + @ResponseBody + @ExceptionHandler(MsgException.class) + public Result exception(MsgException e) { + // 控制台打印异常 + e.printStackTrace(); + // 返回错误格式信息 + return Result.fail(e.getMessage()); + } + +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/LimitSubmitAspect.java b/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/LimitSubmitAspect.java new file mode 100644 index 0000000..70d9a9b --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/LimitSubmitAspect.java @@ -0,0 +1,181 @@ +package com.chaozhanggui.system.cashierservice.interceptor; + +import cn.hutool.core.util.ObjectUtil; +import com.chaozhanggui.system.cashierservice.annotation.LimitSubmit; +import com.chaozhanggui.system.cashierservice.exception.MsgException; +import com.chaozhanggui.system.cashierservice.util.RedisUtil; +import com.chaozhanggui.system.cashierservice.util.RedisUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.*; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; + +@Component +@Aspect +@Slf4j +public class LimitSubmitAspect { + //封装了redis操作各种方法 + @Autowired + private RedisUtils redisUtil; + + @Pointcut("@annotation(com.chaozhanggui.system.cashierservice.annotation.LimitSubmit)") + private void pay() { + } + + @Pointcut("@annotation(com.chaozhanggui.system.cashierservice.annotation.LimitSubmit)") + private void pay1() { + } + + @Around("pay()") + public Object handleSubmit(ProceedingJoinPoint joinPoint) throws Throwable { + + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = attributes.getRequest(); + + String orderId= request.getParameter("orderId"); + if(ObjectUtil.isEmpty(orderId)||ObjectUtil.isNull(orderId)){ + orderId=request.getParameter("authCode"); + } + + //获取注解信息 + LimitSubmit limitSubmit = method.getAnnotation(LimitSubmit.class); + boolean needAllWait = limitSubmit.needAllWait(); + String redisKey = limitSubmit.key(); + + + int submitTimeLimiter = limitSubmit.limit(); + String key = getRedisKey(joinPoint, redisKey, orderId); + Object result = redisUtil.get(key); + log.info("开始锁定资源信息" + key); + + if (result != null) { + log.info("锁定的值是" + result.toString()); + throw new MsgException("正在处理中, 请勿重复操作"); + } + boolean setResult = redisUtil.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), submitTimeLimiter); + if (!setResult) { + throw new MsgException("1正在处理中, 请勿重复操作"); + } + + + try { + Object proceed = joinPoint.proceed(); + return proceed; + } catch (Throwable e) { + log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(), + joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "NULL", e.getMessage(), e); + throw e; + } finally { + if (!needAllWait) { + redisUtil.del(redisKey); + log.info("删除后的结果: " + redisUtil.get(redisKey)); + } + } + } + + + @AfterReturning("pay1()") + public void AfterReturning(JoinPoint joinPoint) { + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + LimitSubmit limitSubmit = method.getAnnotation(LimitSubmit.class); + String redisKey = limitSubmit.key(); + + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = attributes.getRequest(); + + String orderId= request.getParameter("orderId"); + + String key = getRedisKey1(joinPoint, redisKey, orderId); + log.info("正常释放了锁资源" + key); + // 延时 1s 释放 + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { +// redisUtil.del(key); + log.info("删除后的结果: " + redisUtil.get(redisKey)); + } + } + + @AfterThrowing(pointcut = "pay1()", throwing = "ex") + public void AfterThrowing(JoinPoint joinPoint, Throwable ex) { + + if (!(ex instanceof MsgException)) { + // 抛出的如果不是重复性提交的异常, 则释放锁资源 + + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + LimitSubmit limitSubmit = method.getAnnotation(LimitSubmit.class); + String redisKey = limitSubmit.key(); + + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = attributes.getRequest(); + + String orderId= request.getParameter("orderId"); + + String key = getRedisKey1(joinPoint, redisKey, orderId); + log.info("发生异常释放了锁资源" + key); + // 延时 1s 释放 + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + redisUtil.del(key); + log.info("删除后的结果: " + redisUtil.get(redisKey)); + } + } + } + + /** + * 支持多参数,从请求参数进行处理 + */ + private String getRedisKey(ProceedingJoinPoint joinPoint, String key, String orderId) { + if (key.contains("%s") && orderId != null) { + key = String.format(key, orderId); + } + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + + LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); + String[] parameterNames = discoverer.getParameterNames(method); + if (parameterNames != null) { + for (int i = 0; i < parameterNames.length; i++) { + String item = parameterNames[i]; + if (key.contains("#" + item)) { + key = key.replace("#" + item, joinPoint.getArgs()[i].toString()); + } + } + } + return key.toString(); + } + + private String getRedisKey1(JoinPoint joinPoint, String key, String orderId) { + if (key.contains("%s") && orderId != null) { + key = String.format(key, orderId); + } + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + + LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); + String[] parameterNames = discoverer.getParameterNames(method); + if (parameterNames != null) { + for (int i = 0; i < parameterNames.length; i++) { + String item = parameterNames[i]; + if (key.contains("#" + item)) { + key = key.replace("#" + item, joinPoint.getArgs()[i].toString()); + } + } + } + return key.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/WebAppConfigurer.java b/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/WebAppConfigurer.java index 7fa2aae..f13318c 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/WebAppConfigurer.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/interceptor/WebAppConfigurer.java @@ -20,6 +20,7 @@ public class WebAppConfigurer implements WebMvcConfigurer { .excludePathPatterns("/login/login") .excludePathPatterns("/cloudPrinter/print") .excludePathPatterns("/cloudPrinter/handoverPrint") + .excludePathPatterns("/pay/test") .excludePathPatterns("/order/sendMessage"); } } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java index 708a2eb..eda5443 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java @@ -484,6 +484,7 @@ public class PayService { flow.setShopUserId(user.getId()); flow.setBizCode("accountPay"); flow.setBizName("会员储值卡支付"); + flow.setType("-"); flow.setAmount(orderInfo.getOrderAmount()); flow.setBalance(user.getAmount()); flow.setCreateTime(new Date()); @@ -569,6 +570,7 @@ public class PayService { flow.setShopUserId(user.getId()); flow.setBizCode("accountPay"); flow.setBizName("会员储值卡支付"); + flow.setType("-"); flow.setAmount(orderInfo.getOrderAmount()); flow.setBalance(user.getAmount()); flow.setCreateTime(new Date()); @@ -859,8 +861,9 @@ public class PayService { TbShopUserFlow flow = new TbShopUserFlow(); flow.setShopUserId(user.getId()); flow.setBizCode("accountReturnPay"); + flow.setType("+"); flow.setBizName("会员储值卡退款"); - flow.setAmount(orderInfo.getOrderAmount()); + flow.setAmount(newOrderInfo.getPayAmount()); flow.setBalance(user.getAmount()); flow.setCreateTime(new Date()); tbShopUserFlowMapper.insert(flow); @@ -1108,6 +1111,7 @@ public class PayService { TbShopUserFlow flow = new TbShopUserFlow(); flow.setShopUserId(user.getId()); flow.setBizCode("returnGroupOrder"); + flow.setType("+"); flow.setBizName("会员储值卡退款"); flow.setAmount(param.getRefundAmount()); flow.setBalance(user.getAmount()); diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisConfig.java b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisConfig.java index f7146c5..a6e58c3 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisConfig.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisConfig.java @@ -4,12 +4,16 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; +import java.nio.charset.Charset; + /** * @ClassName RedisConfig * @Author Administrator @@ -80,4 +84,17 @@ public class RedisConfig { container.setConnectionFactory(connectionFactory); return container; } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + // 设置Redis连接工厂 + template.setConnectionFactory(factory); + // 设置默认的Key序列化器为StringRedisSerializer + template.setDefaultSerializer(new StringRedisSerializer()); + // 设置Value序列化器为StringRedisSerializer,并指定字符集编码为UTF-8 + template.setValueSerializer(new StringRedisSerializer(Charset.forName("UTF-8"))); + return template; + } + } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisUtils.java b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisUtils.java new file mode 100644 index 0000000..2672ab2 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisUtils.java @@ -0,0 +1,587 @@ +package com.chaozhanggui.system.cashierservice.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Component +public class RedisUtils { + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + // ============================String============================= + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * + * @param key 键 + * @param by 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key 键 + * @param by 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + // ================================Map================================= + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * @Description 上锁并设置过期时间 + * @Date 15:09 2023/7/7 + * @Param [key, value, time] + * @return boolean + **/ + public boolean setIfAbsent(String key, Object value, long time) { + try { + return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 1f2a3a2..a024993 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 10587 + port: 10589 spring: application: name: cashierService diff --git a/src/main/resources/generator-mapper/generatorConfig.xml b/src/main/resources/generator-mapper/generatorConfig.xml index 067c195..5f1b9ca 100644 --- a/src/main/resources/generator-mapper/generatorConfig.xml +++ b/src/main/resources/generator-mapper/generatorConfig.xml @@ -52,7 +52,7 @@ -