feat(REQ-2040): 同步接口

This commit is contained in:
chenwenjian 2024-01-03 21:07:33 +08:00
parent 4506422fc9
commit 86d7501f01
16 changed files with 480 additions and 39 deletions

View File

@ -1,5 +1,6 @@
# 项目介绍
一个通用的聚合服务:通用黑名单服务
一个通用的聚合服务:
* 通用黑白名单服务
# vm参数
## dev环境
@ -18,13 +19,19 @@
-DCUSTOM_ENV=test
-Dserver.port=8080
# 各模块结构
# 黑白名单中各模块结构
## all-login 登录白名单
~~~json
{
"phone": "手机号"
}
~~~
## ou_register_black_list 企业注册黑名单
~~~json
{
"phone": "手机号"
}
~~~
## attendance-pass 考勤黑名单
~~~json
{

View File

@ -1,8 +1,11 @@
package cn.axzo.nanopart.api;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.api.annotation.CheckSign;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import cn.axzo.nanopart.api.request.BlackAndWhiteListExcelImportReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
@ -13,6 +16,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
@ -84,4 +88,36 @@ public interface BlackAndWhiteListApi {
@PostMapping("api/black-white-list/import")
ApiResult<BlackAndWhiteListExcelImportResp> importBlackAndWhiteListExcel(@RequestParam(value = "type") @NotNull(message = "名单类型不能为空") ListTypeEnum type,
@RequestParam(value = "module") @NotBlank(message = "模块不能为空") String module, @RequestParam(value = "url", required = false) String url, @RequestPart(value = "file") MultipartFile file);
/**
* 平台同步黑白名单
* <p>
* 每次最多同步1000条记录且整体上同步策略采用增量更新策略
* 若总记录数超过1000条请自行分片多次调用
* </p>
*
* <p>
* 该接口需要验签参与签名的字段为header中的appKey,timestamp,
* 签名字段为header中的sign
* </p>
*
* @param req @{link BlackAndWhiteListPlatformSyncReq}
* @return true-同步成功false-同步失败
*/
@PostMapping("api/black-white-list/plat-sync")
ApiResult<Boolean> platformSync(@RequestBody @Validated BlackAndWhiteListPlatformSyncReq req);
/**
* TODO 该接口目前耗时较长待优化
* 内部自同步黑白名单
* <p>
* 例如将其他模块的黑名单同步到登录模块黑名单
* </p>
*
* @param req @{link BlackAndWhiteListInternalSyncReq}
* @return 同步结果成功返回同步记录总数
*/
@CheckSign
@PostMapping("api/black-white-list/inner-sync")
ApiResult<Long> internalSync(@RequestBody @Validated BlackAndWhiteListInternalSyncReq req);
}

View File

@ -46,6 +46,7 @@ public class CheckSignAspect {
@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postMapping() {
log.info("post");
}
@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
@ -68,10 +69,14 @@ public class CheckSignAspect {
public void mappingAnnotations() {
}
// @Pointcut(value = "@annotation(cn.axzo.nanopart.api.annotation.CheckSign)")
// public void checkSign() {
// }
/**
* 切入含有@CheckSign && @RestController 注解的类
*/
@Before(value = "@within(checkSign) && @within(restController)")
@Before(value = "@within(checkSign) && @within(restController)", argNames = "joinPoint,checkSign,restController")
public void classHandler(JoinPoint joinPoint, CheckSign checkSign, RestController restController) {
handle(joinPoint, checkSign);
}
@ -127,7 +132,11 @@ public class CheckSignAspect {
if (StringUtils.isBlank(value)) {
throw new BizException(new RespCode("403", "验签失败"));
}
data.append(field).append("=").append(value).append("&");
data.append(field).append("=").append(value);
// 判断最后一个字段如果是最后一个字段则不拼接"&"
if (field.equals(checkSign.requireSignFields()[checkSign.requireSignFields().length - 1])) {
data.append("&");
}
}
}
log.info("data:{}", data);

View File

@ -1,9 +1,10 @@
package cn.axzo.nanopart.api.config;
import cn.axzo.nanopart.api.constant.NanopartConstant;
import cn.axzo.nanopart.api.constant.BlackAndWhiteListConstant;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableFeignClients(NanopartConstant.BASIC_FEIGN_PACKAGE)
@EnableFeignClients(BlackAndWhiteListConstant.BASIC_FEIGN_PACKAGE)
public class NanopartApiAutoConfiguration {
}

View File

@ -7,7 +7,7 @@ package cn.axzo.nanopart.api.constant;
* @modifiedBy
* @version: 1.0
*/
public class NanopartConstant {
public class BlackAndWhiteListConstant {
public static final String BASIC_FEIGN_PACKAGE = "cn.axzo.nanopart.api";
public static final String PHONE_REGEXP = "^1[3456789]\\d{9}$";

View File

@ -1,7 +1,7 @@
package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.constant.NanopartConstant;
import cn.axzo.nanopart.api.constant.BlackAndWhiteListConstant;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@ -21,6 +21,6 @@ public class BlackAndWhiteListInReq {
@NotBlank(message = "模块名称不能为空格")
private String module;
@Pattern(regexp = NanopartConstant.PHONE_REGEXP,message = "手机号格式错误")
@Pattern(regexp = BlackAndWhiteListConstant.PHONE_REGEXP,message = "手机号格式错误")
private String phone;
}

View File

@ -0,0 +1,53 @@
package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 黑白名单内部自同步请求
*
* @author chenwenjian
* @version 1.0
* @date 2024/1/3 16:46
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BlackAndWhiteListInternalSyncReq {
@NotNull(message = "同步类型不能为空")
private ListTypeEnum type;
/**
* 同步源模块
*/
@NotBlank(message = "同步源模块不能为空")
private String sourceModule;
/**
* 同步源字段
*/
@NotEmpty(message = "同步源字段不能为空")
private List<String> sourceFields;
/**
* 同步目标模块
*/
@NotBlank(message = "同步目标模块不能为空")
private String targetModule;
/**
* 同步目标字段
*/
@NotEmpty(message = "同步目标字段不能为空")
private List<String> targetFields;
}

View File

@ -0,0 +1,78 @@
package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
/**
* 黑白名单平台同步请求
*
* @author chenwenjian
* @version 1.0
* @date 2024/1/2 18:17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BlackAndWhiteListPlatformSyncReq {
/**
* 名单类型0为黑名单1为白名单
*/
@NotNull(message = "名单类型错误")
private ListTypeEnum type;
/**
* 模块名自主定义cms-login
*/
@NotBlank(message = "模块名不能为空")
private String module;
/**
* 参数[{"name":"username","value":"admin"},{"name":"password","value":"123456"}]
* 单次同步数量最多1000条
*/
@NotEmpty(message = "参数不能为空")
private List<Map<String, Object>> params;
/**
* 同步时使用的业务唯一字段名username
*/
@NotBlank(message = "同步时使用的业务唯一字段名")
private String businessUniqueField;
/**
* 是否同步至登录黑名单
*/
private Boolean isSyncLogin;
/**
* 同步至登录黑名单时params中代表手机号的字段名userPhone
* <p>
* 因为目前登录黑名单以手机号作为判断依据所以当isSyncLogin为true时此字段必填
* </p>
*/
private String syncLoginField;
/**
* 是否同步至注册黑名单
*/
private Boolean isSyncRegister;
/**
* 同步至注册黑名单时params中代表手机号的字段名userPhone
* <p>
* 因为目前注册黑名单以手机号作为判断依据所以当isSyncRegister为true时此字段必填
* </p>
*/
private String syncRegisterField;
}

View File

@ -1,7 +1,10 @@
package cn.axzo.nanopart.api.request;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ -15,6 +18,9 @@ import java.util.Map;
* @version: 1.0
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BlackAndWhiteListReq {
/**

View File

@ -33,5 +33,9 @@
<artifactId>black-list-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,19 @@
package cn.axzo.nanopart.server.constant;
/**
* @author chenwenjian
* @version 1.0
* @date 2024/1/3 11:28
*/
public class BlackAndWhiteListConstant {
/**
* 所有平台登录黑名单模块名
*/
public static final String ALL_LOGIN = "all-login";
/**
* 企业注册黑名单模块名
*/
public static final String OU_REGISTER_BLACK_LIST = "ou_register_black_list";
}

View File

@ -3,13 +3,17 @@ package cn.axzo.nanopart.server.controller;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.api.BlackAndWhiteListApi;
import cn.axzo.nanopart.api.annotation.CheckSign;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import cn.axzo.nanopart.api.request.BlackAndWhiteListExcelImportReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
import cn.axzo.nanopart.server.service.BlackAndWhiteListService;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
@ -44,12 +48,12 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
@Override
public ApiResult<Long> create(BlackAndWhiteListReq req) {
return blackAndWhiteListService.create(req);
return ApiResult.ok(blackAndWhiteListService.create(req));
}
@Override
public ApiResult<Void> delete(BlackAndWhiteListReq req) {
return blackAndWhiteListService.delete(req);
return ApiResult.ok(blackAndWhiteListService.delete(req));
}
@Override
@ -59,12 +63,12 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
@Override
public ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req) {
return blackAndWhiteListService.detail(req);
return ApiResult.ok(blackAndWhiteListService.detail(req));
}
@Override
public ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req) {
return blackAndWhiteListService.isInBlackOrWhiteList(req);
return ApiResult.ok(blackAndWhiteListService.isInBlackOrWhiteList(req));
}
@Override
@ -73,4 +77,29 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
return ApiResult.ok(blackAndWhiteListService.importBlackAndWhiteListExcel(type, module, url, file));
}
/**
* 平台同步黑白名单
*
* @param req @{link BlackAndWhiteListPlatformSyncReq}
* @return
*/
@CheckSign(requireSignFields = {"appKey", "timestamp"})
@Override
public ApiResult<Boolean> platformSync(BlackAndWhiteListPlatformSyncReq req) {
log.info("平台同步参数req = {}", JSONUtil.toJsonStr(req));
return ApiResult.ok(blackAndWhiteListService.platformSync(req));
}
/**
* 内部自同步黑白名单
*
* @param req @{link BlackAndWhiteListInternalSyncReq}
* @return 同步结果的记录id
*/
@CheckSign(requireSignFields = {"appKey", "timestamp"})
@Override
public ApiResult<Long> internalSync(BlackAndWhiteListInternalSyncReq req) {
return ApiResult.ok(blackAndWhiteListService.internalSync(req));
}
}

