From 0c1a5ac8054f3fd011380f82ec72f32b495453db Mon Sep 17 00:00:00 2001 From: adorabled4 Date: Sat, 30 Dec 2023 16:12:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DGateway=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/GlobalExceptionHandler.java | 91 +++++++------------ 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/api-gateway/src/main/java/com/dhx/apigateway/global/GlobalExceptionHandler.java b/api-gateway/src/main/java/com/dhx/apigateway/global/GlobalExceptionHandler.java index 27fb61d..401f402 100644 --- a/api-gateway/src/main/java/com/dhx/apigateway/global/GlobalExceptionHandler.java +++ b/api-gateway/src/main/java/com/dhx/apigateway/global/GlobalExceptionHandler.java @@ -1,26 +1,22 @@ package com.dhx.apigateway.global; -import cn.hutool.json.JSONUtil; import com.dhx.apicommon.common.BaseResponse; -import com.dhx.apicommon.common.exception.BusinessException; -import com.dhx.apicommon.common.exception.ErrorCode; import com.dhx.apicommon.util.ResultUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.annotation.Order; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.validation.BindingResult; -import org.springframework.validation.ObjectError; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebExceptionHandler; +import reactor.core.publisher.Mono; -import javax.validation.ConstraintViolationException; -import java.util.List; /** * @author adorabled4 @@ -29,48 +25,31 @@ **/ @Slf4j @ControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler(Exception.class) - public ResponseEntity handleException(Exception e) { - // Log the exception here - log.error(e.getMessage(), e); - BaseResponse baseResponse = new BaseResponse<>(ErrorCode.SYSTEM_ERROR); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(JSONUtil.toJsonStr(baseResponse)); - } - - - /** - * 常见的参数异常处理 - */ - @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, MissingServletRequestParameterException.class, - ConversionFailedException.class, ConstraintViolationException.class, HttpMessageNotReadableException.class}) - public BaseResponse handleMethodArgumentTypeMismatchException(HttpMessageNotReadableException e) { - return ResultUtil.error(ErrorCode.PARAMS_ERROR); - } - - /** - * 处理自定义异常 - */ - @ExceptionHandler(BusinessException.class) - public BaseResponse handleRRException(BusinessException e){ - log.error(e.getMessage(), e); - return ResultUtil.error(e.getCode(),e.getMessage()); - } - - - @ExceptionHandler(MethodArgumentNotValidException.class) - @ResponseBody - public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - BindingResult bindingResult = e.getBindingResult(); - StringBuilder sb = new StringBuilder(); - if (bindingResult.hasErrors()) { - List allErrors = bindingResult.getAllErrors(); - for (ObjectError objectError : allErrors) { - sb.append(objectError.getDefaultMessage()).append(";"); - } +@Order(-1) +public class GlobalExceptionHandler implements WebExceptionHandler { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public Mono handle(ServerWebExchange exchange, Throwable ex) { + ServerHttpResponse response = exchange.getResponse(); + HttpHeaders headers = response.getHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + if (response.isCommitted()) { + return Mono.error(ex); + } + DataBufferFactory bufferFactory = response.bufferFactory(); + response.setStatusCode(HttpStatus.FORBIDDEN); + BaseResponse error = ResultUtil.error(HttpStatus.FORBIDDEN.value(), ex.getMessage()); + log.error("【网关异常】:{}", error); + try { + byte[] errorBytes = objectMapper.writeValueAsBytes(error); + DataBuffer dataBuffer = bufferFactory.wrap(errorBytes); + return response.writeWith(Mono.just(dataBuffer)); + } catch (JsonProcessingException e) { + log.error("JSON序列化异常:{}", e.getMessage()); + return Mono.error(e); } - return ResultUtil.error(ErrorCode.PARAMS_ERROR,sb.toString()); } } From 47d4a2cab36084e42fa1a168820b2d1ecc3a3468 Mon Sep 17 00:00:00 2001 From: adorabled4 Date: Sat, 30 Dec 2023 16:26:07 +0800 Subject: [PATCH 2/4] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=BD=91?= =?UTF-8?q?=E5=85=B3=E8=BF=87=E6=BB=A4=E5=99=A8=E9=93=BE=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/enums/InterfaceStatusEnum.java | 15 +- .../apicommon}/model/enums/UserRoleEnum.java | 9 +- .../dhx/apicommon/model/to/InterfaceTo.java | 55 ++++++- .../com/dhx/apicommon/model/to/UserTo.java | 11 ++ .../InnerUserInterfaceInfoService.java | 10 +- .../com/dhx/apicore/aop/AuthCheckAOP.java | 2 +- .../apicore/model/DO/InterfaceInfoEntity.java | 7 +- .../com/dhx/apicore/model/DO/UserEntity.java | 5 + .../dhx/apicore/model/DTO/CallResultDTO.java | 7 +- .../model/query/InterfaceUpdateQuery.java | 2 +- .../model/vo/InterfaceBasicInfoVO.java | 2 +- .../apicore/model/vo/InterfaceDetailVO.java | 2 +- .../impl/InterfaceInfoServiceImpl.java | 4 +- .../service/impl/LoginServiceImpl.java | 4 +- .../mapper/InterfaceInfoEntityMapper.xml | 24 +-- .../src/main/resources/mapper/UserMapper.xml | 32 ++-- .../com/dhx/apicore/service/ApiDocTest.java | 2 +- .../com/dhx/apicore/service/ApiSDKTest.java | 2 +- .../apigateway/global/SDKRequestFilter.java | 138 +++++++----------- 19 files changed, 168 insertions(+), 165 deletions(-) rename {api-core/src/main/java/com/dhx/apicore => api-common/src/main/java/com/dhx/apicommon}/model/enums/InterfaceStatusEnum.java (75%) rename {api-core/src/main/java/com/dhx/apicore => api-common/src/main/java/com/dhx/apicommon}/model/enums/UserRoleEnum.java (91%) diff --git a/api-core/src/main/java/com/dhx/apicore/model/enums/InterfaceStatusEnum.java b/api-common/src/main/java/com/dhx/apicommon/model/enums/InterfaceStatusEnum.java similarity index 75% rename from api-core/src/main/java/com/dhx/apicore/model/enums/InterfaceStatusEnum.java rename to api-common/src/main/java/com/dhx/apicommon/model/enums/InterfaceStatusEnum.java index 23f4739..89373ec 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/enums/InterfaceStatusEnum.java +++ b/api-common/src/main/java/com/dhx/apicommon/model/enums/InterfaceStatusEnum.java @@ -1,4 +1,4 @@ -package com.dhx.apicore.model.enums; +package com.dhx.apicommon.model.enums; import com.fasterxml.jackson.annotation.JsonCreator; import lombok.AllArgsConstructor; @@ -14,7 +14,7 @@ **/ @Getter @AllArgsConstructor -public enum InterfaceStatusEnum implements BaseEnum { +public enum InterfaceStatusEnum { AVAILABLE(1, "可用"), CLOSED(2, "已关闭"), DEVELOPING(3, "开发中"), @@ -27,7 +27,7 @@ public enum InterfaceStatusEnum implements BaseEnum { static { for (InterfaceStatusEnum status : InterfaceStatusEnum.values()) { - MAP.put(status.getName(), status); + MAP.put(status.getValue(), status); } } @@ -40,13 +40,4 @@ public static InterfaceStatusEnum createByName(String name) { return MAP.get(name); } - @Override - public Integer getValue() { - return this.index; - } - - @Override - public String getName() { - return this.value; - } } diff --git a/api-core/src/main/java/com/dhx/apicore/model/enums/UserRoleEnum.java b/api-common/src/main/java/com/dhx/apicommon/model/enums/UserRoleEnum.java similarity index 91% rename from api-core/src/main/java/com/dhx/apicore/model/enums/UserRoleEnum.java rename to api-common/src/main/java/com/dhx/apicommon/model/enums/UserRoleEnum.java index 6f1d39b..5efe5eb 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/enums/UserRoleEnum.java +++ b/api-common/src/main/java/com/dhx/apicommon/model/enums/UserRoleEnum.java @@ -1,4 +1,4 @@ -package com.dhx.apicore.model.enums; +package com.dhx.apicommon.model.enums; import com.dhx.apicommon.common.exception.BusinessException; import com.dhx.apicommon.common.exception.ErrorCode; @@ -16,7 +16,7 @@ **/ @AllArgsConstructor @Getter -public enum UserRoleEnum implements BaseEnum { +public enum UserRoleEnum{ VISITOR(1, "游客", "visitor"), USER(2, "认证用户", "user"), VIP(3, "会员用户", "vip"), @@ -64,13 +64,8 @@ public static UserRoleEnum findUserRoleByValue(String value) { throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "UserRoleEnum not found. value=" + value); } - @Override public String getName() { return this.role; } - @Override - public Integer getValue() { - return this.index; - } } diff --git a/api-common/src/main/java/com/dhx/apicommon/model/to/InterfaceTo.java b/api-common/src/main/java/com/dhx/apicommon/model/to/InterfaceTo.java index 4209c0d..c59719a 100644 --- a/api-common/src/main/java/com/dhx/apicommon/model/to/InterfaceTo.java +++ b/api-common/src/main/java/com/dhx/apicommon/model/to/InterfaceTo.java @@ -1,10 +1,12 @@ package com.dhx.apicommon.model.to; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.io.Serializable; import java.util.Date; +import java.util.List; /** * @author adorabled4 @@ -29,25 +31,64 @@ public class InterfaceTo implements Serializable { private String description; /** - * 是否免费 + * 花费 */ - private Integer isFree; + private Integer cost; /** - * 接口地址 + * 接口图片 */ - private String url; + private String imageUrl; + + /** + * 接口状态 + */ + private InterfaceStatusEnum status; + + /** + * 接口文档地址 + */ + private String docUrl; /** * 请求方式 */ - private String method; + private String requestMethod; + + /** + * 请求参数 + */ + private String requestParam; + + /** + * 请求头 + */ + private String requestHeaders; + /** + * 调用路径 + */ + private String callPath; + + /** + * 服务地址 + */ + private String serviceAddress; + + /** + * 请求示例 + */ + private String requestExample; + + /** + * 响应示例 + */ + private String responseExample; /** - * 创建人 + * 总调用次数 */ - private String userName; + private Long totalCallCount; private static final long serialVersionUID = 1L; diff --git a/api-common/src/main/java/com/dhx/apicommon/model/to/UserTo.java b/api-common/src/main/java/com/dhx/apicommon/model/to/UserTo.java index e1153e5..f6deb41 100644 --- a/api-common/src/main/java/com/dhx/apicommon/model/to/UserTo.java +++ b/api-common/src/main/java/com/dhx/apicommon/model/to/UserTo.java @@ -1,5 +1,6 @@ package com.dhx.apicommon.model.to; +import com.dhx.apicommon.model.enums.UserRoleEnum; import lombok.Data; import java.io.Serializable; @@ -39,11 +40,21 @@ public class UserTo implements Serializable { */ private String accessKey; + /** + * 用户角色enum + */ + private UserRoleEnum userRole; + /** * sk */ private String secretKey; + /** + * 剩余硬币数量 + */ + private Integer leftCoin; + private static final long serialVersionUID = 1L; @Override diff --git a/api-common/src/main/java/com/dhx/apicommon/service/InnerUserInterfaceInfoService.java b/api-common/src/main/java/com/dhx/apicommon/service/InnerUserInterfaceInfoService.java index 70f87ea..f70511e 100644 --- a/api-common/src/main/java/com/dhx/apicommon/service/InnerUserInterfaceInfoService.java +++ b/api-common/src/main/java/com/dhx/apicommon/service/InnerUserInterfaceInfoService.java @@ -16,13 +16,5 @@ public interface InnerUserInterfaceInfoService { * @param interfaceId 接口id * @return boolean */ - boolean invokeCount(Long userId, Long interfaceId, BaseResponse baseResponse); - - /** - * 获取用户剩余调用次数 - * - * @param userId 用户id - * @return int - */ - int getUserLeftNum(Long userId); + boolean invokeCount(Long userId, Long interfaceId, Integer cost); } diff --git a/api-core/src/main/java/com/dhx/apicore/aop/AuthCheckAOP.java b/api-core/src/main/java/com/dhx/apicore/aop/AuthCheckAOP.java index d5e9119..1a221fa 100644 --- a/api-core/src/main/java/com/dhx/apicore/aop/AuthCheckAOP.java +++ b/api-core/src/main/java/com/dhx/apicore/aop/AuthCheckAOP.java @@ -4,7 +4,7 @@ import com.dhx.apicommon.common.exception.ErrorCode; import com.dhx.apicore.common.annotation.AuthCheck; import com.dhx.apicore.model.DTO.UserDTO; -import com.dhx.apicore.model.enums.UserRoleEnum; +import com.dhx.apicommon.model.enums.UserRoleEnum; import com.dhx.apicore.util.UserHolder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/api-core/src/main/java/com/dhx/apicore/model/DO/InterfaceInfoEntity.java b/api-core/src/main/java/com/dhx/apicore/model/DO/InterfaceInfoEntity.java index d75ad28..aba53a9 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/DO/InterfaceInfoEntity.java +++ b/api-core/src/main/java/com/dhx/apicore/model/DO/InterfaceInfoEntity.java @@ -1,7 +1,7 @@ package com.dhx.apicore.model.DO; import com.baomidou.mybatisplus.annotation.*; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Builder; @@ -57,6 +57,11 @@ public class InterfaceInfoEntity implements Serializable { */ private String docUrl; + /** + * 花费 + */ + private Integer cost; + /** * 请求方式 */ diff --git a/api-core/src/main/java/com/dhx/apicore/model/DO/UserEntity.java b/api-core/src/main/java/com/dhx/apicore/model/DO/UserEntity.java index af69d62..2067bce 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/DO/UserEntity.java +++ b/api-core/src/main/java/com/dhx/apicore/model/DO/UserEntity.java @@ -54,6 +54,11 @@ public class UserEntity implements Serializable { */ private String email; + /** + * 剩余硬币数 + */ + private Long leftCoin; + /** * ak */ diff --git a/api-core/src/main/java/com/dhx/apicore/model/DTO/CallResultDTO.java b/api-core/src/main/java/com/dhx/apicore/model/DTO/CallResultDTO.java index cd0b29f..fecf3b8 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/DTO/CallResultDTO.java +++ b/api-core/src/main/java/com/dhx/apicore/model/DTO/CallResultDTO.java @@ -25,14 +25,9 @@ public class CallResultDTO implements Serializable { */ private Long interfaceId; - /** - * 调用结果 - */ - private BaseResponse baseResponse; - public CallResultDTO(Long userId, Long interfaceId, BaseResponse baseResponse) { + public CallResultDTO(Long userId, Long interfaceId) { this.userId=userId; this.interfaceId=interfaceId; - this.baseResponse=baseResponse; } } diff --git a/api-core/src/main/java/com/dhx/apicore/model/query/InterfaceUpdateQuery.java b/api-core/src/main/java/com/dhx/apicore/model/query/InterfaceUpdateQuery.java index d78d377..5e50bdf 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/query/InterfaceUpdateQuery.java +++ b/api-core/src/main/java/com/dhx/apicore/model/query/InterfaceUpdateQuery.java @@ -1,7 +1,7 @@ package com.dhx.apicore.model.query; import com.dhx.apicore.model.enums.InterfaceCategoryEnum; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceBasicInfoVO.java b/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceBasicInfoVO.java index 545029b..c3f7afb 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceBasicInfoVO.java +++ b/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceBasicInfoVO.java @@ -1,7 +1,7 @@ package com.dhx.apicore.model.vo; import com.dhx.apicore.model.enums.InterfaceCategoryEnum; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import lombok.Data; import java.io.Serializable; diff --git a/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceDetailVO.java b/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceDetailVO.java index 1ca0b18..aef7aa9 100644 --- a/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceDetailVO.java +++ b/api-core/src/main/java/com/dhx/apicore/model/vo/InterfaceDetailVO.java @@ -1,7 +1,7 @@ package com.dhx.apicore.model.vo; import com.dhx.apicore.model.enums.InterfaceCategoryEnum; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import lombok.Data; import java.io.Serializable; diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java index 2719e03..03a2011 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java @@ -17,7 +17,7 @@ import com.dhx.apicore.model.DO.InterfaceVariableInfoEntity; import com.dhx.apicore.model.DTO.InterfaceMetaDataDTO; import com.dhx.apicore.model.enums.InterfaceCategoryEnum; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import com.dhx.apicore.model.query.InterfaceCategoryQuery; import com.dhx.apicore.model.query.InterfaceIdsQuery; import com.dhx.apicore.model.query.InterfaceUpdateQuery; @@ -278,7 +278,7 @@ private InterfaceMetaDataDTO getInterfaceTemplateData(Long id) { // 设置分类信息 Long categoryBitMap = interfaceEntity.getCategoryBitMap(); List interfaceCategoryEnums = CategoryBitMapUtil.parse2String(categoryBitMap); - interfaceMetaDataDTO.setStatus(interfaceEntity.getStatus().getName()); + interfaceMetaDataDTO.setStatus(interfaceEntity.getStatus().getValue()); interfaceMetaDataDTO.setCategories(interfaceCategoryEnums); // 设置version String version = variableInfo.getCallPath().substring(4, 6); diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/LoginServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/LoginServiceImpl.java index 48348eb..d8047e9 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/LoginServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/LoginServiceImpl.java @@ -14,7 +14,7 @@ import com.dhx.apicore.model.DO.UserEntity; import com.dhx.apicore.model.DTO.JwtToken; import com.dhx.apicore.model.DTO.UserDTO; -import com.dhx.apicore.model.enums.UserRoleEnum; +import com.dhx.apicommon.model.enums.UserRoleEnum; import com.dhx.apicore.model.query.EmailVerifyCodeRequest; import com.dhx.apicore.model.query.LoginQuery; import com.dhx.apicore.model.query.RegisterQuery; @@ -33,7 +33,7 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import static com.dhx.apicore.model.enums.UserRoleEnum.*; +import static com.dhx.apicommon.model.enums.UserRoleEnum.*; /** * @author adorabled4 diff --git a/api-core/src/main/resources/mapper/InterfaceInfoEntityMapper.xml b/api-core/src/main/resources/mapper/InterfaceInfoEntityMapper.xml index c474437..7e5a875 100644 --- a/api-core/src/main/resources/mapper/InterfaceInfoEntityMapper.xml +++ b/api-core/src/main/resources/mapper/InterfaceInfoEntityMapper.xml @@ -3,19 +3,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/api-core/src/main/resources/mapper/UserMapper.xml b/api-core/src/main/resources/mapper/UserMapper.xml index ab9f7f0..49855ff 100644 --- a/api-core/src/main/resources/mapper/UserMapper.xml +++ b/api-core/src/main/resources/mapper/UserMapper.xml @@ -3,26 +3,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - user_id,user_name,user_account, + user_id,user_name,user_account,left_coin, avatar_url,gender,password, phone,email,access_key, secret_key,user_role,create_time, diff --git a/api-core/src/test/java/com/dhx/apicore/service/ApiDocTest.java b/api-core/src/test/java/com/dhx/apicore/service/ApiDocTest.java index b412efe..ec22373 100644 --- a/api-core/src/test/java/com/dhx/apicore/service/ApiDocTest.java +++ b/api-core/src/test/java/com/dhx/apicore/service/ApiDocTest.java @@ -1,7 +1,7 @@ package com.dhx.apicore.service; import com.dhx.apicore.model.DTO.InterfaceMetaDataDTO; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import com.dhx.apicore.util.CategoryBitMapUtil; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; diff --git a/api-core/src/test/java/com/dhx/apicore/service/ApiSDKTest.java b/api-core/src/test/java/com/dhx/apicore/service/ApiSDKTest.java index c3afd4c..c1192e6 100644 --- a/api-core/src/test/java/com/dhx/apicore/service/ApiSDKTest.java +++ b/api-core/src/test/java/com/dhx/apicore/service/ApiSDKTest.java @@ -1,6 +1,6 @@ package com.dhx.apicore.service; -import com.dhx.apicore.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; import com.dhx.apicore.util.CategoryBitMapUtil; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; diff --git a/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java b/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java index 08315f9..bd3c57d 100644 --- a/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java +++ b/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java @@ -2,8 +2,10 @@ import cn.hutool.json.JSONUtil; import com.dhx.apicommon.common.BaseResponse; +import com.dhx.apicommon.common.exception.BusinessException; import com.dhx.apicommon.common.exception.ErrorCode; -import com.dhx.apicommon.model.bo.UserInterfaceInfo; +import com.dhx.apicommon.model.enums.InterfaceStatusEnum; +import com.dhx.apicommon.model.enums.UserRoleEnum; import com.dhx.apicommon.model.to.InterfaceTo; import com.dhx.apicommon.model.to.UserTo; import com.dhx.apicommon.service.InnerInterfaceService; @@ -57,53 +59,54 @@ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); RequestPath path = request.getPath(); HttpHeaders headers = request.getHeaders(); - String accessKey = headers.getFirst("accessKey"); + // 请求来自SDK,执行对应流程 if (path.toString().startsWith("/api/")) { + String accessKey = headers.getFirst("accessKey"); UserTo user = innerUserService.getUserEntityByAccessKey(accessKey); - // 请求来自SDK,执行对应流程 - if (!validateUser(headers, accessKey, user)) { - return handleNoAuth(exchange.getResponse()); - } - // 获取路径以及 method InterfaceTo interfaceInfo = innerInterfaceService.getInterfaceInfo(path.value(), request.getMethodValue()); - // 请求的接口不存在 - if (interfaceInfo == null) { - return handleNoInterfaceError(exchange.getResponse()); - } - // 校验用户的剩余可用次数 - int count = innerUserInterfaceInfoService.getUserLeftNum(user.getUserId()); - if (count <= 0) { - return handleNoLeftNum(exchange.getResponse()); - } - UserInterfaceInfo userInterfaceInfo = new UserInterfaceInfo(interfaceInfo.getId(), user.getUserId()); - return handleInvokeInterfaceResponse(exchange, chain, userInterfaceInfo); + validateRequest(headers, accessKey, user, interfaceInfo); + // 获取路径以及 method + return handleInvokeInterfaceResponse(exchange, chain, user, interfaceInfo); } else { return chain.filter(exchange); } } - private boolean validateUser(HttpHeaders headers, String accessKey, UserTo user) { + /** + * 校验调用请求 + * + * @param headers 请求头 + * @param accessKey 访问密钥 + * @param user 用户 + * @param interfaceInfo 接口信息 + */ + private void validateRequest(HttpHeaders headers, String accessKey, UserTo user, InterfaceTo interfaceInfo) { String nonce = headers.getFirst("nonce"); String timestamp = headers.getFirst("timestamp"); String sign = headers.getFirst("sign"); String body = headers.getFirst("body"); + // 时间和当前时间不能超过 5 分钟 + long currentTime = System.currentTimeMillis() / 1000; + final long FIVE_MINUTES = 60 * 5L; + assert timestamp != null; if (StringUtils.isAnyBlank(timestamp, nonce, accessKey, sign)) { - return false; + throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "HMAC signature does not match"); + } + if (currentTime - Long.parseLong(timestamp) >= FIVE_MINUTES) { + throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication"); } - // 判断请求是否合法 if (user == null) { - return false; + throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "账号不存在"); } - if (nonce != null && Long.parseLong(nonce) > 10000L) { - return false; + // 校验accessKey + if (!user.getAccessKey().equals(accessKey)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "HMAC signature cannot be verified"); } - // 时间和当前时间不能超过 5 分钟 - long currentTime = System.currentTimeMillis() / 1000; - final long FIVE_MINUTES = 60 * 5L; - if (timestamp != null && (currentTime - Long.parseLong(timestamp)) >= FIVE_MINUTES) { - return false; + if (user.getUserRole().equals(UserRoleEnum.BAN)) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "该账号已封禁"); } + // 校验签名 // 对比签名是否相同 String secretKey = user.getSecretKey(); String serverSign; @@ -113,25 +116,36 @@ private boolean validateUser(HttpHeaders headers, String accessKey, UserTo user) serverSign = SignUtil.genSign(body, secretKey); } if (sign == null || !sign.equals(serverSign)) { - return false; + throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "非法请求!"); + } + if (user.getLeftCoin() <= 0) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "余额不足,请先充值。"); + } + if (interfaceInfo == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "接口不存在!"); + } + if (interfaceInfo.getStatus() != InterfaceStatusEnum.AVAILABLE) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前接口暂时未开启!"); } - return true; } /** + * 处理调用接口响应 * 进行用户调用统计 => 执行这个方法的时候, 实际上还没有进行路由, 这里只是添加了(处理响应的)逻辑, 并没有执行 * 具体来说,当一个请求到达网关服务后,会先经过一系列的过滤器处理,最终被转发到指定的服务提供者。 * 服务提供者处理完请求后,将响应结果返回给网关服务,此时 handleInvokeInterfaceResponse 方法就会被调用。 * 该方法对响应结果进行了封装和增强,包括对响应内容进行日志记录、接口调用次数统计等操作。增强后的响应结果会被返回给客户端,完成整个路由请求的过程。 * - * @param exchange - * @param chain - * @param userInterfaceInfo - * @return + * @param exchange 交换 + * @param chain 过滤器链 + * @param user 用户信息 + * @param interfaceTo 接口信息 + * @return {@link Mono}<{@link Void}> */ - public Mono handleInvokeInterfaceResponse(ServerWebExchange exchange, GatewayFilterChain chain, UserInterfaceInfo userInterfaceInfo) { - long interfaceInfoId = userInterfaceInfo.getInterfaceId(); - long userId = userInterfaceInfo.getUserId(); + public Mono handleInvokeInterfaceResponse(ServerWebExchange exchange, GatewayFilterChain chain, + UserTo user, InterfaceTo interfaceTo) { + long userId = user.getUserId(); + long interfaceInfoId = interfaceTo.getId(); //拿到 requet ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse originalResponse = exchange.getResponse(); @@ -156,7 +170,7 @@ public Mono writeWith(Publisher body) { DataBufferUtils.release(dataBuffer); String responseStr = new String(content, StandardCharsets.UTF_8); BaseResponse baseResponse = JSONUtil.toBean(responseStr, BaseResponse.class); - innerUserInterfaceInfoService.invokeCount(userId, interfaceInfoId, baseResponse); + innerUserInterfaceInfoService.invokeCount(userId, interfaceInfoId, interfaceTo.getCost()); if (baseResponse.getCode() == 200) { log.info("[callSuccess],ip:{} ,用户ID:{}, 接口ID: {}, 请求参数:{}, 响应结果:{}", request.getRemoteAddress().getHostString(), userId, interfaceInfoId, request.getQueryParams(), new String(content, StandardCharsets.UTF_8)); return bufferFactory.wrap(content); @@ -165,8 +179,6 @@ public Mono writeWith(Publisher body) { return bufferFactory.wrap(content); } })); - } else { - log.error("<--- {} 响应code异常", getStatusCode()); } return super.writeWith(body); } @@ -174,7 +186,6 @@ public Mono writeWith(Publisher body) { return chain.filter(exchange.mutate().response(successDecoratedResponse).build()); } - /** * 非常关键 ! 否则增强的结果不会起作用 * @@ -184,36 +195,6 @@ public Mono writeWith(Publisher body) { public int getOrder() { return 2; // 设置为-1 优先级最高 } - - /** - * 处理没有权限 - * - * @param response - * @return - */ - public Mono handleNoAuth(ServerHttpResponse response) { - response.setStatusCode(HttpStatus.FORBIDDEN); - BaseResponse baseResponse = new BaseResponse<>(ErrorCode.NO_AUTH_ERROR); - byte[] bytes = JSONUtil.toJsonStr(baseResponse).getBytes(StandardCharsets.UTF_8); - DataBuffer buffer = response.bufferFactory().wrap(bytes); // 创建数据缓冲区 - return response.writeWith(Mono.just(buffer)); // 写入响应内容 - } - - - /** - * 处理用户次数不足 - * - * @param response - * @return - */ - private Mono handleNoLeftNum(ServerHttpResponse response) { - response.setStatusCode(HttpStatus.PAYMENT_REQUIRED); - BaseResponse baseResponse = new BaseResponse<>(ErrorCode.POOR_LEFT_NUM); - byte[] bytes = JSONUtil.toJsonStr(baseResponse).getBytes(StandardCharsets.UTF_8); - DataBuffer buffer = response.bufferFactory().wrap(bytes); // 创建数据缓冲区 - return response.writeWith(Mono.just(buffer)); // 写入响应内容 - } - /** * 处理内部异常 * @@ -228,19 +209,6 @@ public Mono handleSystemError(ServerHttpResponse response) { return response.writeWith(Mono.just(buffer)); // 写入响应内容 } - /** - * 处理内部异常 - * - * @param response - * @return - */ - public Mono handleNoInterfaceError(ServerHttpResponse response) { - response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); - BaseResponse baseResponse = new BaseResponse<>(ErrorCode.PARAMS_ERROR, "请求错误,接口不存在!"); - byte[] bytes = JSONUtil.toJsonStr(baseResponse).getBytes(StandardCharsets.UTF_8); - DataBuffer buffer = response.bufferFactory().wrap(bytes); // 创建数据缓冲区 - return response.writeWith(Mono.just(buffer)); // 写入响应内容 - } } From 74040d4f93b81d8b494731f77265e46fcb2d5b21 Mon Sep 17 00:00:00 2001 From: adorabled4 Date: Sat, 30 Dec 2023 16:49:27 +0800 Subject: [PATCH 3/4] =?UTF-8?q?refactor(core):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E7=94=A8=E6=AC=A1=E6=95=B0=E9=80=BB?= =?UTF-8?q?=E8=BE=91,=20=E7=A7=BB=E9=99=A4RabbitMQ=E4=BE=9D=E8=B5=96,=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4UserInterface=E7=9B=B8=E5=85=B3=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dhx/apicommon/constant/MQConstant.java | 23 --- .../service/InnerInterfaceService.java | 11 +- api-core/pom.xml | 5 - .../apicore/listener/CallResultListener.java | 67 -------- .../listener/InterfaceCountListener.java | 55 ------ .../mapper/UserInterfaceInfoEntityMapper.java | 18 -- .../apicore/service/InterfaceInfoService.java | 7 + .../UserInterfaceInfoEntityService.java | 13 -- .../com/dhx/apicore/service/UserService.java | 2 + .../impl/InterfaceInfoServiceImpl.java | 8 +- .../UserInterfaceInfoEntityServiceImpl.java | 22 --- .../apicore/service/impl/UserServiceImpl.java | 6 + .../inner/InnerInterfaceServiceImpl.java | 40 ++--- .../InnerUserInterfaceInfoServiceImpl.java | 159 ++---------------- .../dhx/apicore/task/RefreshLeftNumTask.java | 79 --------- api-core/src/main/resources/application.yml | 6 - .../mapper/UserInterfaceInfoEntityMapper.xml | 23 --- api-gateway/pom.xml | 12 -- .../apigateway/global/SDKRequestFilter.java | 6 +- .../src/main/resources/application-dev.yml | 6 - 20 files changed, 57 insertions(+), 511 deletions(-) delete mode 100644 api-common/src/main/java/com/dhx/apicommon/constant/MQConstant.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/listener/CallResultListener.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/listener/InterfaceCountListener.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/mapper/UserInterfaceInfoEntityMapper.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/service/UserInterfaceInfoEntityService.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/service/impl/UserInterfaceInfoEntityServiceImpl.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/task/RefreshLeftNumTask.java delete mode 100644 api-core/src/main/resources/mapper/UserInterfaceInfoEntityMapper.xml diff --git a/api-common/src/main/java/com/dhx/apicommon/constant/MQConstant.java b/api-common/src/main/java/com/dhx/apicommon/constant/MQConstant.java deleted file mode 100644 index f08c0b4..0000000 --- a/api-common/src/main/java/com/dhx/apicommon/constant/MQConstant.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dhx.apicommon.constant; - -/** - * @author adorabled4 - * @className RabbitMqQueue - * @date : 2023/04/25/ 18:43 - **/ -public class MQConstant { - public static final String INTERFACE_ROUTE_EXCHANGE="sdk.interface"; - public static final String RANDOM_POET_QUEUE="poet.random"; - public static final String IP_ANALYSIS_QUEUE="ip.ana"; - - public static final String NOW_WEATHER_QUEUE="weather.now"; - - public static final String INTERFACE_COUNT_EXCHANGE="count.interface"; - - public static final String INTERFACE_COUNT_QUEUE="call.count"; - - public static final String CALL_RESULT_EXCHANGE = "call.result"; - - public static final String CALL_RESULT_QUEUE="call.result.queue"; - -} diff --git a/api-common/src/main/java/com/dhx/apicommon/service/InnerInterfaceService.java b/api-common/src/main/java/com/dhx/apicommon/service/InnerInterfaceService.java index 4cf13c5..37b0818 100644 --- a/api-common/src/main/java/com/dhx/apicommon/service/InnerInterfaceService.java +++ b/api-common/src/main/java/com/dhx/apicommon/service/InnerInterfaceService.java @@ -12,15 +12,8 @@ public interface InnerInterfaceService { /** * 获取接口信息 * @param method - * @param url + * @param callPath * @return */ - InterfaceTo getInterfaceInfo(String url , String method); - - - /** - * 接口调用次数+1 - * @param interfaceId - */ - void interfaceCallCount(long interfaceId); + InterfaceTo getInterfaceInfo(String callPath , String method); } diff --git a/api-core/pom.xml b/api-core/pom.xml index a60d4c9..216aa1a 100644 --- a/api-core/pom.xml +++ b/api-core/pom.xml @@ -113,11 +113,6 @@ compile - - - org.springframework.boot - spring-boot-starter-amqp - com.google.code.gson gson diff --git a/api-core/src/main/java/com/dhx/apicore/listener/CallResultListener.java b/api-core/src/main/java/com/dhx/apicore/listener/CallResultListener.java deleted file mode 100644 index 9a9b7f3..0000000 --- a/api-core/src/main/java/com/dhx/apicore/listener/CallResultListener.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.dhx.apicore.listener; - -import com.dhx.apicommon.common.exception.BusinessException; -import com.dhx.apicommon.common.exception.ErrorCode; -import com.dhx.apicommon.constant.MQConstant; -import com.dhx.apicore.model.DO.CallResultEntity; -import com.dhx.apicore.model.DTO.CallResultDTO; -import com.dhx.apicore.model.enums.CallResultEnum; -import com.dhx.apicore.service.CallResultEntityService; -import com.dhx.apicore.util.MQUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.ExchangeTypes; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.annotation.Exchange; -import org.springframework.amqp.rabbit.annotation.Queue; -import org.springframework.amqp.rabbit.annotation.QueueBinding; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.Date; - -/** - * @author adorabled4 - * @className CallResultListener - * @date : 2023/08/24/ 10:57 - **/ -@Component -@Slf4j -public class CallResultListener { - - @Resource - CallResultEntityService callResultService; - - /** - * 保存用户调用接口的情况 - * - * @param message - */ - @RabbitListener(bindings = @QueueBinding( - value = @Queue(name = MQConstant.CALL_RESULT_QUEUE), - exchange = @Exchange(name = MQConstant.CALL_RESULT_EXCHANGE, type = ExchangeTypes.DIRECT), - key = MQConstant.CALL_RESULT_QUEUE - )) - public void callCount(Message message) { - try { - CallResultDTO callResultDTO = MQUtil.getData(message, CallResultDTO.class); - CallResultEntity callResult = new CallResultEntity(); - // 设置参数 - callResult.setCallTime(new Date()); - callResult.setUserId(callResult.getUserId()); - callResult.setInterfaceId(callResultDTO.getInterfaceId()); - // 进行统计 - if (callResultDTO.getBaseResponse().getCode() == 200) { - callResult.setSucceed(CallResultEnum.SUCCEED.getIsSucceed()); - } else { - callResult.setSucceed(CallResultEnum.FAILED.getIsSucceed()); - } - boolean save = callResultService.save(callResult); - if(!save){ - throw new BusinessException(ErrorCode.SYSTEM_ERROR,"保存用户调用结果失败"); - } - } catch (RuntimeException e) { - log.error("统计用户调用结果失败{}", e.getMessage()); - } - } -} diff --git a/api-core/src/main/java/com/dhx/apicore/listener/InterfaceCountListener.java b/api-core/src/main/java/com/dhx/apicore/listener/InterfaceCountListener.java deleted file mode 100644 index 3cc0e6f..0000000 --- a/api-core/src/main/java/com/dhx/apicore/listener/InterfaceCountListener.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dhx.apicore.listener; - -import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; -import com.dhx.apicommon.constant.MQConstant; -import com.dhx.apicore.model.DO.InterfaceInfoEntity; -import com.dhx.apicore.service.InterfaceInfoService; -import com.dhx.apicore.util.MQUtil; -import org.springframework.amqp.core.ExchangeTypes; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.annotation.Exchange; -import org.springframework.amqp.rabbit.annotation.Queue; -import org.springframework.amqp.rabbit.annotation.QueueBinding; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.Map; - -/** - * @author adorabled4 - * @className InterfaceCountListener - * @date : 2023/04/30/ 10:12 - **/ -@Component -public class InterfaceCountListener { - - @Resource - InterfaceInfoService interfaceInfoService; - - /** - * 更新 接口 的总调用次数 - * @param message - */ - @RabbitListener(bindings = @QueueBinding( - value = @Queue(name = MQConstant.INTERFACE_COUNT_QUEUE), - exchange = @Exchange(name =MQConstant.INTERFACE_COUNT_EXCHANGE, type = ExchangeTypes.DIRECT), - key=MQConstant.INTERFACE_COUNT_QUEUE - )) - public void callCount(Message message){ - Map param = MQUtil.getParamFromMessage(message); - Object data = param.get("interfaceId"); - if(data instanceof Integer){ - Integer interfaceId = ((Integer) data); - Long id = Long.valueOf(interfaceId); - UpdateWrapper wrapper = new UpdateWrapper<>(); - wrapper.setSql("call_times = call_times +1"); - wrapper.eq("id",id); - // 更新调用次数 - interfaceInfoService.update(wrapper); - // 更新redis排行榜 - interfaceInfoService.addRankScore(id); - } - } - -} diff --git a/api-core/src/main/java/com/dhx/apicore/mapper/UserInterfaceInfoEntityMapper.java b/api-core/src/main/java/com/dhx/apicore/mapper/UserInterfaceInfoEntityMapper.java deleted file mode 100644 index eeef696..0000000 --- a/api-core/src/main/java/com/dhx/apicore/mapper/UserInterfaceInfoEntityMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dhx.apicore.mapper; - -import com.dhx.apicore.model.DO.UserInterfaceInfoEntity; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; - -/** -* @author dhx -* @description 针对表【t_user_interface_info_entity】的数据库操作Mapper -* @createDate 2023-04-12 09:38:35 -* @Entity generator.domain.UserInterfaceInfoEntity -*/ -public interface UserInterfaceInfoEntityMapper extends BaseMapper { - -} - - - - diff --git a/api-core/src/main/java/com/dhx/apicore/service/InterfaceInfoService.java b/api-core/src/main/java/com/dhx/apicore/service/InterfaceInfoService.java index f204889..60f14a3 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/InterfaceInfoService.java +++ b/api-core/src/main/java/com/dhx/apicore/service/InterfaceInfoService.java @@ -86,4 +86,11 @@ public interface InterfaceInfoService extends IService { * @param query query */ void updateInterfaceInfo(InterfaceUpdateQuery query); + + /** + * 增加接口调用此处 + * + * @param interfaceId 接口id + */ + void increaseCount(Long interfaceId); } diff --git a/api-core/src/main/java/com/dhx/apicore/service/UserInterfaceInfoEntityService.java b/api-core/src/main/java/com/dhx/apicore/service/UserInterfaceInfoEntityService.java deleted file mode 100644 index 9bb66cd..0000000 --- a/api-core/src/main/java/com/dhx/apicore/service/UserInterfaceInfoEntityService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dhx.apicore.service; - -import com.dhx.apicore.model.DO.UserInterfaceInfoEntity; -import com.baomidou.mybatisplus.extension.service.IService; - -/** -* @author dhx -* @description 针对表【t_user_interface_info_entity】的数据库操作Service -* @createDate 2023-04-12 09:38:35 -*/ -public interface UserInterfaceInfoEntityService extends IService { - -} diff --git a/api-core/src/main/java/com/dhx/apicore/service/UserService.java b/api-core/src/main/java/com/dhx/apicore/service/UserService.java index 8379792..6170f45 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/UserService.java +++ b/api-core/src/main/java/com/dhx/apicore/service/UserService.java @@ -38,4 +38,6 @@ public interface UserService extends IService { void updateUserInfO(MultipartFile multipartFile, UserUpdateQuery param); void updateUserPwd(String password); + + void reduceCoin(Long userId, Integer cost); } diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java index 03a2011..00bf330 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/InterfaceInfoServiceImpl.java @@ -224,7 +224,7 @@ private void generateDoc(Template template, InterfaceMetaDataDTO api) throws IOE if (!folder.exists()) { ThrowUtil.throwIf(!folder.mkdirs(), ErrorCode.SYSTEM_ERROR, "创建文件夸失败!"); } - String fileName = docPath + "/" + api.getVersion() +"/"+ api.getName() + template.getName().replace(".ftl", ""); + String fileName = docPath + "/" + api.getVersion() + "/" + api.getName() + template.getName().replace(".ftl", ""); FileOutputStream fos = new FileOutputStream(fileName); OutputStreamWriter out = new OutputStreamWriter(fos); template.process(api, out); @@ -298,6 +298,12 @@ public void updateInterfaceInfo(InterfaceUpdateQuery query) { boolean syncResult = sync2ApiInterface(query, query.getInterfaceId()); ThrowUtil.throwIf(!update || !saveOrUpdate || !syncResult, ErrorCode.OPERATION_ERROR, "保存接口信息失败"); } + + @Override + public void increaseCount(Long interfaceId) { + boolean update = update().setSql("total_count = total_count + 1 ").eq("id", interfaceId).update(); + ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新接口调用次数失败!"); + } } diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/UserInterfaceInfoEntityServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/UserInterfaceInfoEntityServiceImpl.java deleted file mode 100644 index b267e11..0000000 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/UserInterfaceInfoEntityServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dhx.apicore.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.dhx.apicore.service.UserInterfaceInfoEntityService; -import com.dhx.apicore.model.DO.UserInterfaceInfoEntity; -import com.dhx.apicore.mapper.UserInterfaceInfoEntityMapper; -import org.springframework.stereotype.Service; - -/** -* @author dhx -* @description 针对表【t_user_interface_info_entity】的数据库操作Service实现 -* @createDate 2023-04-12 09:38:35 -*/ -@Service -public class UserInterfaceInfoEntityServiceImpl extends ServiceImpl - implements UserInterfaceInfoEntityService { - -} - - - - diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java index a7aacc7..3cbc1ae 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java @@ -129,6 +129,12 @@ public void updateUserPwd(String password) { boolean update = update().set("password", handlerPassword).eq("user_id", user.getUserId()).update(); ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新密码失败!"); } + + @Override + public void reduceCoin(Long userId, Integer cost) { + boolean update = update().setSql("coin = coin - " + cost).eq("user_id", userId).update(); + ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新用户硬币数失败失败!"); + } } diff --git a/api-core/src/main/java/com/dhx/apicore/service/inner/InnerInterfaceServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/inner/InnerInterfaceServiceImpl.java index f115ec6..4b0e9a5 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/inner/InnerInterfaceServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/inner/InnerInterfaceServiceImpl.java @@ -1,22 +1,20 @@ package com.dhx.apicore.service.inner; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dhx.apicommon.common.exception.BusinessException; import com.dhx.apicommon.common.exception.ErrorCode; -import com.dhx.apicommon.constant.MQConstant; import com.dhx.apicommon.model.to.InterfaceTo; import com.dhx.apicommon.service.InnerInterfaceService; import com.dhx.apicore.model.DO.InterfaceInfoEntity; +import com.dhx.apicore.model.DO.InterfaceVariableInfoEntity; import com.dhx.apicore.service.InterfaceInfoService; +import com.dhx.apicore.service.InterfaceVariableInfoService; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.dubbo.config.annotation.DubboService; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.core.RabbitTemplate; import javax.annotation.Resource; -import java.util.HashMap; /** * @author adorabled4 @@ -24,13 +22,14 @@ * @date : 2023/04/19/ 14:36 **/ @DubboService +@Slf4j public class InnerInterfaceServiceImpl implements InnerInterfaceService { @Resource InterfaceInfoService interfaceInfoService; @Resource - RabbitTemplate rabbitTemplate; + InterfaceVariableInfoService interfaceVariableInfoService; @Override public InterfaceTo getInterfaceInfo(String url , String method) { @@ -38,23 +37,18 @@ public InterfaceTo getInterfaceInfo(String url , String method) { throw new BusinessException(ErrorCode.PARAMS_ERROR); } QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.like("url", url); - wrapper.eq("method", method); - InterfaceInfoEntity one = interfaceInfoService.getOne(wrapper); - InterfaceTo interfaceTo = BeanUtil.copyProperties(one, InterfaceTo.class); - return interfaceTo; + wrapper.like("call_path", url); + wrapper.eq("request_method", method); + try{ + InterfaceInfoEntity interfaceInfo = interfaceInfoService.getOne(wrapper); + InterfaceVariableInfoEntity variableInfo = interfaceVariableInfoService.findById(interfaceInfo.getId()); + InterfaceTo interfaceTo = BeanUtil.copyProperties(interfaceInfo, InterfaceTo.class); + BeanUtil.copyProperties(variableInfo,interfaceTo); + return interfaceTo; + }catch (RuntimeException e){ + log.info("获取接口信息失败: {}",e.getMessage()); + } + return null; } - /** - * 发送消息到 rabbitmq , 异步处理 接口信息统计 - * @param interfaceId - */ - @Override - public void interfaceCallCount(long interfaceId) { - // 统一转换成JSON格式字符串传输 - HashMap map = new HashMap<>(); - map.put("interfaceId",interfaceId); - Message message = new Message(JSONUtil.toJsonStr(map).getBytes()); - rabbitTemplate.send(MQConstant.INTERFACE_COUNT_EXCHANGE,MQConstant.INTERFACE_COUNT_QUEUE,message); - } } diff --git a/api-core/src/main/java/com/dhx/apicore/service/inner/InnerUserInterfaceInfoServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/inner/InnerUserInterfaceInfoServiceImpl.java index 69ed3fa..b0baf15 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/inner/InnerUserInterfaceInfoServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/inner/InnerUserInterfaceInfoServiceImpl.java @@ -1,27 +1,13 @@ package com.dhx.apicore.service.inner; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.dhx.apicommon.common.BaseResponse; -import com.dhx.apicommon.constant.MQConstant; import com.dhx.apicommon.service.InnerUserInterfaceInfoService; -import com.dhx.apicore.common.constant.RedisConstant; -import com.dhx.apicore.model.DO.UserInterfaceInfoEntity; -import com.dhx.apicore.model.DTO.CallResultDTO; -import com.dhx.apicore.service.UserInterfaceInfoEntityService; +import com.dhx.apicore.service.InterfaceInfoService; +import com.dhx.apicore.service.UserService; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.apache.dubbo.config.annotation.DubboService; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; -import org.springframework.amqp.core.Message; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.concurrent.TimeUnit; - -import static com.dhx.apicore.common.constant.InterfaceConstant.DEFAULT_LEFT_NUM; /** * @author adorabled4 @@ -31,145 +17,24 @@ @Slf4j @DubboService public class InnerUserInterfaceInfoServiceImpl implements InnerUserInterfaceInfoService { - - @Resource - UserInterfaceInfoEntityService userInterfaceInfoEntityService; - - @Resource - StringRedisTemplate stringRedisTemplate; - @Resource - RedissonClient redissonClient; - + UserService userService; @Resource - RabbitTemplate rabbitTemplate; + InterfaceInfoService interfaceInfoService; @Override - public boolean invokeCount(Long userId, Long interfaceId, BaseResponse baseResponse) { - CallResultDTO callResultDTO = new CallResultDTO(userId, interfaceId, baseResponse); - // 统计调用情况 - Message message = new Message(JSONUtil.toJsonStr(callResultDTO).getBytes()); - rabbitTemplate.send(MQConstant.CALL_RESULT_EXCHANGE,MQConstant.CALL_RESULT_QUEUE,message); - // 统计用户可用次数 - String key = RedisConstant.USER_CALL_LEFTNUM_KEY + userId; - String cachedLeftNum = stringRedisTemplate.opsForValue().get(key); - long leftNum; - boolean shouldUpdateCache = false; // 是否需要更新缓存 - if (StringUtils.isEmpty(cachedLeftNum)) { - // 需要从数据库中查询 - QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.eq("user_id", userId); - UserInterfaceInfoEntity one = userInterfaceInfoEntityService.getOne(wrapper); - if (one == null) { - // 插入新的数据 - UserInterfaceInfoEntity infoEntity = new UserInterfaceInfoEntity(); - infoEntity.setUserId(userId); - infoEntity.setTotalNum(1); - infoEntity.setLeftNum(100 - 1); - leftNum = DEFAULT_LEFT_NUM - 1; - userInterfaceInfoEntityService.save(infoEntity); - } else { - one.setLeftNum(one.getLeftNum() - 1); - one.setTotalNum(one.getTotalNum() + 1); - userInterfaceInfoEntityService.updateById(one); - leftNum = one.getLeftNum() - 1; - } - shouldUpdateCache = true; - } else { - // redis中已经缓存了 - leftNum = Long.parseLong(cachedLeftNum); - if (leftNum <= 0) { - UserInterfaceInfoEntity infoEntity = new UserInterfaceInfoEntity(); - infoEntity.setUserId(userId); - infoEntity.setLeftNum(0); - userInterfaceInfoEntityService.updateById(infoEntity); - shouldUpdateCache = false; - } else { - leftNum -= 1; - shouldUpdateCache = true; - } - } - String lockKey = RedisConstant.LEFTNUM_LOCK_KEY + userId; - RLock lock = redissonClient.getLock(lockKey); + @Transactional + public boolean invokeCount(Long userId, Long interfaceId, Integer cost) { try { - boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS); // 缓存到redis - log.info("leftNum: {}", leftNum); - if (tryLock && shouldUpdateCache) { // 只有获取到锁并且需要更新缓存才进行缓存操作 - stringRedisTemplate.opsForValue().set(key, String.valueOf(leftNum), RedisConstant.LEFT_NUM_TTL, TimeUnit.HOURS); - } - } catch (InterruptedException e) { - log.error("获取锁失败{}", e.getMessage()); - } finally { - if (lock.isHeldByCurrentThread()) { - lock.unlock(); - } + userService.reduceCoin(userId, cost); + interfaceInfoService.increaseCount(interfaceId); + } catch (RuntimeException e) { + log.info("更新用户调用统计异常: {}", e.getMessage()); + return false; } return true; } - @Override - public int getUserLeftNum(Long userId) { - String key = RedisConstant.USER_CALL_LEFTNUM_KEY + userId; - String cachedLeftNum = stringRedisTemplate.opsForValue().get(key); - int leftNum = 100; - if (StringUtils.isEmpty(cachedLeftNum)) { - // 需要从数据库中查询 -// RLock lock = redissonClient.getLock("getUserLeftNumRedis:" + interfaceId+":" +userId); - RLock lock = redissonClient.getLock(RedisConstant.LEFTNUM_LOCK_KEY + userId); - try { - lock.lock(); - cachedLeftNum = stringRedisTemplate.opsForValue().get(key); // 再次尝试获取缓存值 - if (StringUtils.isEmpty(cachedLeftNum)) { - QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.eq("user_id", userId); -// wrapper.eq("user_id", userId).eq("interface_id", interfaceId); - UserInterfaceInfoEntity one = userInterfaceInfoEntityService.getOne(wrapper); - if (one == null) { - // 直接返回默认的数量 - return DEFAULT_LEFT_NUM.intValue(); - } - leftNum = one.getLeftNum(); - } else { - leftNum = Integer.parseInt(cachedLeftNum); - } - } finally { - lock.unlock(); - } - } else { - leftNum = Integer.parseInt(cachedLeftNum); - } - return leftNum; - } - -// @Override -// public int getUserLeftNum(Long userId, Long interfaceId) { -// String lockKey = "getUserLeftNum:" + interfaceId + ":" + userId; -// RLock lock = redissonClient.getLock(lockKey); -// try { -// boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS); -// if (tryLock) { -// try { -// UserInterfaceInfoEntity one = userInterfaceInfoEntityService.query().eq("user_id", userId).eq("interface_id", interfaceId).one(); -// if (one.getLeftNum() == null || one.getLeftNum() <= 0) { -// return 0; -// } -// return one.getLeftNum(); -// } finally { -// lock.unlock(); -// } -// } else { -// // 没有获取到锁, 自旋获取锁 -// try { -// Thread.sleep(100); -// } catch (InterruptedException e) { -// throw new RuntimeException(e); -// } -// return getUserLeftNum(userId, interfaceId); -// } -// } catch (InterruptedException e) { -// throw new RuntimeException(e); -// } -// } } diff --git a/api-core/src/main/java/com/dhx/apicore/task/RefreshLeftNumTask.java b/api-core/src/main/java/com/dhx/apicore/task/RefreshLeftNumTask.java deleted file mode 100644 index 801c2cd..0000000 --- a/api-core/src/main/java/com/dhx/apicore/task/RefreshLeftNumTask.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.dhx.apicore.task; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.dhx.apicore.model.DO.UserInterfaceInfoEntity; -import com.dhx.apicore.model.enums.DayStatus; -import com.dhx.apicore.service.UserInterfaceInfoEntityService; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicLong; - -/** - * @author adorabled4 - * @className RefreshLeftNumTask - * @date : 2023/04/19/ 09:56 - **/ -@Component -public class RefreshLeftNumTask { - public static final Integer DEFAULT_FREE_LEFT_NUM = 100; - public static final Integer DEFAULT_FREE_TOTAL_NUM = 100; - - public static final Integer REFRESH_PAGE_SIZE = 1000; - @Resource - ThreadPoolExecutor executor; - @Resource - UserInterfaceInfoEntityService userInterfaceInfoEntityService; - - /** - * 页数 - */ - volatile long pageNum=1; - - /** - * 当前的页码 - */ - volatile AtomicLong currentPage=new AtomicLong(1L); - - - /** - * 每天定时刷新用户的剩余接口调用次数 - */ - @Scheduled(cron = "0 0 0 * * ?") // 每天零点执行 - private void refreshTask(){ - // 分页查询 - Page page = userInterfaceInfoEntityService.query() - .eq("left_num",DEFAULT_FREE_LEFT_NUM) - .page(new Page<>(1, REFRESH_PAGE_SIZE)); - pageNum = page.getPages(); // 获取页数 - executor.execute(()->{ - readAndRefresh(); - }); - pageNum =0; - } - private void readAndRefresh(){ - if(currentPage.longValue()>pageNum){ - return ; - } - ConcurrentMap concurrentMap = new ConcurrentHashMap<>(); - long currentPageNum = currentPage.getAndAdd(1); - List list = userInterfaceInfoEntityService.query().page(new Page<>(currentPageNum, REFRESH_PAGE_SIZE)).getRecords(); - // 将查询结果放入并发集合中 - for (UserInterfaceInfoEntity entity : list) { - concurrentMap.put(entity.getId(), entity); - } - // 遍历并发集合,使用多线程更新数据 - concurrentMap.forEach( (id, entity) -> { - executor.submit(() -> { - userInterfaceInfoEntityService.updateById( - new UserInterfaceInfoEntity(entity.getUserId(), DayStatus.UNUSED) - ); - }); - }); - } -} diff --git a/api-core/src/main/resources/application.yml b/api-core/src/main/resources/application.yml index 2443f8d..3b521f9 100644 --- a/api-core/src/main/resources/application.yml +++ b/api-core/src/main/resources/application.yml @@ -26,12 +26,6 @@ spring: max-idle: 10 # 连接池中的最小空闲连接 min-idle: 0 - rabbitmq: - username: dhx - password: qwer - host: ${host} - port: 5672 # 端口 - virtual-host: / # 虚拟主机 jackson: serialization: FAIL_ON_EMPTY_BEANS: false diff --git a/api-core/src/main/resources/mapper/UserInterfaceInfoEntityMapper.xml b/api-core/src/main/resources/mapper/UserInterfaceInfoEntityMapper.xml deleted file mode 100644 index 2fb5d4b..0000000 --- a/api-core/src/main/resources/mapper/UserInterfaceInfoEntityMapper.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - id,user_id,total_num, - left_num,status,create_time, - update_time,is_delete - - diff --git a/api-gateway/pom.xml b/api-gateway/pom.xml index bac0599..37ee47e 100644 --- a/api-gateway/pom.xml +++ b/api-gateway/pom.xml @@ -42,12 +42,6 @@ test - - - - - - com.dhx api-common @@ -66,12 +60,6 @@ spring-boot-starter-data-redis-reactive - - - org.springframework.boot - spring-boot-starter-amqp - - com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config diff --git a/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java b/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java index bd3c57d..194101b 100644 --- a/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java +++ b/api-gateway/src/main/java/com/dhx/apigateway/global/SDKRequestFilter.java @@ -164,13 +164,15 @@ public Mono writeWith(Publisher body) { if (body instanceof Flux) { return super.writeWith(Mono.fromDirect(body).map(dataBuffer -> { // 统计接口调用 - innerInterfaceService.interfaceCallCount(interfaceInfoId); byte[] content = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(content); DataBufferUtils.release(dataBuffer); String responseStr = new String(content, StandardCharsets.UTF_8); BaseResponse baseResponse = JSONUtil.toBean(responseStr, BaseResponse.class); - innerUserInterfaceInfoService.invokeCount(userId, interfaceInfoId, interfaceTo.getCost()); + boolean invokeCount = innerUserInterfaceInfoService.invokeCount(userId, interfaceInfoId, interfaceTo.getCost()); + if(!invokeCount){ + throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新用户调用异常!"); + } if (baseResponse.getCode() == 200) { log.info("[callSuccess],ip:{} ,用户ID:{}, 接口ID: {}, 请求参数:{}, 响应结果:{}", request.getRemoteAddress().getHostString(), userId, interfaceInfoId, request.getQueryParams(), new String(content, StandardCharsets.UTF_8)); return bufferFactory.wrap(content); diff --git a/api-gateway/src/main/resources/application-dev.yml b/api-gateway/src/main/resources/application-dev.yml index 3765bb6..7681ab3 100644 --- a/api-gateway/src/main/resources/application-dev.yml +++ b/api-gateway/src/main/resources/application-dev.yml @@ -3,12 +3,6 @@ spring: host: 192.168.159.134 port: 6379 password: adorabeld4 - rabbitmq: - username: dhx - host: 192.168.159.134 - port: 5672 # 端口 - virtual-host: / # 虚拟主机 - password: qwer logging: config: classpath:logback.xml level: From 10dd03cbbb6c25f2061a91bee931937b02c40a91 Mon Sep 17 00:00:00 2001 From: adorabled4 Date: Sat, 30 Dec 2023 17:14:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=AF=8F=E6=97=A5=E7=99=BB=E5=BD=95=E9=A2=86=E5=8F=96?= =?UTF-8?q?coin=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DailyCheckInController.java | 72 +++ .../dhx/apicore/manager/RedisLockManager.java | 424 ++++++++++++++++++ .../apicore/mapper/DailyCheckInMapper.java | 18 + .../dhx/apicore/model/DO/DailyCheckIn.java | 106 +++++ .../apicore/service/DailyCheckInService.java | 13 + .../com/dhx/apicore/service/UserService.java | 2 + .../service/impl/DailyCheckInServiceImpl.java | 22 + .../apicore/service/impl/UserServiceImpl.java | 10 +- .../java/com/dhx/apicore/util/MQUtil.java | 54 --- api-core/src/main/resources/application.yml | 10 +- .../resources/mapper/DailyCheckInMapper.xml | 20 + 11 files changed, 686 insertions(+), 65 deletions(-) create mode 100644 api-core/src/main/java/com/dhx/apicore/controller/DailyCheckInController.java create mode 100644 api-core/src/main/java/com/dhx/apicore/manager/RedisLockManager.java create mode 100644 api-core/src/main/java/com/dhx/apicore/mapper/DailyCheckInMapper.java create mode 100644 api-core/src/main/java/com/dhx/apicore/model/DO/DailyCheckIn.java create mode 100644 api-core/src/main/java/com/dhx/apicore/service/DailyCheckInService.java create mode 100644 api-core/src/main/java/com/dhx/apicore/service/impl/DailyCheckInServiceImpl.java delete mode 100644 api-core/src/main/java/com/dhx/apicore/util/MQUtil.java create mode 100644 api-core/src/main/resources/mapper/DailyCheckInMapper.xml diff --git a/api-core/src/main/java/com/dhx/apicore/controller/DailyCheckInController.java b/api-core/src/main/java/com/dhx/apicore/controller/DailyCheckInController.java new file mode 100644 index 0000000..cd08756 --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/controller/DailyCheckInController.java @@ -0,0 +1,72 @@ +package com.dhx.apicore.controller; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dhx.apicommon.common.BaseResponse; +import com.dhx.apicommon.common.exception.BusinessException; +import com.dhx.apicommon.common.exception.ErrorCode; +import com.dhx.apicommon.util.ResultUtil; +import com.dhx.apicore.manager.RedisLockManager; +import com.dhx.apicore.model.DO.DailyCheckIn; +import com.dhx.apicore.model.vo.UserVo; +import com.dhx.apicore.service.DailyCheckInService; +import com.dhx.apicore.service.UserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @Author: QiMu + * @Date: 2023/08/31 11:51:14 + * @Version: 1.0 + * @Description: 签到接口 + */ +@RestController +@RequestMapping("/dailyCheckIn") +@Slf4j +public class DailyCheckInController { + + @Resource + private DailyCheckInService dailyCheckInService; + + @Resource + private UserService userService; + @Resource + private RedisLockManager redisLockManager; + + public static final Long LOGIN_ADD_COIN = 10L; + + + /** + * 签到 + * + * @return {@link BaseResponse}<{@link Boolean}> + */ + @PostMapping("/doCheckIn") + @Transactional(rollbackFor = Exception.class) + public BaseResponse doDailyCheckIn() { + UserVo loginUser = userService.getCurrentUser(); + String redissonLock = ("doDailyCheckIn_" + loginUser.getUserAccount()).intern(); + return redisLockManager.redissonDistributedLocks(redissonLock, () -> { + LambdaQueryWrapper dailyCheckInLambdaQueryWrapper = new LambdaQueryWrapper<>(); + dailyCheckInLambdaQueryWrapper.eq(DailyCheckIn::getUserId, loginUser.getUserId()); + DailyCheckIn dailyCheckIn = dailyCheckInService.getOne(dailyCheckInLambdaQueryWrapper); + if (ObjectUtils.isNotEmpty(dailyCheckIn)) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "签到失败,今日已签到"); + } + dailyCheckIn = new DailyCheckIn(); + dailyCheckIn.setUserId(loginUser.getUserId()); + dailyCheckIn.setAddCoins(LOGIN_ADD_COIN); + boolean dailyCheckInResult = dailyCheckInService.save(dailyCheckIn); + userService.addLeftCoin(loginUser.getUserId(), dailyCheckIn.getAddCoins()); + if (!dailyCheckInResult) { + throw new BusinessException(ErrorCode.OPERATION_ERROR); + } + return ResultUtil.success(true); + }, "签到失败"); + } +} diff --git a/api-core/src/main/java/com/dhx/apicore/manager/RedisLockManager.java b/api-core/src/main/java/com/dhx/apicore/manager/RedisLockManager.java new file mode 100644 index 0000000..aabcdd8 --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/manager/RedisLockManager.java @@ -0,0 +1,424 @@ +package com.dhx.apicore.manager; + +import com.dhx.apicommon.common.exception.BusinessException; +import com.dhx.apicommon.common.exception.ErrorCode; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * @author adorabled4 + * @className RedisLockManager + * @date : 2023/12/30/ 17:09 + **/ +@Component +@Slf4j +public class RedisLockManager { + + @Resource + public RedissonClient redissonClient; + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + return supplier.get(); + } + throw new BusinessException(errorCode.getCode(), errorMessage); + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.error("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, String errorLogTitle, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + return supplier.get(); + } + throw new BusinessException(errorCode.getCode(), errorMessage); + } catch (Exception e) { + log.error(errorLogTitle, e.getMessage()); + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.error("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, Runnable logMessage, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + return supplier.get(); + } + throw new BusinessException(errorCode.getCode(), errorMessage); + } catch (Exception e) { + logMessage.run(); + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.error("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param waitTime 等待时间 + * @param leaseTime 租赁时间 + * @param unit 单元 + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + * @param args args + * @return {@link T} + */ + public T redissonDistributedLocks(long waitTime, long leaseTime, TimeUnit unit, String lockName, Supplier supplier, ErrorCode errorCode, String errorMessage, Object... args) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(waitTime, leaseTime, unit)) { + return supplier.get(); + } + throw new BusinessException(errorCode.getCode(), errorMessage); + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param unit 时间单位 + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + * @param time 时间 + * @return {@link T} + */ + public T redissonDistributedLocks(long time, TimeUnit unit, String lockName, Supplier supplier, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(time, unit)) { + return supplier.get(); + } + throw new BusinessException(errorCode.getCode(), errorMessage); + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, ErrorCode errorCode) { + return redissonDistributedLocks(lockName, supplier, errorCode, errorCode.getMsg()); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorCode 错误代码 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, Runnable logMessage, ErrorCode errorCode) { + return redissonDistributedLocks(lockName, supplier, logMessage, errorCode, errorCode.getMsg()); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @param errorMessage 错误消息 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, String errorMessage) { + return redissonDistributedLocks(lockName, supplier, ErrorCode.OPERATION_ERROR, errorMessage); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier) { + return redissonDistributedLocks(lockName, supplier, ErrorCode.OPERATION_ERROR); + } + + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, String errorLogTitle, Supplier supplier) { + return redissonDistributedLocks(lockName, supplier, errorLogTitle, ErrorCode.OPERATION_ERROR, ErrorCode.OPERATION_ERROR.getMsg()); + } + + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param supplier 供应商 + * @return {@link T} + */ + public T redissonDistributedLocks(String lockName, Supplier supplier, Runnable logMessage) { + return redissonDistributedLocks(lockName, supplier, logMessage, ErrorCode.OPERATION_ERROR); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + runnable.run(); + } else { + throw new BusinessException(errorCode.getCode(), errorMessage); + } + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("lockName:{},unLockId:{} ", lockName, Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, String errorLogTitle, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + runnable.run(); + } else { + throw new BusinessException(errorCode.getCode(), errorMessage); + } + } catch (Exception e) { + log.error(errorLogTitle, e.getMessage()); + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("lockName:{},unLockId:{} ", lockName, Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, Runnable logMessage, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(0, -1, TimeUnit.MILLISECONDS)) { + runnable.run(); + } else { + throw new BusinessException(errorCode.getCode(), errorMessage); + } + } catch (Exception e) { + logMessage.run(); + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("lockName:{},unLockId:{} ", lockName, Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, ErrorCode errorCode) { + redissonDistributedLocks(lockName, runnable, errorCode, errorCode.getMsg()); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, String errorMessage) { + redissonDistributedLocks(lockName, runnable, ErrorCode.OPERATION_ERROR, errorMessage); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable) { + redissonDistributedLocks(lockName, runnable, ErrorCode.OPERATION_ERROR, ErrorCode.OPERATION_ERROR.getMsg()); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + */ + public void redissonDistributedLocks(String lockName, Runnable runnable, Runnable logMessage) { + redissonDistributedLocks(lockName, runnable, logMessage, ErrorCode.OPERATION_ERROR, ErrorCode.OPERATION_ERROR.getMsg()); + } + + /** + * redisson分布式锁 + * + * @param lockName 锁名称 + * @param runnable 可运行 + */ + public void redissonDistributedLocks(String lockName, String errorLogTitle, Runnable runnable) { + redissonDistributedLocks(lockName, runnable, errorLogTitle, ErrorCode.OPERATION_ERROR, ErrorCode.OPERATION_ERROR.getMsg()); + } + + /** + * redisson分布式锁 可自定义 waitTime 、leaseTime、TimeUnit + * + * @param waitTime 等待时间 + * @param leaseTime 租赁时间 + * @param unit 时间单位 + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(long waitTime, long leaseTime, TimeUnit unit, String lockName, Runnable runnable, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(waitTime, leaseTime, unit)) { + runnable.run(); + } else { + throw new BusinessException(errorCode.getCode(), errorMessage); + } + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } + + /** + * redisson分布式锁 可自定义 time 、unit + * + * @param time 时间 + * @param unit 时间单位 + * @param lockName 锁名称 + * @param runnable 可运行 + * @param errorCode 错误代码 + * @param errorMessage 错误消息 + */ + public void redissonDistributedLocks(long time, TimeUnit unit, String lockName, Runnable runnable, ErrorCode errorCode, String errorMessage) { + RLock rLock = redissonClient.getLock(lockName); + try { + if (rLock.tryLock(time, unit)) { + runnable.run(); + } else { + throw new BusinessException(errorCode.getCode(), errorMessage); + } + } catch (Exception e) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, e.getMessage()); + } finally { + if (rLock.isHeldByCurrentThread()) { + log.info("unLock: " + Thread.currentThread().getId()); + rLock.unlock(); + } + } + } +} diff --git a/api-core/src/main/java/com/dhx/apicore/mapper/DailyCheckInMapper.java b/api-core/src/main/java/com/dhx/apicore/mapper/DailyCheckInMapper.java new file mode 100644 index 0000000..ed9f16c --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/mapper/DailyCheckInMapper.java @@ -0,0 +1,18 @@ +package com.dhx.apicore.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.dhx.apicore.model.DO.DailyCheckIn; + +/** +* @author dhx +* @description 针对表【daily_check_in(每日签到表)】的数据库操作Mapper +* @createDate 2023-12-30 17:01:21 +* @Entity com.dhx.apicore.model.DO.DailyCheckIn +*/ +public interface DailyCheckInMapper extends BaseMapper { + +} + + + + diff --git a/api-core/src/main/java/com/dhx/apicore/model/DO/DailyCheckIn.java b/api-core/src/main/java/com/dhx/apicore/model/DO/DailyCheckIn.java new file mode 100644 index 0000000..c78222e --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/model/DO/DailyCheckIn.java @@ -0,0 +1,106 @@ +package com.dhx.apicore.model.DO; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 每日签到表 + * @TableName daily_check_in + */ +@TableName(value ="daily_check_in") +@Data +public class DailyCheckIn implements Serializable { + /** + * id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 签到人 + */ + @TableField(value = "user_id") + private Long userId; + + /** + * 描述 + */ + @TableField(value = "description") + private String description; + + /** + * 签到增加硬币个数 + */ + @TableField(value = "add_coins") + private Long addCoins; + + /** + * 创建时间 + */ + @TableField(value = "create_time") + private Date createTime; + + /** + * 更新时间 + */ + @TableField(value = "update_time") + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + DailyCheckIn other = (DailyCheckIn) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) + && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription())) + && (this.getAddCoins() == null ? other.getAddCoins() == null : this.getAddCoins().equals(other.getAddCoins())) + && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) + && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); + result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode()); + result = prime * result + ((getAddCoins() == null) ? 0 : getAddCoins().hashCode()); + result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); + result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", userId=").append(userId); + sb.append(", description=").append(description); + sb.append(", addPoints=").append(addCoins); + sb.append(", createTime=").append(createTime); + sb.append(", updateTime=").append(updateTime); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/api-core/src/main/java/com/dhx/apicore/service/DailyCheckInService.java b/api-core/src/main/java/com/dhx/apicore/service/DailyCheckInService.java new file mode 100644 index 0000000..d176935 --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/service/DailyCheckInService.java @@ -0,0 +1,13 @@ +package com.dhx.apicore.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.dhx.apicore.model.DO.DailyCheckIn; + +/** +* @author dhx +* @description 针对表【daily_check_in(每日签到表)】的数据库操作Service +* @createDate 2023-12-30 17:01:21 +*/ +public interface DailyCheckInService extends IService { + +} diff --git a/api-core/src/main/java/com/dhx/apicore/service/UserService.java b/api-core/src/main/java/com/dhx/apicore/service/UserService.java index 6170f45..d150d65 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/UserService.java +++ b/api-core/src/main/java/com/dhx/apicore/service/UserService.java @@ -40,4 +40,6 @@ public interface UserService extends IService { void updateUserPwd(String password); void reduceCoin(Long userId, Integer cost); + + void addLeftCoin(Long userId, Long addCoins); } diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/DailyCheckInServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/DailyCheckInServiceImpl.java new file mode 100644 index 0000000..3eb4b13 --- /dev/null +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/DailyCheckInServiceImpl.java @@ -0,0 +1,22 @@ +package com.dhx.apicore.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dhx.apicore.model.DO.DailyCheckIn; +import com.dhx.apicore.mapper.DailyCheckInMapper; +import com.dhx.apicore.service.DailyCheckInService; +import org.springframework.stereotype.Service; + +/** +* @author dhx +* @description 针对表【daily_check_in(每日签到表)】的数据库操作Service实现 +* @createDate 2023-12-30 17:01:21 +*/ +@Service +public class DailyCheckInServiceImpl extends ServiceImpl + implements DailyCheckInService { + +} + + + + diff --git a/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java b/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java index 3cbc1ae..e504b03 100644 --- a/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java +++ b/api-core/src/main/java/com/dhx/apicore/service/impl/UserServiceImpl.java @@ -132,8 +132,14 @@ public void updateUserPwd(String password) { @Override public void reduceCoin(Long userId, Integer cost) { - boolean update = update().setSql("coin = coin - " + cost).eq("user_id", userId).update(); - ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新用户硬币数失败失败!"); + boolean update = update().setSql("left_coin = left_coin - " + cost).eq("user_id", userId).update(); + ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新用户硬币数失败!"); + } + + @Override + public void addLeftCoin(Long userId, Long addCoins) { + boolean update = update().setSql("left_coin = left_coin + " + addCoins).eq("user_id", userId).update(); + ThrowUtil.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新用户硬币数失败!"); } } diff --git a/api-core/src/main/java/com/dhx/apicore/util/MQUtil.java b/api-core/src/main/java/com/dhx/apicore/util/MQUtil.java deleted file mode 100644 index 7070c75..0000000 --- a/api-core/src/main/java/com/dhx/apicore/util/MQUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dhx.apicore.util; - -import cn.hutool.json.JSONUtil; -import com.dhx.apicommon.common.BaseResponse; -import org.springframework.amqp.core.Message; - -import java.nio.charset.StandardCharsets; -import java.util.Map; - -/** - * @author adorabled4 - * @className MessageUtil MQ工具类 => rabbitmq使用二进制来传输消息 - * @date : 2023/04/27/ 14:35 - **/ -public class MQUtil { - - /** - * 转换 baseResponse 到 byte数组 - * - * @param baseResponse - * @return - */ - public static byte[] result2Byte(BaseResponse baseResponse) { - String json = JSONUtil.toJsonStr(baseResponse); - return json.getBytes(StandardCharsets.UTF_8); - } - - - /** - * 获取MQ message中的参数 - * - * @param message - * @return - */ - public static Map getParamFromMessage(Message message) { - byte[] body = message.getBody(); - String s = new String(body); - Map map = JSONUtil.toBean(s, Map.class); - return map; - } - - /** - * 获取指定类型的数据 - * - * @param message 消息 - * @param clazz clazz - * @return {@link T} - */ - public static T getData(Message message, Class clazz) { - byte[] body = message.getBody(); - String string = new String(body, StandardCharsets.UTF_8); - return JSONUtil.toBean(string, clazz); - } -} diff --git a/api-core/src/main/resources/application.yml b/api-core/src/main/resources/application.yml index 3b521f9..e3d953f 100644 --- a/api-core/src/main/resources/application.yml +++ b/api-core/src/main/resources/application.yml @@ -86,12 +86,4 @@ dhx: template: gen: doc-path: ../api-doc/docs/gen - sdk-path: ../api-sdk/src/main/java/com/dhx/apisdk/client -alibaba: - cloud: - oss: - endpoint: https://oss-cn-beijing.aliyuncs.com - bucket: dhx-blog - domain: https://oss.dhx.icu/ - access-key: LTAI5tPcnQEU3vr3Vss5Ax7n - secret-key: NCySlHYxtHgEhM9CPg3sYv3va2Pbfj \ No newline at end of file + sdk-path: ../api-sdk/src/main/java/com/dhx/apisdk/client \ No newline at end of file diff --git a/api-core/src/main/resources/mapper/DailyCheckInMapper.xml b/api-core/src/main/resources/mapper/DailyCheckInMapper.xml new file mode 100644 index 0000000..4338fb2 --- /dev/null +++ b/api-core/src/main/resources/mapper/DailyCheckInMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + id,userId,description, + addPoints,createTime,updateTime + +