Commit d91374865fb33ea96a5ec6c30c9a9b2d04d5d29f
1 parent
97b0ec46
day11-物流信息微服务
Showing
12 changed files
with
457 additions
and
2 deletions
sl-express-ms-transport-info-service/pom.xml
| ... | ... | @@ -49,6 +49,10 @@ |
| 49 | 49 | <artifactId>spring-boot-starter-web</artifactId> |
| 50 | 50 | </dependency> |
| 51 | 51 | <dependency> |
| 52 | + <groupId>org.redisson</groupId> | |
| 53 | + <artifactId>redisson</artifactId> | |
| 54 | + </dependency> | |
| 55 | + <dependency> | |
| 52 | 56 | <groupId>com.alibaba.cloud</groupId> |
| 53 | 57 | <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> |
| 54 | 58 | </dependency> | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/config/BloomFilterConfig.java
0 → 100644
| 1 | +package com.sl.transport.info.config; | |
| 2 | + | |
| 3 | +import lombok.Getter; | |
| 4 | +import org.springframework.beans.factory.annotation.Value; | |
| 5 | +import org.springframework.context.annotation.Configuration; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 布隆过滤器相关配置 | |
| 9 | + */ | |
| 10 | +@Getter | |
| 11 | +@Configuration | |
| 12 | +public class BloomFilterConfig { | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 名称,默认:sl-bloom-filter | |
| 16 | + */ | |
| 17 | + @Value("${bloom.name:sl-bloom-filter}") | |
| 18 | + private String name; | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 布隆过滤器长度,最大支持Integer.MAX_VALUE*2,即:4294967294,默认:1千万 | |
| 22 | + */ | |
| 23 | + @Value("${bloom.expectedInsertions:10000000}") | |
| 24 | + private long expectedInsertions; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 误判率,默认:0.05 | |
| 28 | + */ | |
| 29 | + @Value("${bloom.falseProbability:0.05d}") | |
| 30 | + private double falseProbability; | |
| 31 | + | |
| 32 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/config/CaffeineConfig.java
0 → 100644
| 1 | +package com.sl.transport.info.config; | |
| 2 | + | |
| 3 | +import com.github.benmanes.caffeine.cache.Cache; | |
| 4 | +import com.github.benmanes.caffeine.cache.Caffeine; | |
| 5 | +import com.sl.transport.info.domain.TransportInfoDTO; | |
| 6 | +import org.springframework.beans.factory.annotation.Value; | |
| 7 | +import org.springframework.context.annotation.Bean; | |
| 8 | +import org.springframework.context.annotation.Configuration; | |
| 9 | + | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Caffeine缓存配置 | |
| 13 | + */ | |
| 14 | +@Configuration | |
| 15 | +public class CaffeineConfig { | |
| 16 | + | |
| 17 | + @Value("${caffeine.init}") | |
| 18 | + private Integer init; | |
| 19 | + | |
| 20 | + @Value("${caffeine.max}") | |
| 21 | + private Integer max; | |
| 22 | + | |
| 23 | + @Bean | |
| 24 | + public Cache<String, TransportInfoDTO> transportInfoCache() { | |
| 25 | + return Caffeine.newBuilder() | |
| 26 | + .initialCapacity(init) | |
| 27 | + .maximumSize(max) | |
| 28 | + .build(); | |
| 29 | + } | |
| 30 | + | |
| 31 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/config/MyRedisCacheManager.java
0 → 100644
| 1 | +package com.sl.transport.info.config; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import cn.hutool.core.util.RandomUtil; | |
| 5 | +import org.springframework.data.redis.cache.RedisCache; | |
| 6 | +import org.springframework.data.redis.cache.RedisCacheConfiguration; | |
| 7 | +import org.springframework.data.redis.cache.RedisCacheManager; | |
| 8 | +import org.springframework.data.redis.cache.RedisCacheWriter; | |
| 9 | + | |
| 10 | +import java.time.Duration; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 自定义CacheManager,用于设置不同的过期时间,防止雪崩问题的发生 | |
| 14 | + */ | |
| 15 | +public class MyRedisCacheManager extends RedisCacheManager { | |
| 16 | + | |
| 17 | + public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) { | |
| 18 | + super(cacheWriter, defaultCacheConfiguration); | |
| 19 | + } | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) { | |
| 23 | + //获取到原有过期时间 | |
| 24 | + Duration duration = cacheConfig.getTtl(); | |
| 25 | + if (ObjectUtil.isNotEmpty(duration)) { | |
| 26 | + //在原有时间上随机增加1~10分钟 | |
| 27 | + Duration newDuration = duration.plusMinutes(RandomUtil.randomInt(1, 11)); | |
| 28 | + cacheConfig = cacheConfig.entryTtl(newDuration); | |
| 29 | + } | |
| 30 | + return super.createRedisCache(name, cacheConfig); | |
| 31 | + } | |
| 32 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/config/RedisConfig.java
0 → 100644
| 1 | +package com.sl.transport.info.config; | |
| 2 | + | |
| 3 | +import io.lettuce.core.dynamic.RedisCommandFactory; | |
| 4 | +import org.springframework.beans.factory.annotation.Value; | |
| 5 | +import org.springframework.context.annotation.Bean; | |
| 6 | +import org.springframework.context.annotation.Configuration; | |
| 7 | +import org.springframework.data.redis.cache.RedisCacheConfiguration; | |
| 8 | +import org.springframework.data.redis.cache.RedisCacheManager; | |
| 9 | +import org.springframework.data.redis.cache.RedisCacheWriter; | |
| 10 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
| 11 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 12 | +import org.springframework.data.redis.listener.ChannelTopic; | |
| 13 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 14 | +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; | |
| 15 | +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; | |
| 16 | +import org.springframework.data.redis.serializer.RedisSerializationContext; | |
| 17 | +import org.springframework.data.redis.serializer.StringRedisSerializer; | |
| 18 | + | |
| 19 | +import java.time.Duration; | |
| 20 | + | |
| 21 | +@Configuration | |
| 22 | +public class RedisConfig { | |
| 23 | + | |
| 24 | + public static final String CHANNEL_TOPIC = "sl-express-ms-transport-info-caffeine"; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 存储的默认有效期时间,单位:小时 | |
| 28 | + */ | |
| 29 | + @Value("${redis.ttl:1}") | |
| 30 | + private Integer redisTtl; | |
| 31 | + | |
| 32 | + @Bean | |
| 33 | + public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) { | |
| 34 | + // 默认配置 | |
| 35 | + RedisCacheConfiguration defaultCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() | |
| 36 | + // 设置key的序列化方式为字符串 | |
| 37 | + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) | |
| 38 | + // 设置value的序列化方式为json格式 | |
| 39 | + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) | |
| 40 | + .disableCachingNullValues() // 不缓存null | |
| 41 | + .entryTtl(Duration.ofHours(redisTtl)); // 默认缓存数据保存1小时 | |
| 42 | + | |
| 43 | + // 构redis缓存管理器 | |
| 44 | +// RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder | |
| 45 | +// .fromConnectionFactory(redisTemplate.getConnectionFactory()) | |
| 46 | +// .cacheDefaults(defaultCacheConfiguration) | |
| 47 | +// .transactionAware() // 只在事务成功提交后才会进行缓存的put/evict操作 | |
| 48 | +// .build(); | |
| 49 | + | |
| 50 | + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory()); | |
| 51 | + MyRedisCacheManager myRedisCacheManager = new MyRedisCacheManager(redisCacheWriter, defaultCacheConfiguration); | |
| 52 | + myRedisCacheManager.setTransactionAware(true); | |
| 53 | + return myRedisCacheManager; | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 配置订阅,用于解决Caffeine一致性的问题 | |
| 58 | + * | |
| 59 | + * @param redisCommandFactory 链接工厂 | |
| 60 | + * @param messageListenerAdapter 消息监听器 | |
| 61 | + * @return 消息监听容器 | |
| 62 | + */ | |
| 63 | + @Bean | |
| 64 | + public RedisMessageListenerContainer container( | |
| 65 | + RedisConnectionFactory redisCommandFactory, | |
| 66 | + MessageListenerAdapter messageListenerAdapter | |
| 67 | + ) { | |
| 68 | + RedisMessageListenerContainer container = new RedisMessageListenerContainer(); | |
| 69 | + container.setConnectionFactory(redisCommandFactory); | |
| 70 | + container.addMessageListener(messageListenerAdapter, new ChannelTopic(CHANNEL_TOPIC)); | |
| 71 | + return container; | |
| 72 | + } | |
| 73 | + | |
| 74 | + | |
| 75 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/config/RedissonConfiguration.java
0 → 100644
| 1 | +package com.sl.transport.info.config; | |
| 2 | + | |
| 3 | + | |
| 4 | +import cn.hutool.core.convert.Convert; | |
| 5 | +import cn.hutool.core.util.StrUtil; | |
| 6 | +import org.redisson.Redisson; | |
| 7 | +import org.redisson.api.RedissonClient; | |
| 8 | +import org.redisson.config.Config; | |
| 9 | +import org.redisson.config.SingleServerConfig; | |
| 10 | +import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | |
| 11 | +import org.springframework.context.annotation.Bean; | |
| 12 | +import org.springframework.context.annotation.Configuration; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | + | |
| 16 | +@Configuration | |
| 17 | +public class RedissonConfiguration { | |
| 18 | + | |
| 19 | + @Resource | |
| 20 | + private RedisProperties redisProperties; | |
| 21 | + | |
| 22 | + @Bean | |
| 23 | + public RedissonClient redissonSingle() { | |
| 24 | + Config config = new Config(); | |
| 25 | + SingleServerConfig serverConfig = config.useSingleServer() | |
| 26 | + .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort()); | |
| 27 | + if (null != (redisProperties.getTimeout())) { | |
| 28 | + serverConfig.setTimeout(1000 * Convert.toInt(redisProperties.getTimeout().getSeconds())); | |
| 29 | + } | |
| 30 | + if (StrUtil.isNotEmpty(redisProperties.getPassword())) { | |
| 31 | + serverConfig.setPassword(redisProperties.getPassword()); | |
| 32 | + } | |
| 33 | + return Redisson.create(config); | |
| 34 | + } | |
| 35 | + | |
| 36 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/controller/TransportInfoController.java
| 1 | 1 | package com.sl.transport.info.controller; |
| 2 | 2 | |
| 3 | +import com.github.benmanes.caffeine.cache.Cache; | |
| 3 | 4 | import com.sl.transport.common.exception.SLException; |
| 4 | 5 | import com.sl.transport.common.util.BeanUtil; |
| 5 | 6 | import com.sl.transport.common.util.ObjectUtil; |
| 7 | +import com.sl.transport.info.config.CaffeineConfig; | |
| 6 | 8 | import com.sl.transport.info.domain.TransportInfoDTO; |
| 7 | 9 | import com.sl.transport.info.entity.TransportInfoEntity; |
| 8 | 10 | import com.sl.transport.info.enums.ExceptionEnum; |
| 11 | +import com.sl.transport.info.service.BloomFilterService; | |
| 9 | 12 | import com.sl.transport.info.service.TransportInfoService; |
| 10 | 13 | import io.swagger.annotations.Api; |
| 11 | 14 | import io.swagger.annotations.ApiImplicitParam; |
| 12 | 15 | import io.swagger.annotations.ApiImplicitParams; |
| 13 | 16 | import io.swagger.annotations.ApiOperation; |
| 17 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 14 | 18 | import org.springframework.web.bind.annotation.GetMapping; |
| 15 | 19 | import org.springframework.web.bind.annotation.PathVariable; |
| 16 | 20 | import org.springframework.web.bind.annotation.RequestMapping; |
| ... | ... | @@ -26,6 +30,12 @@ public class TransportInfoController { |
| 26 | 30 | @Resource |
| 27 | 31 | private TransportInfoService transportInfoService; |
| 28 | 32 | |
| 33 | + @Resource | |
| 34 | + public Cache<String, TransportInfoDTO> transportInfoCache; | |
| 35 | + | |
| 36 | + @Autowired | |
| 37 | + private BloomFilterService bloomFilterService; | |
| 38 | + | |
| 29 | 39 | /** |
| 30 | 40 | * 根据运单id查询运单信息 |
| 31 | 41 | * |
| ... | ... | @@ -38,10 +48,23 @@ public class TransportInfoController { |
| 38 | 48 | @ApiOperation(value = "查询", notes = "根据运单id查询物流信息") |
| 39 | 49 | @GetMapping("{transportOrderId}") |
| 40 | 50 | public TransportInfoDTO queryByTransportOrderId(@PathVariable("transportOrderId") String transportOrderId) { |
| 41 | - TransportInfoEntity transportInfoEntity = transportInfoService.queryByTransportOrderId(transportOrderId); | |
| 42 | - if (ObjectUtil.isNotEmpty(transportInfoEntity)) { | |
| 51 | +// 如果布隆过滤器中不存在,无需缓存命中,直接返回即可 | |
| 52 | + boolean contains = bloomFilterService.contains(transportOrderId); | |
| 53 | + if (!contains) { | |
| 54 | + throw new SLException(ExceptionEnum.NOT_FOUND); | |
| 55 | + } | |
| 56 | + | |
| 57 | + TransportInfoDTO transportInfoDTO = transportInfoCache.get(transportOrderId, s -> { | |
| 58 | +// 未命中,查询MongoMD | |
| 59 | + TransportInfoEntity transportInfoEntity = this.transportInfoService.queryByTransportOrderId(transportOrderId); | |
| 60 | +// 转换成DTO | |
| 43 | 61 | return BeanUtil.toBean(transportInfoEntity, TransportInfoDTO.class); |
| 62 | + }); | |
| 63 | + | |
| 64 | + if (ObjectUtil.isNotEmpty(transportInfoDTO)) { | |
| 65 | + return transportInfoDTO; | |
| 44 | 66 | } |
| 67 | + | |
| 45 | 68 | throw new SLException(ExceptionEnum.NOT_FOUND); |
| 46 | 69 | } |
| 47 | 70 | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/mq/RedisMessageListener.java
0 → 100644
| 1 | +package com.sl.transport.info.mq; | |
| 2 | + | |
| 3 | +import cn.hutool.core.convert.Convert; | |
| 4 | +import com.github.benmanes.caffeine.cache.Cache; | |
| 5 | +import com.sl.transport.info.domain.TransportInfoDTO; | |
| 6 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 7 | +import org.springframework.data.redis.connection.Message; | |
| 8 | +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; | |
| 9 | +import org.springframework.stereotype.Component; | |
| 10 | + | |
| 11 | +import javax.annotation.Resource; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * redis消息监听,解决Caffeine一致性的问题 | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +public class RedisMessageListener extends MessageListenerAdapter { | |
| 18 | + | |
| 19 | + @Resource | |
| 20 | + public Cache<String, TransportInfoDTO> transportInfoCache; | |
| 21 | + | |
| 22 | + @Override | |
| 23 | + public void onMessage(Message message, byte[] pattern) { | |
| 24 | +// 获取到消息中的运单ID | |
| 25 | + String transportOrderId = Convert.toStr(message); | |
| 26 | + | |
| 27 | +// 将本JVM中的缓存删除掉 | |
| 28 | + transportInfoCache.invalidate(transportOrderId); | |
| 29 | + } | |
| 30 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/mq/TransportInfoMQListener.java
| 1 | 1 | package com.sl.transport.info.mq; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.convert.Convert; | |
| 4 | +import cn.hutool.core.util.StrUtil; | |
| 5 | +import cn.hutool.json.JSONUtil; | |
| 6 | +import com.sl.ms.transport.api.OrganFeign; | |
| 3 | 7 | import com.sl.transport.common.constant.Constants; |
| 8 | +import com.sl.transport.common.vo.TransportInfoMsg; | |
| 9 | +import com.sl.transport.domain.OrganDTO; | |
| 10 | +import com.sl.transport.info.entity.TransportInfoDetail; | |
| 11 | +import com.sl.transport.info.service.TransportInfoService; | |
| 4 | 12 | import org.springframework.amqp.core.ExchangeTypes; |
| 5 | 13 | import org.springframework.amqp.rabbit.annotation.Exchange; |
| 6 | 14 | import org.springframework.amqp.rabbit.annotation.Queue; |
| 7 | 15 | import org.springframework.amqp.rabbit.annotation.QueueBinding; |
| 8 | 16 | import org.springframework.amqp.rabbit.annotation.RabbitListener; |
| 17 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 9 | 18 | import org.springframework.stereotype.Component; |
| 10 | 19 | import org.springframework.transaction.annotation.Transactional; |
| 11 | 20 | |
| ... | ... | @@ -15,6 +24,13 @@ import org.springframework.transaction.annotation.Transactional; |
| 15 | 24 | @Component |
| 16 | 25 | public class TransportInfoMQListener { |
| 17 | 26 | |
| 27 | + @Autowired | |
| 28 | + private OrganFeign organFeign; | |
| 29 | + | |
| 30 | + @Autowired | |
| 31 | + private TransportInfoService transportInfoService; | |
| 32 | + | |
| 33 | + | |
| 18 | 34 | @RabbitListener(bindings = @QueueBinding( |
| 19 | 35 | value = @Queue(name = Constants.MQ.Queues.TRANSPORT_INFO_APPEND), |
| 20 | 36 | exchange = @Exchange(name = Constants.MQ.Exchanges.TRANSPORT_INFO, type = ExchangeTypes.TOPIC), |
| ... | ... | @@ -23,6 +39,29 @@ public class TransportInfoMQListener { |
| 23 | 39 | @Transactional |
| 24 | 40 | public void listenTransportInfoMsg(String msg) { |
| 25 | 41 | //{"info":"您的快件已到达【$organId】", "status":"运输中", "organId":90001, "transportOrderId":"SL920733749248" , "created":1653133234913} |
| 42 | + TransportInfoMsg transportInfoMsg = JSONUtil.toBean(msg, TransportInfoMsg.class); | |
| 43 | + Long organId = transportInfoMsg.getOrganId(); | |
| 44 | + String transportOrderId = Convert.toStr(transportInfoMsg.getTransportOrderId()); | |
| 45 | + String info = transportInfoMsg.getInfo(); | |
| 46 | + | |
| 47 | +// 查询机构信息 | |
| 48 | + if (StrUtil.contains(info, "$organId")) { | |
| 49 | + OrganDTO organDTO = organFeign.queryById(organId); | |
| 50 | + if (organDTO == null) { | |
| 51 | + return; | |
| 52 | + } | |
| 53 | + info = StrUtil.replace(info, "$organId", organDTO.getName()); | |
| 54 | + } | |
| 55 | + | |
| 56 | +// 封装Detail对象 | |
| 57 | + TransportInfoDetail infoDetail = TransportInfoDetail.builder() | |
| 58 | + .info(info) | |
| 59 | + .status(transportInfoMsg.getStatus()) | |
| 60 | + .created(transportInfoMsg.getCreated()) | |
| 61 | + .build(); | |
| 62 | + | |
| 63 | +// 存储到MongoDB | |
| 64 | + transportInfoService.saveOrUpdate(transportOrderId, infoDetail); | |
| 26 | 65 | |
| 27 | 66 | } |
| 28 | 67 | } | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/service/BloomFilterService.java
0 → 100644
| 1 | +package com.sl.transport.info.service; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 布隆过滤器服务 | |
| 5 | + */ | |
| 6 | +public interface BloomFilterService { | |
| 7 | + | |
| 8 | + /** | |
| 9 | + * 初始化布隆过滤器 | |
| 10 | + */ | |
| 11 | + void init(); | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 向布隆过滤器中添加数据 | |
| 15 | + * | |
| 16 | + * @param obj 待添加的数据 | |
| 17 | + * @return 是否成功 | |
| 18 | + */ | |
| 19 | + boolean add(Object obj); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 判断数据是否存在 | |
| 23 | + * | |
| 24 | + * @param obj 数据 | |
| 25 | + * @return 是否存在 | |
| 26 | + */ | |
| 27 | + boolean contains(Object obj); | |
| 28 | + | |
| 29 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/service/impl/BloomFilterServiceImpl.java
0 → 100644
| 1 | +package com.sl.transport.info.service.impl; | |
| 2 | + | |
| 3 | +import com.sl.transport.info.config.BloomFilterConfig; | |
| 4 | +import com.sl.transport.info.service.BloomFilterService; | |
| 5 | +import org.redisson.api.RBloomFilter; | |
| 6 | +import org.redisson.api.RedissonClient; | |
| 7 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 8 | +import org.springframework.stereotype.Service; | |
| 9 | + | |
| 10 | +import javax.annotation.PostConstruct; | |
| 11 | + | |
| 12 | +@Service | |
| 13 | +public class BloomFilterServiceImpl implements BloomFilterService { | |
| 14 | + | |
| 15 | + @Autowired | |
| 16 | + private RedissonClient redissonClient; | |
| 17 | + | |
| 18 | + @Autowired | |
| 19 | + private BloomFilterConfig bloomFilterConfig; | |
| 20 | + | |
| 21 | + private RBloomFilter<Object> getBloomFilter() { | |
| 22 | + return redissonClient.getBloomFilter(this.bloomFilterConfig.getName()); | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + @PostConstruct | |
| 27 | + public void init() { | |
| 28 | + RBloomFilter<Object> bloomFilter = getBloomFilter(); | |
| 29 | + bloomFilter.tryInit( | |
| 30 | + bloomFilterConfig.getExpectedInsertions(), | |
| 31 | + bloomFilterConfig.getFalseProbability()); | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public boolean add(Object obj) { | |
| 36 | + return getBloomFilter().add(obj); | |
| 37 | + } | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public boolean contains(Object obj) { | |
| 41 | + return getBloomFilter().contains(obj); | |
| 42 | + } | |
| 43 | + | |
| 44 | +} | ... | ... |
sl-express-ms-transport-info-service/src/main/java/com/sl/transport/info/service/impl/TransportInfoServiceImpl.java
0 → 100644
| 1 | +package com.sl.transport.info.service.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.ListUtil; | |
| 4 | +import com.github.benmanes.caffeine.cache.Cache; | |
| 5 | +import com.sl.transport.common.util.ObjectUtil; | |
| 6 | +import com.sl.transport.info.config.RedisConfig; | |
| 7 | +import com.sl.transport.info.entity.TransportInfoDetail; | |
| 8 | +import com.sl.transport.info.entity.TransportInfoEntity; | |
| 9 | +import com.sl.transport.info.service.TransportInfoService; | |
| 10 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 11 | +import org.springframework.cache.annotation.CachePut; | |
| 12 | +import org.springframework.cache.annotation.Cacheable; | |
| 13 | +import org.springframework.data.mongodb.core.MongoTemplate; | |
| 14 | +import org.springframework.data.mongodb.core.query.Criteria; | |
| 15 | +import org.springframework.data.mongodb.core.query.Query; | |
| 16 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
| 17 | +import org.springframework.stereotype.Service; | |
| 18 | + | |
| 19 | +@Service | |
| 20 | +public class TransportInfoServiceImpl implements TransportInfoService { | |
| 21 | + | |
| 22 | + @Autowired | |
| 23 | + private MongoTemplate mongoTemplate; | |
| 24 | + @Autowired | |
| 25 | + private Cache transportInfoCache; | |
| 26 | + private StringRedisTemplate stringRedisTemplate; | |
| 27 | + @Autowired | |
| 28 | + private BloomFilterServiceImpl bloomFilterService; | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 如果运单数据不存在,就新增,否则更新数据 | |
| 32 | + * | |
| 33 | + * @param transportOrderId 运单id | |
| 34 | + * @param infoDetail 信息详情 | |
| 35 | + * @return 运输信息数据 | |
| 36 | + */ | |
| 37 | + @Override | |
| 38 | + @CachePut(value = "transport-info",key = "#p0") | |
| 39 | + public TransportInfoEntity saveOrUpdate(String transportOrderId, TransportInfoDetail infoDetail) { | |
| 40 | +// 根据运单ID查询 | |
| 41 | + Query query = Query.query(Criteria.where("transportOrderId").is(transportOrderId)); | |
| 42 | + TransportInfoEntity transportInfoEntity = mongoTemplate.findOne(query, TransportInfoEntity.class); | |
| 43 | + if (ObjectUtil.isEmpty(transportInfoEntity)) { | |
| 44 | +// 运单信息不存在,新增数据 | |
| 45 | + transportInfoEntity = new TransportInfoEntity(); | |
| 46 | + transportInfoEntity.setTransportOrderId(transportOrderId); | |
| 47 | + transportInfoEntity.setInfoList(ListUtil.toList(infoDetail)); | |
| 48 | + transportInfoEntity.setCreated(System.currentTimeMillis()); | |
| 49 | + | |
| 50 | +// 写到布隆过滤器中 | |
| 51 | + bloomFilterService.add(transportOrderId); | |
| 52 | + } else { | |
| 53 | +// 运单信息存在,只需要追加物流详情数据 | |
| 54 | + transportInfoEntity.getInfoList().add(infoDetail); | |
| 55 | + } | |
| 56 | + | |
| 57 | +// 无论新增还是更新都要设置更新时间 | |
| 58 | + transportInfoEntity.setUpdated(System.currentTimeMillis()); | |
| 59 | + | |
| 60 | +// 清除缓存中的数据 | |
| 61 | +// transportInfoCache.invalidate(transportOrderId); | |
| 62 | + stringRedisTemplate.convertAndSend(RedisConfig.CHANNEL_TOPIC, transportOrderId); | |
| 63 | + | |
| 64 | + return mongoTemplate.save(transportInfoEntity); | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * 根据运单id查询运输信息 | |
| 69 | + * | |
| 70 | + * @param transportOrderId 运单id | |
| 71 | + * @return 运输信息数据 | |
| 72 | + */ | |
| 73 | + @Override | |
| 74 | + @Cacheable(value = "transport-info", key = "#p0") | |
| 75 | + public TransportInfoEntity queryByTransportOrderId(String transportOrderId) { | |
| 76 | + Query query = Query.query(Criteria.where("transportOrderId").is(transportOrderId)); | |
| 77 | + return mongoTemplate.findOne(query, TransportInfoEntity.class); | |
| 78 | + } | |
| 79 | + | |
| 80 | +} | ... | ... |