View File

@ -7,6 +7,7 @@ import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
import cn.axzo.nanopart.server.dao.mapper.BlackAndWhiteListMapper;
import cn.azxo.framework.common.utils.StringUtils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
@ -33,7 +34,7 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
private final BlackAndWhiteListMapper blackAndWhiteListMapper;
public Long create(BlackAndWhiteListReq req){
public Long create(BlackAndWhiteListReq req) {
SaasBlackWhiteList blackWhiteList = BeanMapper.copyBean(req, SaasBlackWhiteList.class, (req1, saasBlackWhiteList) -> saasBlackWhiteList.setType(req1.getType().getValue()));
Date nowTime = new Date(System.currentTimeMillis());
blackWhiteList.setCreateAt(nowTime);
@ -44,13 +45,13 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
public Void delete(BlackAndWhiteListReq req) {
List<SaasBlackWhiteList> blackWhiteLists = detail(req);
if (CollectionUtil.isNotEmpty(blackWhiteLists)){
if (CollectionUtil.isNotEmpty(blackWhiteLists)) {
blackWhiteLists.forEach(saasBlackWhiteList -> {
lambdaUpdate().eq(SaasBlackWhiteList::getId,saasBlackWhiteList.getId())
.eq(SaasBlackWhiteList::getIsDelete,0)
.set(SaasBlackWhiteList::getIsDelete,saasBlackWhiteList.getId())
lambdaUpdate().eq(SaasBlackWhiteList::getId, saasBlackWhiteList.getId())
.eq(SaasBlackWhiteList::getIsDelete, 0)
.set(SaasBlackWhiteList::getIsDelete, saasBlackWhiteList.getId())
.update();
log.info("deleted record:{}", JSONObject.valueToString(saasBlackWhiteList));
log.info("deleted record:{}", JSONUtil.toJsonStr(saasBlackWhiteList));
});
}
return null;
@ -58,10 +59,10 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
public List<SaasBlackWhiteList> detail(BlackAndWhiteListReq req) {
QueryWrapper<SaasBlackWhiteList> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("type",req.getType().getValue())
.eq(StringUtils.isNotBlank(req.getModule()),"module",req.getModule())
.eq("is_delete",0)
.groupBy("type","param");
queryWrapper.eq("type", req.getType().getValue())
.eq(StringUtils.isNotBlank(req.getModule()), "module", req.getModule())
.eq("is_delete", 0)
.groupBy("type", "param");
buildQueryWrapper(queryWrapper, req.getParam(), "");
return blackAndWhiteListMapper.selectList(queryWrapper);
}
@ -83,4 +84,50 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
.set(SaasBlackWhiteList::getIsDelete, 1)
.update();
}
/**
* 按模块删除名单
*
* @param type 名单类型
* @param module 模块名
* @return 删除结果true删除成功false删除失败
*/
public Boolean deleteByModule(Integer type, String module) {
return lambdaUpdate()
.eq(SaasBlackWhiteList::getType, type)
.eq(SaasBlackWhiteList::getModule, module)
.eq(SaasBlackWhiteList::getIsDelete, 0)
.set(SaasBlackWhiteList::getIsDelete, 1)
.update();
}
/**
* 更新名单参数
*
* @param id 名单id
* @param param 名单参数
* @return 更新结果true更新成功false更新失败
*/
public boolean updateParamById(Long id, Map<String, Object> param) {
return lambdaUpdate()
.eq(SaasBlackWhiteList::getIsDelete, id)
.eq(SaasBlackWhiteList::getIsDelete, 0)
.set(SaasBlackWhiteList::getParam, param)
.update();
}
/**
* 根据模块名获取名单
*
* @param type 名单类型
* @param module 模块名
* @return 名单列表
*/
public List<SaasBlackWhiteList> getListByModule(Integer type, String module) {
return lambdaQuery()
.eq(SaasBlackWhiteList::getType, type)
.eq(SaasBlackWhiteList::getModule, module)
.eq(SaasBlackWhiteList::getIsDelete, 0)
.list();
}
}

View File

@ -2,6 +2,8 @@ package cn.axzo.nanopart.server.service;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
@ -19,15 +21,19 @@ import java.util.List;
*/
public interface BlackAndWhiteListService {
ApiResult<Long> create(BlackAndWhiteListReq req);
Long create(BlackAndWhiteListReq req);
ApiResult<Void> delete(BlackAndWhiteListReq req);
Void delete(BlackAndWhiteListReq req);
ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req);
List<BlackAndWhiteListResp> detail(BlackAndWhiteListReq req);
ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req);
Boolean isInBlackOrWhiteList(BlackAndWhiteListReq req);
BlackAndWhiteListExcelImportResp importBlackAndWhiteListExcel(ListTypeEnum type, String module, String url, MultipartFile file);
Boolean deleteByIds(List<Long> ids);
Boolean platformSync(BlackAndWhiteListPlatformSyncReq req);
Long internalSync(BlackAndWhiteListInternalSyncReq req);
}

