问题描述
最近在学习Redis,动手搭建了黑马点评项目,配置文件都修改好了,Redis也能正常连接上,但运行项目的时候卡住了,发现官方提供的完整代码跑不起来,控制台一直在刷错误信息,如下图:
问题定位
定位到VoucherOrderServiceImpl
文件可以发现run方法中有一个while循环:
@Override
public void run() {
while (true) {
try {
// 1.获取消息队列中的订单信息 XREADGROUP GROUP g1 c1 COUNT 1 BLOCK 2000 STREAMS s1 >
List<MapRecord<String, Object, Object>> list = stringRedisTemplate.opsForStream().read(
Consumer.from("g1", "c1"),
StreamReadOptions.empty().count(1).block(Duration.ofSeconds(2)),
StreamOffset.create("stream.orders", ReadOffset.lastConsumed())
);
// 2.判断订单信息是否为空
if (list == null || list.isEmpty()) {
// 如果为null,说明没有消息,继续下一次循环
continue;
}
// 解析数据
MapRecord<String, Object, Object> record = list.get(0);
Map<Object, Object> value = record.getValue();
VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(value, new VoucherOrder(), true);
// 3.创建订单
createVoucherOrder(voucherOrder);
// 4.确认消息 XACK
stringRedisTemplate.opsForStream().acknowledge("s1", "g1", record.getId());
} catch (Exception e) {
log.error("处理订单异常", e);
handlePendingList();
}
}
}
由于while(true)
循环会一直执行,其作用是不断从Redis的消息队列中读取消息。但大家一开始搭建项目的时候还没有创建Redis的消息队列。因此启动就会出错。
老师那边演示的代码是不完整版的,因此不会报错。但我们从黑马那边拿到的资料里的代码是完整版的,导入之后直接运行就会报错。
问题解决
为了保证能正常学习此项目,所以大家刚开始搭建此项目的时候,可以先不提交此任务,注释掉提交任务的代码(后面深入学习之后会打开注释),如下图所示:
注释掉代码提交的部分之后,项目就可以正常运行了。
然后还有一个小点需要注意:
我们可以运行
hm-dianping\src\test\java\com\hmdp
目录下的HmDianPingApplicationTests.java
文件中的loadShopData()
方法(代码如下)将一些信息写入redis数据库。
@Test
void loadShopData() {
// 1.查询店铺信息
List<Shop> list = shopService.list();
// 2.把店铺分组,按照typeId分组,typeId一致的放到一个集合
Map<Long, List<Shop>> map = list.stream().collect(Collectors.groupingBy(Shop::getTypeId));
// 3.分批完成写入Redis
for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
// 3.1.获取类型id
Long typeId = entry.getKey();
String key = SHOP_GEO_KEY + typeId;
// 3.2.获取同类型的店铺的集合
List<Shop> value = entry.getValue();
List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(value.size());
// 3.3.写入redis GEOADD key 经度 纬度 member
for (Shop shop : value) {
// stringRedisTemplate.opsForGeo().add(key, new Point(shop.getX(), shop.getY()), shop.getId().toString());
locations.add(new RedisGeoCommands.GeoLocation<>(
shop.getId().toString(),
new Point(shop.getX(), shop.getY())
));
}
stringRedisTemplate.opsForGeo().add(key, locations);
}
然后就可以开始愉快地学习啦!!!