diff --git a/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java b/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java index 27ad4b5..3d4b28f 100644 --- a/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java +++ b/beacon-api/src/main/java/com/mashibing/api/controller/SmsController.java @@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; +import java.time.LocalDateTime; /** * @author zjw @@ -91,8 +92,9 @@ public class SmsController { //=========================调用策略模式的校验链========================================= checkFilterContext.check(submit); - //========================基于雪花算法生成唯一id,并添加到StandardSubmit对象中========================================= + //========================基于雪花算法生成唯一id,并添加到StandardSubmit对象中,并设置发送时间========================================= submit.setSequenceId(snowFlakeUtil.nextId()); + submit.setSendTime(LocalDateTime.now()); //=========================发送到MQ,交给策略模块处理========================================= rabbitTemplate.convertAndSend(RabbitMQConstants.SMS_PRE_SEND,submit,new CorrelationData(submit.getSequenceId().toString())); diff --git a/beacon-common/src/main/java/com/mashibing/common/constant/CacheConstant.java b/beacon-common/src/main/java/com/mashibing/common/constant/CacheConstant.java index e81cc70..634bc5f 100644 --- a/beacon-common/src/main/java/com/mashibing/common/constant/CacheConstant.java +++ b/beacon-common/src/main/java/com/mashibing/common/constant/CacheConstant.java @@ -33,5 +33,20 @@ public interface CacheConstant { */ String DIRTY_WORD = "dirty_word"; + /** + * 黑名单的前缀 + */ + String BLACK = "black:"; + + /** + * 间隔符 + */ + String SEPARATE = ":"; + + /** + * 携号转网 + */ + String TRANSFER = "transfer:"; + } diff --git a/beacon-common/src/main/java/com/mashibing/common/constant/RabbitMQConstants.java b/beacon-common/src/main/java/com/mashibing/common/constant/RabbitMQConstants.java index a7494e1..2b77fbc 100644 --- a/beacon-common/src/main/java/com/mashibing/common/constant/RabbitMQConstants.java +++ b/beacon-common/src/main/java/com/mashibing/common/constant/RabbitMQConstants.java @@ -17,4 +17,16 @@ public interface RabbitMQConstants { * 策略模块发送手机号归属地&运营商到后台管理模块的队列名称 */ String MOBILE_AREA_OPERATOR = "mobile_area_operator_topic"; + + /** + * 写日志到Elasticsearch的队列 + */ + String SMS_WRITE_LOG = "sms_write_log_topic"; + + /** + * 状态报告推送的队列 + */ + String SMS_PUSH_REPORT = "sms_push_report_topic"; + + } diff --git a/beacon-common/src/main/java/com/mashibing/common/constant/SmsConstant.java b/beacon-common/src/main/java/com/mashibing/common/constant/SmsConstant.java new file mode 100644 index 0000000..28cd5e6 --- /dev/null +++ b/beacon-common/src/main/java/com/mashibing/common/constant/SmsConstant.java @@ -0,0 +1,20 @@ +package com.mashibing.common.constant; + +/** + * 通用的一些常量 + * @author zjw + * @description + */ +public interface SmsConstant { + + /** + * 短信发送成功 + */ + int REPORT_SUCCESS = 1; + + /** + * 短信发送失败 + */ + int REPORT_FAIL = 2; + +} diff --git a/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java b/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java index 31ee049..7110763 100644 --- a/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java +++ b/beacon-common/src/main/java/com/mashibing/common/enums/ExceptionEnums.java @@ -18,9 +18,12 @@ public enum ExceptionEnums { PARAMETER_ERROR(-10,"参数不合法!"), SNOWFLAKE_OUT_OF_RANGE(-11,"雪花算法的机器id或服务id超出最大范围!"), SNOWFLAKE_TIME_BACK(-12,"雪花算法的服务器出现时间回拨问题!"), + HAVE_DIRTY_WORD(-13,"当前短信内容中包含敏感词信息!"), + BLACK_GLOBAL(-14,"当前手机号为平台黑名单!"), + BLACK_CLIENT(-15,"当前手机号为客户黑名单!"), ; - private Integer code; + private Integer code; private String msg; ExceptionEnums(Integer code, String msg) { diff --git a/beacon-common/src/main/java/com/mashibing/common/exception/StrategyException.java b/beacon-common/src/main/java/com/mashibing/common/exception/StrategyException.java new file mode 100644 index 0000000..87635b7 --- /dev/null +++ b/beacon-common/src/main/java/com/mashibing/common/exception/StrategyException.java @@ -0,0 +1,27 @@ +package com.mashibing.common.exception; + +import com.mashibing.common.enums.ExceptionEnums; +import lombok.Getter; + +/** + * 策略模块的异常对象 + * @author zjw + * @description + */ +@Getter +public class StrategyException extends RuntimeException { + + private Integer code; + + public StrategyException(String message, Integer code) { + super(message); + this.code = code; + } + + + public StrategyException(ExceptionEnums enums) { + super(enums.getMsg()); + this.code = enums.getCode(); + } + +} diff --git a/beacon-common/src/main/java/com/mashibing/common/model/StandardReport.java b/beacon-common/src/main/java/com/mashibing/common/model/StandardReport.java new file mode 100644 index 0000000..cefa39c --- /dev/null +++ b/beacon-common/src/main/java/com/mashibing/common/model/StandardReport.java @@ -0,0 +1,62 @@ +package com.mashibing.common.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 状态报告推送等操作时的类 + * @author zjw + * @description + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class StandardReport implements Serializable { + + /** + * 针对当前短信的唯一标识,雪花算法(保留) + */ + private Long sequenceId; + + /** + * 客户端ID,基于apikey查询缓存模块得到客户的ID + */ + private Long clientId; + + + /** + * 客户业务内的uid,客户请求传递的 + */ + private String uid; + + /** + * 目标手机号,客户请求传递的 + */ + private String mobile; + + /** + * 短信的发送时间,当前系统时间 + */ + private LocalDateTime sendTime; + + /** + * 短信的发送状态, 0-等待/发送ing,1-成功,2-失败 ,默认情况就是0 + */ + private int reportState; + + /** + * 短信发送失败的原因是什么,记录在当前属性 + */ + private String errorMsg; + + /** + * 回调的信息 + */ + private Integer isCallback; + private String callbackUrl; + +} diff --git a/beacon-common/src/main/java/com/mashibing/common/model/StandardSubmit.java b/beacon-common/src/main/java/com/mashibing/common/model/StandardSubmit.java index bde64c5..1ebb38a 100644 --- a/beacon-common/src/main/java/com/mashibing/common/model/StandardSubmit.java +++ b/beacon-common/src/main/java/com/mashibing/common/model/StandardSubmit.java @@ -70,7 +70,7 @@ public class StandardSubmit implements Serializable { /** - * 目标手机号的归属地区号 0451 0455 (策略模块) + * 目标手机号的归属地区号 0451 0455 (策略模块,三方查询不到,先不管) */ private Integer areaCode; @@ -94,6 +94,11 @@ public class StandardSubmit implements Serializable { */ private int reportState; + /** + * 短信发送失败的原因是什么,记录在当前属性 + */ + private String errorMsg; + // ============================================================================= /** * 获取到的客户端真实IP地址 @@ -115,6 +120,10 @@ public class StandardSubmit implements Serializable { */ private Long signId; + /** + * 是否携号转网, isTransfer = true,代表做了携号转网的判断并且做了操作 + */ + private Boolean isTransfer = false; // 后续再做封装~~~~ diff --git a/beacon-strategy/pom.xml b/beacon-strategy/pom.xml index f6da17d..7fb4b6a 100644 --- a/beacon-strategy/pom.xml +++ b/beacon-strategy/pom.xml @@ -50,6 +50,12 @@ ikanalyzer 2012_u6 + + + cn.hutool + hutool-dfa + 5.8.12 + diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/client/BeaconCacheClient.java b/beacon-strategy/src/main/java/com/mashibing/strategy/client/BeaconCacheClient.java index 7c107c9..9663367 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/client/BeaconCacheClient.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/client/BeaconCacheClient.java @@ -18,9 +18,15 @@ public interface BeaconCacheClient { @GetMapping("/cache/hget/{key}/{field}") String hget(@PathVariable(value = "key")String key, @PathVariable(value = "field")String field); + @GetMapping("/cache/hget/{key}/{field}") + Integer hgetInteger(@PathVariable(value = "key")String key, @PathVariable(value = "field")String field); + @GetMapping(value = "/cache/get/{key}") String getString(@PathVariable(value = "key") String key); @PostMapping(value = "/cache/sinterstr/{key}/{sinterKey}") Set sinterStr(@PathVariable(value = "key")String key, @PathVariable String sinterKey, @RequestBody String... value); + + @GetMapping("/cache/smember/{key}") + Set smember(@PathVariable(value = "key")String key); } diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitMQConfig.java b/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitMQConfig.java index eebd603..c36daeb 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitMQConfig.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitMQConfig.java @@ -23,4 +23,22 @@ public class RabbitMQConfig { return QueueBuilder.durable(RabbitMQConstants.MOBILE_AREA_OPERATOR).build(); } + /** + * 写日志的队列。 + * @return + */ + @Bean + public Queue writeLogQueue(){ + return QueueBuilder.durable(RabbitMQConstants.SMS_WRITE_LOG).build(); + } + + /** + * 状态报告的队列。 + * @return + */ + @Bean + public Queue pushReportQueue(){ + return QueueBuilder.durable(RabbitMQConstants.SMS_PUSH_REPORT).build(); + } + } diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackClientStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackClientStrategyFilter.java new file mode 100644 index 0000000..8c01295 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackClientStrategyFilter.java @@ -0,0 +1,53 @@ +package com.mashibing.strategy.filter.impl; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.enums.ExceptionEnums; +import com.mashibing.common.exception.StrategyException; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import com.mashibing.strategy.filter.StrategyFilter; +import com.mashibing.strategy.util.ErrorSendMsgUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 黑名单校验 + * @author zjw + * @description + */ +@Service(value = "blackClient") +@Slf4j +public class BlackClientStrategyFilter implements StrategyFilter { + + @Autowired + private ErrorSendMsgUtil sendMsgUtil; + + @Autowired + private BeaconCacheClient cacheClient; + + // 黑名单的默认value + private final String TRUE = "1"; + + @Override + public void strategy(StandardSubmit submit) { + log.info("【策略模块-客户级别黑名单校验】 校验ing…………"); + //1、获取发送短信的手机号,以及客户的ID + String mobile = submit.getMobile(); + Long clientId = submit.getClientId(); + + //2、调用Redis查询 + String value = cacheClient.getString(CacheConstant.BLACK + clientId + CacheConstant.SEPARATE + mobile); + + //3、如果查询的结果为"1",代表是黑名单 + if(TRUE.equals(value)){ + log.info("【策略模块-客户级别黑名单校验】 当前发送的手机号是客户黑名单! mobile = {}",mobile); + submit.setErrorMsg(ExceptionEnums.BLACK_CLIENT + ",mobile = " + mobile); + sendMsgUtil.sendWriteLog(submit); + sendMsgUtil.sendPushReport(submit); + throw new StrategyException(ExceptionEnums.BLACK_CLIENT); + } + //4、不是1,正常结束 + log.info("【策略模块-客户级别黑名单校验】 当前手机号不是客户黑名单! "); + } +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackGlobalStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackGlobalStrategyFilter.java new file mode 100644 index 0000000..083e181 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackGlobalStrategyFilter.java @@ -0,0 +1,52 @@ +package com.mashibing.strategy.filter.impl; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.enums.ExceptionEnums; +import com.mashibing.common.exception.StrategyException; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import com.mashibing.strategy.filter.StrategyFilter; +import com.mashibing.strategy.util.ErrorSendMsgUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 黑名单校验 + * @author zjw + * @description + */ +@Service(value = "blackGlobal") +@Slf4j +public class BlackGlobalStrategyFilter implements StrategyFilter { + + @Autowired + private ErrorSendMsgUtil sendMsgUtil; + + @Autowired + private BeaconCacheClient cacheClient; + + // 黑名单的默认value + private final String TRUE = "1"; + + @Override + public void strategy(StandardSubmit submit) { + log.info("【策略模块-全局级别黑名单校验】 校验ing…………"); + //1、获取发送短信的手机号 + String mobile = submit.getMobile(); + + //2、调用Redis查询 + String value = cacheClient.getString(CacheConstant.BLACK + mobile); + + //3、如果查询的结果为"1",代表是黑名单 + if(TRUE.equals(value)){ + log.info("【策略模块-全局级别黑名单校验】 当前手机号是黑名单! mobile = {}",mobile); + submit.setErrorMsg(ExceptionEnums.BLACK_GLOBAL.getMsg() + ",mobile = " + mobile); + sendMsgUtil.sendWriteLog(submit); + sendMsgUtil.sendPushReport(submit); + throw new StrategyException(ExceptionEnums.BLACK_GLOBAL); + } + //4、不是1,正常结束 + log.info("【策略模块-全局级别黑名单校验】 当前手机号不是黑名单!"); + } +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackStrategyFilter.java deleted file mode 100644 index 209670e..0000000 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/BlackStrategyFilter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.mashibing.strategy.filter.impl; - -import com.mashibing.common.model.StandardSubmit; -import com.mashibing.strategy.filter.StrategyFilter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * 黑名单校验 - * @author zjw - * @description - */ -@Service(value = "black") -@Slf4j -public class BlackStrategyFilter implements StrategyFilter { - @Override - public void strategy(StandardSubmit submit) { - log.info("【策略模块-黑名单校验】 校验ing…………"); - } -} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordDFAStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordDFAStrategyFilter.java new file mode 100644 index 0000000..219c0aa --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordDFAStrategyFilter.java @@ -0,0 +1,46 @@ +package com.mashibing.strategy.filter.impl; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import com.mashibing.strategy.filter.StrategyFilter; +import com.mashibing.strategy.util.DFAUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.wltea.analyzer.core.IKSegmenter; +import org.wltea.analyzer.core.Lexeme; + +import java.io.IOException; +import java.io.StringReader; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * 敏感词校验 + * + * @author zjw + * @description + */ +@Service(value = "dfaDirtyWord") +@Slf4j +public class DirtyWordDFAStrategyFilter implements StrategyFilter { + + @Override + public void strategy(StandardSubmit submit) { + log.info("【策略模块-敏感词校验】 校验ing…………"); + //1、 获取短信内容 + String text = submit.getText(); + + //2、 调用DFA查看敏感词 + Set dirtyWords = DFAUtil.getDirtyWord(text); + + //4、 根据返回的set集合,判断是否包含敏感词 + if (dirtyWords != null && dirtyWords.size() > 0) { + //5、 如果有敏感词,抛出异常 / 其他操作。。 + log.info("【策略模块-敏感词校验】 短信内容包含敏感词信息, dirtyWords = {}", dirtyWords); + // 还需要做其他处理 + } + } +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordHutoolDFAStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordHutoolDFAStrategyFilter.java new file mode 100644 index 0000000..8145aa9 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordHutoolDFAStrategyFilter.java @@ -0,0 +1,73 @@ +package com.mashibing.strategy.filter.impl; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.constant.RabbitMQConstants; +import com.mashibing.common.constant.SmsConstant; +import com.mashibing.common.enums.ExceptionEnums; +import com.mashibing.common.exception.StrategyException; +import com.mashibing.common.model.StandardReport; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import com.mashibing.strategy.filter.StrategyFilter; +import com.mashibing.strategy.util.DFAUtil; +import com.mashibing.strategy.util.ErrorSendMsgUtil; +import com.mashibing.strategy.util.HutoolDFAUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Set; + +/** + * 敏感词校验 + * + * @author zjw + * @description + */ +@Service(value = "hutoolDFADirtyWord") +@Slf4j +public class DirtyWordHutoolDFAStrategyFilter implements StrategyFilter { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Autowired + private BeaconCacheClient cacheClient; + + @Autowired + private ErrorSendMsgUtil sendMsgUtil; + + @Override + public void strategy(StandardSubmit submit) { + log.info("【策略模块-敏感词校验】 校验ing…………"); + //1、 获取短信内容 + String text = submit.getText(); + + //2、 调用DFA查看敏感词 + List dirtyWords = HutoolDFAUtil.getDirtyWord(text); + + //4、 根据返回的set集合,判断是否包含敏感词 + if (dirtyWords != null && dirtyWords.size() > 0) { + //5、 如果有敏感词,抛出异常 / 其他操作。。 + log.info("【策略模块-敏感词校验】 短信内容包含敏感词信息, dirtyWords = {}", dirtyWords); + // ================================发送写日志================================ + submit.setErrorMsg(ExceptionEnums.HAVE_DIRTY_WORD.getMsg() + "dirtyWords = " + dirtyWords.toString()); + sendMsgUtil.sendWriteLog(submit); + // ================================发送状态报告的消息前,需要将report对象数据封装================================ + sendMsgUtil.sendPushReport(submit); + // // ================================抛出异常================================ + throw new StrategyException(ExceptionEnums.HAVE_DIRTY_WORD); + + } + + log.info("【策略模块-敏感词校验】 校验通过,没有敏感词信息"); + } + + + + +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordStrategyFilter.java index 54b7bb5..25a3b7f 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordStrategyFilter.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/DirtyWordStrategyFilter.java @@ -18,12 +18,13 @@ import java.util.UUID; /** * 敏感词校验 + * * @author zjw * @description */ - @Service(value = "dirtyword") - @Slf4j - public class DirtyWordStrategyFilter implements StrategyFilter { +@Service(value = "dirtyword") +@Slf4j +public class DirtyWordStrategyFilter implements StrategyFilter { @Autowired private BeaconCacheClient cacheClient; @@ -37,13 +38,13 @@ import java.util.UUID; //2、 对短信内容进行分词,并且将分析内容存储到集合中 Set contents = new HashSet<>(); StringReader reader = new StringReader(text); - IKSegmenter ik = new IKSegmenter(reader,false); + IKSegmenter ik = new IKSegmenter(reader, false); Lexeme lex = null; - while(true){ + while (true) { try { if ((lex = ik.next()) == null) break; } catch (IOException e) { - log.info("【策略模块-敏感词校验】 IK分词器在处理短信内容时,出现异常 e = {}" ,e.getMessage()); + log.info("【策略模块-敏感词校验】 IK分词器在处理短信内容时,出现异常 e = {}", e.getMessage()); } contents.add(lex.getLexemeText()); } @@ -54,9 +55,9 @@ import java.util.UUID; Set dirtyWords = cacheClient.sinterStr(UUID.randomUUID().toString(), CacheConstant.DIRTY_WORD, contents.toArray(new String[]{})); //4、 根据返回的set集合,判断是否包含敏感词 - if(dirtyWords != null && dirtyWords.size() > 0){ + if (dirtyWords != null && dirtyWords.size() > 0) { //5、 如果有敏感词,抛出异常 / 其他操作。。 - log.info("【策略模块-敏感词校验】 短信内容包含敏感词信息, dirtyWords = {}",dirtyWords); + log.info("【策略模块-敏感词校验】 短信内容包含敏感词信息, dirtyWords = {}", dirtyWords); // 还需要做其他处理 } } diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/TransferStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/TransferStrategyFilter.java new file mode 100644 index 0000000..5dc2cef --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/TransferStrategyFilter.java @@ -0,0 +1,48 @@ +package com.mashibing.strategy.filter.impl; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import com.mashibing.strategy.filter.StrategyFilter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 携号转网策略!!!! + * @author zjw + * @description + */ +@Service(value = "transfer") +@Slf4j +public class TransferStrategyFilter implements StrategyFilter { + + // 代表携号转网了! + private final Boolean TRANSFER = true; + + @Autowired + private BeaconCacheClient cacheClient; + + @Override + public void strategy(StandardSubmit submit) { + log.info("【策略模块-携号转网策略】 ing…………"); + //1、获取用户手机号 + String mobile = submit.getMobile(); + + //2、直接基于Redis查询携号转网信息 + String value = cacheClient.getString(CacheConstant.TRANSFER + mobile); + + //3、如果存在携号转网,设置运营商信息 + if(!StringUtils.isEmpty(value)){ + // 代表携号转网了 + submit.setOperatorId(Integer.valueOf(value)); + submit.setIsTransfer(TRANSFER); + log.info("【策略模块-携号转网策略】 当前手机号携号转网了!"); + return; + } + + log.info("【策略模块-携号转网策略】 嘛事没有!"); + + } +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/mq/PreSendListener.java b/beacon-strategy/src/main/java/com/mashibing/strategy/mq/PreSendListener.java index 81349b8..9bec43b 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/mq/PreSendListener.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/mq/PreSendListener.java @@ -1,6 +1,7 @@ package com.mashibing.strategy.mq; import com.mashibing.common.constant.RabbitMQConstants; +import com.mashibing.common.exception.StrategyException; import com.mashibing.common.model.StandardSubmit; import com.mashibing.strategy.filter.StrategyFilterContext; import com.rabbitmq.client.Channel; @@ -9,6 +10,7 @@ import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import rx.BackpressureOverflow; import java.io.IOException; @@ -31,14 +33,17 @@ public class PreSendListener { @RabbitListener(queues = RabbitMQConstants.SMS_PRE_SEND) public void listen(StandardSubmit submit, Message message, Channel channel) throws IOException { log.info("【策略模块-接收消息】 接收到接口模块发送的消息 submit = {}",submit); + System.out.println("start:" + System.currentTimeMillis()); // 处理业务………… try { filterContext.strategy(submit); log.info("【策略模块-消费完毕】手动ack"); channel.basicAck(message.getMessageProperties().getDeliveryTag(),false); - } catch (IOException e) { - e.printStackTrace(); - log.error("【策略模块-消费失败】凉凉~~~"); + } catch (StrategyException e) { + log.info("【策略模块-消费失败】校验未通过, msg = {}",e.getMessage()); + channel.basicAck(message.getMessageProperties().getDeliveryTag(),false); + }finally { + System.out.println("end:" + System.currentTimeMillis()); } } } diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/util/DFAUtil.java b/beacon-strategy/src/main/java/com/mashibing/strategy/util/DFAUtil.java new file mode 100644 index 0000000..c4aa280 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/util/DFAUtil.java @@ -0,0 +1,130 @@ +package com.mashibing.strategy.util; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.strategy.client.BeaconCacheClient; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author zjw + * @description + */ +public class DFAUtil { + // 敏感词树 + private static Map dfaMap = new HashMap<>(); + + private static final String IS_END = "isEnd"; + + private static final String NOT_END = "0"; + private static final String ALREADY_END = "1"; + + /** + * 初始化敏感词树 + */ + static { + // 获取Spring容器中的cacheClient + BeaconCacheClient cacheClient = (BeaconCacheClient) SpringUtil.getBeanByClass(BeaconCacheClient.class); + // 获取存储在Redis中的全部敏感词 + Set dirtyWords = cacheClient.smember(CacheConstant.DIRTY_WORD); + // 调用create,将dfaMap的敏感词树构建 + create(dirtyWords); + } + + /** + * 构建敏感词树 + * @param dirtyWords + */ + public static void create(Set dirtyWords) { + //1、 声明一个Map作为临时存储 + Map nowMap; + + //2、遍历敏感词库 + for (String dirtyWord : dirtyWords) { + nowMap = dfaMap; + // 每个词,依次获取 + for (int i = 0; i < dirtyWord.length(); i++) { + // 获取敏感词的每个字 + String word = String.valueOf(dirtyWord.charAt(i)); + // 判断当前的敏感词树中是否包含当前的字 + Map map = (Map) nowMap.get(word); + if (map == null) { + // 当前敏感词树中没有这个字 + map = new HashMap(); + // 将当前的敏感词存入 + nowMap.put(word, map); + } + // 操作当前key对应的value的map + nowMap = map; + // 如果当前的字,已经有IS_END了,并且值为1,直接不管, + if (nowMap.containsKey(IS_END) && nowMap.get(IS_END).equals(ALREADY_END)) { + continue; + } + // 如果当前的isEnd没有,或者是0,需要考虑需要改为1 + if (i == dirtyWord.length() - 1) { + // 到最后一个字了。 + nowMap.put(IS_END, ALREADY_END); + } else { + // isEnd之前就是0,或者压根就没有isEnd + nowMap.putIfAbsent(IS_END, NOT_END); + } + } + } + } + + /** + * 基于敏感词树,对文字进行敏感词获取 + * @param text + * @return + */ + public static Set getDirtyWord(String text) { + // 1、作为返回结果存储敏感词的位置 + Set dirtyWords = new HashSet<>(); + // 2、循环遍历文本内容 + for (int i = 0; i < text.length(); i++) { + // 临时存储索引位置的变量 + int nextLength = 0; + int dirtyLength = 0; + // 获取最外层key的map + Map nowMap = dfaMap; + // 外层是索引向后动,匹配最外层的key + // 内层是在匹配上一个后,继续向内部匹配内部的key + for (int j = i; j < text.length(); j++) { + // 获取当前索引位置的字 + String word = String.valueOf(text.charAt(j)); + // 先匹配最外层的key + nowMap = (Map) nowMap.get(word); + // 判断 + if (nowMap == null) { + // 没有这个字开头的敏感词 + break; + } else { + // 敏感词长度,从i开始算,现在的是dirtyLength + dirtyLength++; + // 出口即是,当前的map的isEnd是1,代表结束了。已经找到完整的敏感词 + if (ALREADY_END.equals(nowMap.get(IS_END))) { + // 代表敏感词匹配到一个完整的 + nextLength = dirtyLength; + break; + } + } + + } + // 判断是否匹配上了敏感词 + if (nextLength > 0) { + // 匹配上了,添加敏感词到set,同时移动外层索引 + dirtyWords.add(text.substring(i, i + nextLength)); + // -1的原因是,外层for循环,会对i进行++ + i = i + nextLength - 1; + } + } + // 返回 + return dirtyWords; + } +} + + + diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/util/ErrorSendMsgUtil.java b/beacon-strategy/src/main/java/com/mashibing/strategy/util/ErrorSendMsgUtil.java new file mode 100644 index 0000000..7c89778 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/util/ErrorSendMsgUtil.java @@ -0,0 +1,64 @@ +package com.mashibing.strategy.util; + +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.constant.RabbitMQConstants; +import com.mashibing.common.constant.SmsConstant; +import com.mashibing.common.enums.ExceptionEnums; +import com.mashibing.common.model.StandardReport; +import com.mashibing.common.model.StandardSubmit; +import com.mashibing.strategy.client.BeaconCacheClient; +import org.apache.commons.lang.StringUtils; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author zjw + * @description + */ +@Component +public class ErrorSendMsgUtil { + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Autowired + private BeaconCacheClient cacheClient; + + /** + * 策略模块校验未通过,发送写日志操作 + * @param submit + */ + public void sendWriteLog(StandardSubmit submit) { + submit.setReportState(SmsConstant.REPORT_FAIL); + // 发送消息到写日志队列 + rabbitTemplate.convertAndSend(RabbitMQConstants.SMS_WRITE_LOG,submit); + } + + /** + * 策略模块校验未通过,发送状态报告操作 + */ + public void sendPushReport(StandardSubmit submit) { + // 查询当前客户的isCallback + Integer isCallback = cacheClient.hgetInteger(CacheConstant.CLIENT_BUSINESS + submit.getApikey(), "isCallback"); + // 查看是否需要给客户一个回调 + if(isCallback == 1){ + // 如果需要回调,再查询客户的回调地址 + String callbackUrl = cacheClient.hget(CacheConstant.CLIENT_BUSINESS + submit.getApikey(), "callbackUrl"); + // 如果回调地址不为空。 + if(!StringUtils.isEmpty(callbackUrl)){ + // 封装客户的报告推送的信息,开始封装StandardReport + StandardReport report = new StandardReport(); + BeanUtils.copyProperties(submit,report); + report.setIsCallback(isCallback); + report.setCallbackUrl(callbackUrl); + // 发送消息到RabbitMQ + rabbitTemplate.convertAndSend(RabbitMQConstants.SMS_PUSH_REPORT,report); + } + + } + } +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/util/HutoolDFAUtil.java b/beacon-strategy/src/main/java/com/mashibing/strategy/util/HutoolDFAUtil.java new file mode 100644 index 0000000..c5dc45c --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/util/HutoolDFAUtil.java @@ -0,0 +1,35 @@ +package com.mashibing.strategy.util; + +import cn.hutool.dfa.WordTree; +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.strategy.client.BeaconCacheClient; + +import java.util.List; +import java.util.Set; + +/** + * @author zjw + * @description + */ +public class HutoolDFAUtil { + + private static WordTree wordTree = new WordTree(); + + /** + * 初始化敏感词树 + */ + static { + // 获取Spring容器中的cacheClient + BeaconCacheClient cacheClient = (BeaconCacheClient) SpringUtil.getBeanByClass(BeaconCacheClient.class); + // 获取存储在Redis中的全部敏感词 + Set dirtyWords = cacheClient.smember(CacheConstant.DIRTY_WORD); + // 调用WordTree的add方法,将dfaMap的敏感词树构建 + wordTree.addWords(dirtyWords); + } + + + public static List getDirtyWord(String text){ + return wordTree.matchAll(text); + } + +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/util/SpringUtil.java b/beacon-strategy/src/main/java/com/mashibing/strategy/util/SpringUtil.java new file mode 100644 index 0000000..90c052e --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/util/SpringUtil.java @@ -0,0 +1,29 @@ +package com.mashibing.strategy.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @author zjw + * @description + */ +@Component +public class SpringUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringUtil.applicationContext = applicationContext; + } + + public static Object getBeanByName(String beanName){ + return SpringUtil.applicationContext.getBean(beanName); + } + + public static Object getBeanByClass(Class clazz){ + return SpringUtil.applicationContext.getBean(clazz); + } +} diff --git a/beacon-test/src/main/java/com/mashibing/test/TestStarterApp.java b/beacon-test/src/main/java/com/mashibing/test/TestStarterApp.java index 233eb92..2271d6a 100644 --- a/beacon-test/src/main/java/com/mashibing/test/TestStarterApp.java +++ b/beacon-test/src/main/java/com/mashibing/test/TestStarterApp.java @@ -6,6 +6,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** * @author zjw * @description @@ -19,4 +24,5 @@ public class TestStarterApp { public static void main(String[] args) { SpringApplication.run(TestStarterApp.class,args); } + } diff --git a/beacon-test/src/main/java/com/mashibing/test/entity/MobileBlack.java b/beacon-test/src/main/java/com/mashibing/test/entity/MobileBlack.java new file mode 100644 index 0000000..b2ba0fb --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/entity/MobileBlack.java @@ -0,0 +1,29 @@ +package com.mashibing.test.entity; + +/** + * @author zjw + * @description + */ +public class MobileBlack { + + private String blackNumber; + + private Integer clientId; + + + public String getBlackNumber() { + return blackNumber; + } + + public void setBlackNumber(String blackNumber) { + this.blackNumber = blackNumber; + } + + public Integer getClientId() { + return clientId; + } + + public void setClientId(Integer clientId) { + this.clientId = clientId; + } +} diff --git a/beacon-test/src/main/java/com/mashibing/test/entity/MobileTransfer.java b/beacon-test/src/main/java/com/mashibing/test/entity/MobileTransfer.java new file mode 100644 index 0000000..c8d8a7a --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/entity/MobileTransfer.java @@ -0,0 +1,30 @@ +package com.mashibing.test.entity; + +/** + * @author zjw + * @description + */ +public class MobileTransfer { + + // 手机号 + private String transferNumber; + + // 最终运营商 + private Integer nowIsp; + + public String getTransferNumber() { + return transferNumber; + } + + public void setTransferNumber(String transferNumber) { + this.transferNumber = transferNumber; + } + + public Integer getNowIsp() { + return nowIsp; + } + + public void setNowIsp(Integer nowIsp) { + this.nowIsp = nowIsp; + } +} diff --git a/beacon-test/src/main/java/com/mashibing/test/mapper/MobileBlackMapper.java b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileBlackMapper.java new file mode 100644 index 0000000..80e5231 --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileBlackMapper.java @@ -0,0 +1,18 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.entity.MobileArea; +import com.mashibing.test.entity.MobileBlack; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author zjw + * @description + */ +public interface MobileBlackMapper { + + @Select("select black_number,client_id from mobile_black where is_delete = 0") + List findAll(); + +} diff --git a/beacon-test/src/main/java/com/mashibing/test/mapper/MobileTransferMapper.java b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileTransferMapper.java new file mode 100644 index 0000000..258e1b9 --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileTransferMapper.java @@ -0,0 +1,18 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.entity.MobileBlack; +import com.mashibing.test.entity.MobileTransfer; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author zjw + * @description + */ +public interface MobileTransferMapper { + + @Select("select transfer_number,now_isp from mobile_transfer where is_transfer = 1 and is_delete = 0") + List findAll(); + +} diff --git a/beacon-test/src/test/java/com/mashibing/test/mapper/MobileBlackMapperTest.java b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileBlackMapperTest.java new file mode 100644 index 0000000..8646c91 --- /dev/null +++ b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileBlackMapperTest.java @@ -0,0 +1,40 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.client.CacheClient; +import com.mashibing.test.entity.MobileArea; +import com.mashibing.test.entity.MobileBlack; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SpringBootTest +@RunWith(SpringRunner.class) +public class MobileBlackMapperTest { + + @Autowired + private MobileBlackMapper mapper; + + @Autowired + private CacheClient cacheClient; + + + @Test + public void findAll() { + List mobileBlackList = mapper.findAll(); + for (MobileBlack mobileBlack : mobileBlackList) { + if(mobileBlack.getClientId() == 0){ + // 平台级别的黑名单 black:手机号 作为key + cacheClient.set("black:" + mobileBlack.getBlackNumber(),"1"); + }else{ + // 客户级别的黑名单 black:clientId:手机号 + cacheClient.set("black:" + mobileBlack.getClientId() + ":" +mobileBlack.getBlackNumber(),"1"); + } + } + } +} \ No newline at end of file diff --git a/beacon-test/src/test/java/com/mashibing/test/mapper/MobileTransferMapperTest.java b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileTransferMapperTest.java new file mode 100644 index 0000000..ea5f7de --- /dev/null +++ b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileTransferMapperTest.java @@ -0,0 +1,33 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.client.CacheClient; +import com.mashibing.test.entity.MobileBlack; +import com.mashibing.test.entity.MobileTransfer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@SpringBootTest +@RunWith(SpringRunner.class) +public class MobileTransferMapperTest { + + @Autowired + private MobileTransferMapper mapper; + + @Autowired + private CacheClient cacheClient; + + + @Test + public void findAll() { + List list = mapper.findAll(); + + for (MobileTransfer mobileTransfer : list) { + cacheClient.set("transfer:" + mobileTransfer.getTransferNumber(),mobileTransfer.getNowIsp()); + } + } +} \ No newline at end of file