diff --git a/beacon-cache/src/main/java/com/mashibing/cache/controller/CacheController.java b/beacon-cache/src/main/java/com/mashibing/cache/controller/CacheController.java index b563c88..5e10bb7 100644 --- a/beacon-cache/src/main/java/com/mashibing/cache/controller/CacheController.java +++ b/beacon-cache/src/main/java/com/mashibing/cache/controller/CacheController.java @@ -38,6 +38,13 @@ public class CacheController { redisClient.sAdd(key,value); } + @PostMapping(value = "/cache/saddstr/{key}") + public void saddStr(@PathVariable(value = "key")String key, @RequestBody String... value){ + log.info("【缓存模块】 saddStr方法,存储key = {},存储value = {}", key, value); + redisClient.sAdd(key,value); + } + + @GetMapping("/cache/hgetall/{key}") public Map hGetAll(@PathVariable(value = "key")String key){ log.info("【缓存模块】 hGetAll方法,获取key ={} 的数据", key); @@ -62,6 +69,23 @@ public class CacheController { return values; } + @PostMapping("/cache/pipeline/string") + public void pipelineString(@RequestBody Map map){ + log.info("【缓存模块】 pipelineString,获取到存储的数据,map的长度 ={}的数据", map.size()); + redisClient.pipelined(operations -> { + for (Map.Entry entry : map.entrySet()) { + operations.opsForValue().set(entry.getKey(),entry.getValue()); + } + }); + } + + @GetMapping(value = "/cache/get/{key}") + public Object get(@PathVariable(value = "key") String key) { + log.info("【缓存模块】 get方法,查询key = {}", key); + Object value = redisClient.get(key); + log.info("【缓存模块】 get方法,查询key = {}对应的value = {}", key,value); + return value; + } diff --git a/beacon-cache/src/main/java/com/mashibing/cache/controller/TestController.java b/beacon-cache/src/main/java/com/mashibing/cache/controller/TestController.java index b3d9ac7..e0f2357 100644 --- a/beacon-cache/src/main/java/com/mashibing/cache/controller/TestController.java +++ b/beacon-cache/src/main/java/com/mashibing/cache/controller/TestController.java @@ -31,17 +31,19 @@ public class TestController { Map result = redisClient.getMap(key); return result; } - @GetMapping("/test/xxx") - public Map xxx(){ - Map maps = new HashMap<>(); - maps.put("1801003","北京 北京,电信"); - maps.put("1734310","北京 北京,电信"); + // 管道测试 + @PostMapping("/test/pipeline") + public String pipeline(){ + Map maps = new HashMap<>(); + maps.put("1888888","北京 北京,移动"); + maps.put("1888889","北京 北京,电信"); redisClient.pipelined(operations -> { for (Map.Entry entry : maps.entrySet()) { operations.opsForValue().set(entry.getKey(),entry.getValue()); } }); - return null; + return "ok"; } + } 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 62bba3e..e81cc70 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 @@ -23,6 +23,15 @@ public interface CacheConstant { * 客户的余额 */ String CLIENT_BALANCE = "client_balance:"; + /** + * 号段补全 + */ + String PHASE = "phase:"; + + /** + * 敏感词前缀 + */ + String DIRTY_WORD = "dirty_word"; } 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 e84dbae..a7494e1 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 @@ -11,4 +11,10 @@ public interface RabbitMQConstants { * 接口模块发送消息到策略模块的队列名称 */ String SMS_PRE_SEND = "sms_pre_send_topic"; + + + /** + * 策略模块发送手机号归属地&运营商到后台管理模块的队列名称 + */ + String MOBILE_AREA_OPERATOR = "mobile_area_operator_topic"; } diff --git a/beacon-common/src/main/java/com/mashibing/common/enums/MobileOperatorEnum.java b/beacon-common/src/main/java/com/mashibing/common/enums/MobileOperatorEnum.java new file mode 100644 index 0000000..6357ac7 --- /dev/null +++ b/beacon-common/src/main/java/com/mashibing/common/enums/MobileOperatorEnum.java @@ -0,0 +1,27 @@ +package com.mashibing.common.enums; + +import lombok.Getter; + +/** + * @author zjw + * @description + */ +@Getter +public enum MobileOperatorEnum { + + CHINA_MOBILE(1,"移动"), + CHINA_UNICOM(2,"联通"), + CHINA_TELECOM(3,"电信"), + UNKNOWN(0,"未知"); + + private Integer operatorId; + + private String operatorName; + + + + MobileOperatorEnum(Integer operatorId, String operatorName) { + this.operatorId = operatorId; + this.operatorName = operatorName; + } +} diff --git a/beacon-common/src/main/java/com/mashibing/common/util/OperatorUtil.java b/beacon-common/src/main/java/com/mashibing/common/util/OperatorUtil.java new file mode 100644 index 0000000..bf1480c --- /dev/null +++ b/beacon-common/src/main/java/com/mashibing/common/util/OperatorUtil.java @@ -0,0 +1,33 @@ +package com.mashibing.common.util; + +import com.mashibing.common.enums.MobileOperatorEnum; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author zjw + * @description + */ +public class OperatorUtil { + + private static Map operators = new HashMap<>(); + + static{ + MobileOperatorEnum[] operatorEnums = MobileOperatorEnum.values(); + for (MobileOperatorEnum operatorEnum : operatorEnums) { + operators.put(operatorEnum.getOperatorName(),operatorEnum.getOperatorId()); + } + } + + /** + * 通过运营商名称获取运营商Id + * @param operatorName + * @return + */ + public static Integer getOperatorIdByOperatorName(String operatorName){ + return operators.get(operatorName); + } + + +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/StrategyStarterApp.java b/beacon-strategy/src/main/java/com/mashibing/strategy/StrategyStarterApp.java index 32793f4..41a60d5 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/StrategyStarterApp.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/StrategyStarterApp.java @@ -4,6 +4,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; /** * @author zjw @@ -18,4 +20,9 @@ public class StrategyStarterApp { SpringApplication.run(StrategyStarterApp.class,args); } + + @Bean + public RestTemplate restTemplate(){ + return new RestTemplate(); + } } 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 527373a..da295a4 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 @@ -3,6 +3,7 @@ package com.mashibing.strategy.client; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; /** * @author zjw @@ -13,4 +14,7 @@ public interface BeaconCacheClient { @GetMapping("/cache/hget/{key}/{field}") String hget(@PathVariable(value = "key")String key, @PathVariable(value = "field")String field); + + @GetMapping(value = "/cache/get/{key}") + String getString(@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 new file mode 100644 index 0000000..eebd603 --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitMQConfig.java @@ -0,0 +1,26 @@ +package com.mashibing.strategy.config; + +import com.mashibing.common.constant.RabbitMQConstants; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 构建队列&交换机信息 + * @author zjw + * @description + */ +@Configuration +public class RabbitMQConfig { + + /** + * 接口模块发送消息到策略模块的队列 + * @return + */ + @Bean + public Queue preSendQueue(){ + return QueueBuilder.durable(RabbitMQConstants.MOBILE_AREA_OPERATOR).build(); + } + +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitTemplateConfig.java b/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitTemplateConfig.java new file mode 100644 index 0000000..e66d0fb --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/config/RabbitTemplateConfig.java @@ -0,0 +1,55 @@ +package com.mashibing.strategy.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 设置RabbitTemplate的confirm&return机制 + * @author zjw + * @description + */ +@Configuration +@Slf4j +public class RabbitTemplateConfig { + + @Bean + public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){ + //1、构建RabbitTemplate对象 + RabbitTemplate rabbitTemplate = new RabbitTemplate(); + + //2、设置connectionFactory + rabbitTemplate.setConnectionFactory(connectionFactory); + + //3、配置confirm机制 + rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback(){ + + @Override + public void confirm(CorrelationData correlationData, boolean ack, String cause) { + // ack为false,代表消息没有发送到exchange。 + if(!ack){ + log.error("【接口模块-发送消息】 消息没有发送到交换机,correlationData = {},cause = {}",correlationData,cause); + } + } + }); + + //4、配置return机制 + rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback(){ + + // 触发这个回调,说明交换机没有把消息路由到指定的队列中 + @Override + public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { + log.error("【接口模块-发送消息】 消息没有路由到指定的Queue。 message = {},exchange = {},routingKey = {}", + new String(message.getBody()),exchange,routingKey); + } + }); + + //5、返回 + return rabbitTemplate; + } + +} diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/PhaseStrategyFilter.java b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/PhaseStrategyFilter.java index 2384dd0..72bf40b 100644 --- a/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/PhaseStrategyFilter.java +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/filter/impl/PhaseStrategyFilter.java @@ -1,12 +1,21 @@ package com.mashibing.strategy.filter.impl; +import com.mashibing.common.constant.CacheConstant; +import com.mashibing.common.constant.RabbitMQConstants; import com.mashibing.common.model.StandardSubmit; +import com.mashibing.common.util.OperatorUtil; +import com.mashibing.strategy.client.BeaconCacheClient; import com.mashibing.strategy.filter.StrategyFilter; +import com.mashibing.strategy.util.MobileOperatorUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 号段补全:获取手机号的运营商以及对应的归属地 + * * @author zjw * @description */ @@ -14,8 +23,57 @@ import org.springframework.stereotype.Service; @Slf4j public class PhaseStrategyFilter implements StrategyFilter { + /** + * 切分手机号前7位 + */ + private final int MOBILE_START = 0; + private final int MOBILE_END = 7; + /** + * 校验的长度 + */ + private final int LENGTH = 2; + /** + * 分割区域和运营商的标识 + */ + private final String SEPARATE = ","; + /** + * 未知的情况 + */ + private final String UNKNOWN = "未知 未知,未知"; + + @Autowired + private BeaconCacheClient cacheClient; + + @Autowired + private MobileOperatorUtil mobileOperatorUtil; + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Override public void strategy(StandardSubmit submit) { - log.info("【策略模块-号段补齐】 校验ing…………"); + log.info("【策略模块-号段补齐】 补全ing…………"); + //1、根据手机号前7位,查询手机号信息 + String mobile = submit.getMobile().substring(MOBILE_START, MOBILE_END); + String mobileInfo = cacheClient.getString(CacheConstant.PHASE + mobile); + + getMobileInfo: if (StringUtils.isEmpty(mobileInfo)) { + //2、查询不到,需要调用三方接口,查询手机号对应信息 + mobileInfo = mobileOperatorUtil.getMobileInfoBy360(mobile); + if(!StringUtils.isEmpty(mobileInfo)){ + //3、调用三方查到信息后,发送消息到MQ,并且同步到MySQL和Redis + rabbitTemplate.convertAndSend(RabbitMQConstants.MOBILE_AREA_OPERATOR,submit.getMobile()); + break getMobileInfo; + } + mobileInfo = UNKNOWN; + } + + //4、无论是Redis还是三方接口查询到之后,封装到StandardSubmit对象中 + String[] areaAndOperator = mobileInfo.split(SEPARATE); + if (areaAndOperator.length == LENGTH) { + submit.setArea(areaAndOperator[0]); + submit.setOperatorId(OperatorUtil.getOperatorIdByOperatorName(areaAndOperator[1])); + } } } diff --git a/beacon-strategy/src/main/java/com/mashibing/strategy/util/MobileOperatorUtil.java b/beacon-strategy/src/main/java/com/mashibing/strategy/util/MobileOperatorUtil.java new file mode 100644 index 0000000..c12cb5a --- /dev/null +++ b/beacon-strategy/src/main/java/com/mashibing/strategy/util/MobileOperatorUtil.java @@ -0,0 +1,66 @@ +package com.mashibing.strategy.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.aspectj.apache.bcel.generic.ObjectType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +/** + * 获取手机号归属地和运营商的工具 + * @author zjw + * @description + */ +@Component +public class MobileOperatorUtil { + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private ObjectMapper objectMapper; + + private final String url1 = "https://cx.shouji.360.cn/phonearea.php?number="; + + private final String CODE = "code"; + private final String DATA = "data"; + private final String PROVINCE = "province"; + private final String CITY = "city"; + private final String SP = "sp"; + private final String SPACE = " "; + private final String SEPARATE = ","; + + /** + * 获取手机号信息 + * @param mobile 手机号前7位即可 + * @return + */ + public String getMobileInfoBy360(String mobile){ + String url = url1; + //1、发送请求获取信息 + String mobileInfoJSON = restTemplate.getForObject(url + mobile, String.class); + // {"code":0,"data":{"province":"\u4e91\u5357","city":"\u6606\u660e","sp":"\u79fb\u52a8"}} + //2、解析JSON + Map map = null; + try { + map = objectMapper.readValue(mobileInfoJSON, Map.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + Integer code = (Integer) map.get(CODE); + if(code != 0){ + return null; + } + Map areaAndOperator = (Map) map.get(DATA); + String province = areaAndOperator.get(PROVINCE); + String city = areaAndOperator.get(CITY); + String sp = areaAndOperator.get(SP); + //3、封装为 省 市,运营商 的格式返回 + return province + SPACE +city + SEPARATE + sp; + } + + +} diff --git a/beacon-test/src/main/java/com/mashibing/test/client/CacheClient.java b/beacon-test/src/main/java/com/mashibing/test/client/CacheClient.java index 87da2e4..b1894b2 100644 --- a/beacon-test/src/main/java/com/mashibing/test/client/CacheClient.java +++ b/beacon-test/src/main/java/com/mashibing/test/client/CacheClient.java @@ -25,4 +25,9 @@ public interface CacheClient { @PostMapping(value = "/cache/sadd/{key}") void sadd(@PathVariable(value = "key")String key, @RequestBody Map... maps); + @PostMapping("/cache/pipeline/string") + void pipelineString(@RequestBody Map map); + + @PostMapping(value = "/cache/saddstr/{key}") + void saddStr(@PathVariable(value = "key")String key, @RequestBody String... value); } diff --git a/beacon-test/src/main/java/com/mashibing/test/entity/MobileArea.java b/beacon-test/src/main/java/com/mashibing/test/entity/MobileArea.java new file mode 100644 index 0000000..08d7c0a --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/entity/MobileArea.java @@ -0,0 +1,38 @@ +package com.mashibing.test.entity; + +/** + * @author zjw + * @description + */ +public class MobileArea { + + private String mobileNumber; + + private String mobileArea; + + private String mobileType; + + public String getMobileNumber() { + return mobileNumber; + } + + public void setMobileNumber(String mobileNumber) { + this.mobileNumber = mobileNumber; + } + + public String getMobileArea() { + return mobileArea; + } + + public void setMobileArea(String mobileArea) { + this.mobileArea = mobileArea; + } + + public String getMobileType() { + return mobileType; + } + + public void setMobileType(String mobileType) { + this.mobileType = mobileType; + } +} diff --git a/beacon-test/src/main/java/com/mashibing/test/mapper/MobileAreaMapper.java b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileAreaMapper.java new file mode 100644 index 0000000..c8bc48d --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileAreaMapper.java @@ -0,0 +1,19 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.entity.ClientBalance; +import com.mashibing.test.entity.MobileArea; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author zjw + * @description + */ +public interface MobileAreaMapper { + + @Select("select mobile_number,mobile_area,mobile_type from mobile_area") + List findAll(); + +} diff --git a/beacon-test/src/main/java/com/mashibing/test/mapper/MobileDirtyWordMapper.java b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileDirtyWordMapper.java new file mode 100644 index 0000000..3a01056 --- /dev/null +++ b/beacon-test/src/main/java/com/mashibing/test/mapper/MobileDirtyWordMapper.java @@ -0,0 +1,17 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.entity.MobileArea; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * @author zjw + * @description + */ +public interface MobileDirtyWordMapper { + + @Select("select dirtyword from mobile_dirtyword") + List findDirtyWord(); + +} diff --git a/beacon-test/src/main/resources/application.yml b/beacon-test/src/main/resources/application.yml index 2daa35d..b692038 100644 --- a/beacon-test/src/main/resources/application.yml +++ b/beacon-test/src/main/resources/application.yml @@ -20,4 +20,4 @@ server: # mybatis mybatis: configuration: - map-underscore-to-camel-case: true \ No newline at end of file + map-underscore-to-camel-case: true diff --git a/beacon-test/src/test/java/com/mashibing/test/mapper/MobileAreaMapperTest.java b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileAreaMapperTest.java new file mode 100644 index 0000000..1725133 --- /dev/null +++ b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileAreaMapperTest.java @@ -0,0 +1,37 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.client.CacheClient; +import com.mashibing.test.entity.MobileArea; +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; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@RunWith(SpringRunner.class) +public class MobileAreaMapperTest { + + @Autowired + private MobileAreaMapper mapper; + + @Autowired + private CacheClient cacheClient; + + + @Test + public void findAll() { + List list = mapper.findAll(); + Map map = new HashMap(list.size()); + for (MobileArea mobileArea : list) { + map.put("phase:" + mobileArea.getMobileNumber(),mobileArea.getMobileArea() + "," + mobileArea.getMobileType()); + } + cacheClient.pipelineString(map); + } +} \ No newline at end of file diff --git a/beacon-test/src/test/java/com/mashibing/test/mapper/MobileDirtyWordMapperTest.java b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileDirtyWordMapperTest.java new file mode 100644 index 0000000..8ec4d7c --- /dev/null +++ b/beacon-test/src/test/java/com/mashibing/test/mapper/MobileDirtyWordMapperTest.java @@ -0,0 +1,32 @@ +package com.mashibing.test.mapper; + +import com.mashibing.test.client.CacheClient; +import com.mashibing.test.entity.MobileArea; +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 MobileDirtyWordMapperTest { + + @Autowired + private MobileDirtyWordMapper mapper; + + @Autowired + private CacheClient cacheClient; + + + @Test + public void findAll() { + List dirtyWords = mapper.findDirtyWord(); + + cacheClient.saddStr("dirty_word",dirtyWords.toArray(new String[]{})); + } +} \ No newline at end of file