View File

@ -2,20 +2,26 @@ package cn.axzo.nanopart.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
import cn.axzo.nanopart.server.constant.BlackAndWhiteListConstant;
import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
import cn.axzo.nanopart.server.dao.repository.BlackAndWhiteListRepository;
import cn.axzo.nanopart.server.service.BlackAndWhiteListService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
@ -24,11 +30,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
@ -40,11 +49,18 @@ import java.util.stream.Collectors;
*/
@Slf4j
@Service
@RefreshScope
@RequiredArgsConstructor
public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
private final BlackAndWhiteListRepository blackAndWhiteListRepository;
/**
* 黑白名单外部平台单次最大同步记录数
*/
@Value("${sync.fragmentSize:1000}")
private Long fragmentSize;
/**
* 新增一条黑白名单记录
*
@ -52,17 +68,17 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
* @return 记录id
*/
@Override
public ApiResult<Long> create(BlackAndWhiteListReq req) {
public Long create(BlackAndWhiteListReq req) {
// 黑白名单创建互斥,若存在于黑名单中则不允许存在于白名单中反之亦然
BlackAndWhiteListReq reverseReq = BeanMapper.copyBean(req, BlackAndWhiteListReq.class, (req1, req2) -> req2.setType((req1.getType().equals(ListTypeEnum.BLACK_LIST)) ? ListTypeEnum.WHITE_LIST : ListTypeEnum.BLACK_LIST));
if (isInBlackOrWhiteList(reverseReq).getData()) {
if (isInBlackOrWhiteList(reverseReq)) {
throw new ServiceException("该记录已存在于" + reverseReq.getType().getDescription() + "中,不能创建对应" + req.getType().getDescription());
}
// 同类型名单内唯一性校验
if (isInBlackOrWhiteList(req).getData()) {
if (isInBlackOrWhiteList(req)) {
throw new ServiceException("该记录已存在于" + req.getType().getDescription() + "");
}
return ApiResult.ok(blackAndWhiteListRepository.create(req));
return blackAndWhiteListRepository.create(req);
}
/**
@ -72,8 +88,8 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
* @return null
*/
@Override
public ApiResult<Void> delete(BlackAndWhiteListReq req) {
return ApiResult.ok(blackAndWhiteListRepository.delete(req));
public Void delete(BlackAndWhiteListReq req) {
return blackAndWhiteListRepository.delete(req);
}
/**
@ -83,10 +99,9 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
* @return 记录列表
*/
@Override
public ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req) {
public List<BlackAndWhiteListResp> detail(BlackAndWhiteListReq req) {
List<SaasBlackWhiteList> saasBlackWhiteLists = blackAndWhiteListRepository.detail(req);
List<BlackAndWhiteListResp> blackAndWhiteListResps = BeanMapper.copyList(saasBlackWhiteLists, BlackAndWhiteListResp.class);
return ApiResult.ok(blackAndWhiteListResps);
return BeanMapper.copyList(saasBlackWhiteLists, BlackAndWhiteListResp.class);
}
/**
@ -96,9 +111,9 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
* @return 记录存在返回true否则返回false
*/
@Override
public ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req) {
public Boolean isInBlackOrWhiteList(BlackAndWhiteListReq req) {
List<SaasBlackWhiteList> blackWhiteLists = blackAndWhiteListRepository.detail(req);
return ApiResult.ok(CollectionUtil.isNotEmpty(blackWhiteLists));
return CollectionUtil.isNotEmpty(blackWhiteLists);
}
/**
@ -144,6 +159,135 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
return true;
}
/**
* 平台同步黑白名单
*
* @param req {@link BlackAndWhiteListPlatformSyncReq}
* @return true-同步成功false-同步失败
*/
@Override
public Boolean platformSync(BlackAndWhiteListPlatformSyncReq req) {
if (Objects.isNull(req.getType())) {
throw new ServiceException("请选择正确的名单类型");
}
if (req.getParams().size() > fragmentSize) {
throw new ServiceException("请主动进行分片多次同步,单次同步数小于" + fragmentSize + "条数据");
}
// 存入本次同步的黑/白名单记录
req.getParams().forEach(param -> {
HashMap<String, Object> map = new HashMap<>();
map.put(req.getBusinessUniqueField(), param.get(req.getBusinessUniqueField()));
List<BlackAndWhiteListResp> detail = detail(BlackAndWhiteListReq.builder()
.type(req.getType())
.module(req.getModule())
.param(map)
.build());
// 该记录原来不存在即未同步过直接新增一条
if (detail.size() == 0) {
create(BlackAndWhiteListReq.builder()
.type(req.getType())
.module(req.getModule())
.param(param)
.build());
} else if (detail.size() == 1) {
updateParamById(detail.get(0).getId(), param);
} else {
log.warn("指定唯一字段:{},不唯一记录:{}", req.getBusinessUniqueField(), JSONUtil.toJsonStr(detail));
throw new ServiceException("请检查指定的【业务唯一字段名:" + req.getBusinessUniqueField() + "】是否正确,记录中存在不唯一值");
}
});
// 同步至登录黑名单
if (Objects.nonNull(req.getIsSyncLogin()) && req.getIsSyncLogin()){
internalSync(BlackAndWhiteListInternalSyncReq.builder()
.type(req.getType())
.sourceModule(req.getModule())
.sourceFields(Collections.singletonList(req.getSyncLoginField()))
.targetModule(BlackAndWhiteListConstant.ALL_LOGIN).build());
}
// 同步至注册黑名单
if (Objects.nonNull(req.getIsSyncRegister()) && req.getIsSyncRegister()){
internalSync(BlackAndWhiteListInternalSyncReq.builder()
.type(req.getType())
.sourceModule(req.getModule())
.sourceFields(Collections.singletonList(req.getSyncRegisterField()))
.targetModule(BlackAndWhiteListConstant.OU_REGISTER_BLACK_LIST).build());
}
return true;
}
/**
* 内部自同步黑白名单
*
* @param req {@link BlackAndWhiteListInternalSyncReq}
* @return 同步成功的记录总条数
*/
public Long internalSync(BlackAndWhiteListInternalSyncReq req) {
AtomicReference<Long> count = new AtomicReference<>(0L);
// 获取所有源记录
List<SaasBlackWhiteList> sourceList = blackAndWhiteListRepository.getListByModule(req.getType().getValue(), req.getSourceModule());
sourceList.stream().map(s -> {
// 抽取出需要同步的字段值
HashMap<String, Object> map = new HashMap<>();
req.getSourceFields().forEach(sf -> map.put(sf, s.getParam().get(sf)));
return map;
}).forEach(m -> {
// 判断是否存在目标记录不存在则新增一条
if (!isInBlackOrWhiteList(BlackAndWhiteListReq.builder()
.type(req.getType())
.module(req.getTargetModule())
.param(m)
.build())) {
create(BlackAndWhiteListReq.builder()
.type(req.getType())
.module(req.getTargetModule())
.param(m)
.build());
count.getAndSet(count.get() + 1);
}
});
return count.get();
}
/**
* 获取指定模块名的所有黑/白名单记录
*
* @param type 名单类型
* @param module 模块名
* @return /白名单记录列表
*/
public List<BlackAndWhiteListResp> getListByModule(ListTypeEnum type, String module) {
return BeanMapper.copyList(blackAndWhiteListRepository.getListByModule(type.getValue(), module), BlackAndWhiteListResp.class);
}
/**
* 更新指定id的黑白名单记录
*
* @param id 记录id
* @param param 记录参数
* @return true-更新成功false-更新失败
*/
public boolean updateParamById(Long id, Map<String, Object> param) {
return blackAndWhiteListRepository.updateParamById(id, param);
}
/**
* 删除指定模块名的所有黑/白名单记录
*
* @param type 名单类型
* @param module 模块名
* @return true-删除成功false-删除失败
*/
public Boolean deleteByModule(ListTypeEnum type, String module) {
if (Objects.isNull(type)) {
throw new ServiceException("待删除名单类型不能为空");
}
if (!StringUtils.hasText(module)) {
throw new ServiceException("待删除模块名不能为空");
}
return blackAndWhiteListRepository.deleteByModule(type.getValue(), module);
}
/**
* 使用EasyExcel读取Excel数据
*

View File

@ -4,12 +4,14 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@MapperScan(value = {"cn.axzo.**.mapper"})
@SpringBootApplication
@EnableFeignClients(basePackages = {
"cn.axzo.nanopart.api"
})
@EnableAspectJAutoProxy()
public class NanopartApplication {
public static void main(String[] args) {
SpringApplication.run(NanopartApplication.class, args);