淘淘商城47-商品详情页面之添加热点商品缓存

版权声明:本文为博主原创文章,如有转载请注明出处,谢谢。 https://blog.csdn.net/pdsu161530247/article/details/82119208

目录

1.为什么要使用缓存?

2.缓存数据库中表的分析

2.1分析

2.2总结

3.后端代码实现

3.1引入redis客户端

3.2配置常量配置文件

3.3向业务逻辑中添加缓存代码

3.3.1注入常量与对象

3.3.2添加缓存

4.运行测试


1.为什么要使用缓存?

在 淘淘商城46-商品详情页面代码编写 中,我们根据商品id从数据库中查询tb_item表与tb_itemDesc表,其实我们会发现,商品的信息与商品描述,基本上十天半个月都不会发生改变,所以我们可以考虑使用redis缓存一些不经常更换但是访问量很大的数据。

2.缓存数据库中表的分析

2.1分析

当我们准备使用redis缓存表中的数据时,会发现一些难题。

1.我们是否要缓存所有商品数据

由于商品量大而且访问频繁,所有我们肯定不会存储所有商品数据,我们要设置热点商品缓存,对于冷门的商品,我们不进行缓存。如何区分热门的商品与冷门的商品?我们可以对缓存的商品设置超时时间,如果一个商品长时间没有被用户访问,就会超时,从redis缓存中删除。

2.选择redis哪种数据结构来缓存商品数据

3.如何缓存一张表中的数据

下面是tb_item表、tb_itemDesc表的结构:

由于我们要根据商品id,来获取tb_item表与tb_itemDesc表的某一个字段。在redis中,最能模拟数据库中两张以上的不同表的类型就是hash类型。

hash类型:使用key:表名、filed:主键id、value:整个字段的数据

比如我们要缓存商品id为536563:

key:tb_item、filed:536563、value:整个字段的值

key:tb_itemDesc、filed:536563、value:整个字段的值

但是我们要设置超时时间,在redis中hash类型并不能设置超时时间,所以我们并不能使用hash类型来缓存商品数据。

对于list、set、sortset在这里并不合适,我们只能使用String类型。

String类型是key:value的形式,如果以id作为key,tb_item与tb_itemDesc放入缓存时会发生冲突,所以需要构造一个key。

构造一个key的思路:可以加前缀方法对redis中的key进行归类。

比如要缓存id:123456的商品信息:

key:ITEM_INFO:123456:BASE

要缓存id:123456的商品描述:

key:ITEM_INFO:123456:DESC

这里的ITEM_INFO只是一个用于分类的前缀(或者说是表名),可以任意修改。12346是商品id。BASE与DESC是用于区分是商品信息还是商品描述的后缀。中间的冒号用来分割的。

2.2总结

使用redis中的String类型来缓存tb_item与tb_itmeDesc表中的字段信息,

构造"ITEM_INFO:123456:BASE"与"ITEM_INFO:123456:DESC"这样的key,通过前缀来模拟redis中的表。商品id标识不同商品,后缀BASE与DESC区分是商品信息还是商品描述。

3.后端代码实现

3.1引入redis客户端

redis客户端的代码与applicationContext-redis.xml配置在 淘淘商城28-使用spring管理通用连接redis的接口 中

同时需要在taotao-manager-service的pom.xml中加入依赖

<!-- Redis客户端 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
		</dependency>

3.2配置常量配置文件

由于商品缓存入redis需要一个前缀与过期时间,所以我们将这种常量存放在properties文件中。

在src/main/resources的resources下新建一个resource.properties

#redis缓存时分类的前缀
ITEM_INFO_KEY=ITEM_INFO
#缓存商品超时时间
ITEM_INFO_KEY_EXPIRE=86400

需要在spring的配置文件中配置加载properties文件

<context:property-placeholder location="classpath:resource/*.properties" />

3.3向业务逻辑中添加缓存代码

在ItemServiceImpl中添加缓存

添加思路:根据构造的key从缓存中查询是否有商品信息或者商品描述对应的值,如果有直接返回,并重新设置过期时间,如果没有则从数据库中查询,并添加到缓存中,同时添加过期时间,然后返回。

3.3.1注入常量与对象

将商品缓存的前缀、过期时间 、redis客户端对象依赖注入

/** 商品缓存的前缀与过期时间 */
@Value("${ITEM_INFO_KEY}")
private String ITEM_INFO_KEY;
@Value("${ITEM_INFO_KEY_EXPIRE}")
private Integer ITEM_INFO_KEY_EXPIRE;
/** redis单机连接 */
@Autowired
private JedisClient client;

3.3.2添加缓存

在ItemServiceImpl的getItemById与getItemDescById方法中添加缓存

具体可以看我代码上的注释:

/**
	 * 根据商品id获取商品详细信息
	 */
	@Override
	public TbItem getItemById(Long itemId) {
		// 1.封装成redis中的key
		String key = ITEM_INFO_KEY + ":"  + itemId + "" + ":BASE";
		// 2.根据key从缓存中查询是否存在该商品信息,如果存在,直接返回。
		try {
			String tbItemJson = client.get(key);
			if (StringUtils.isNotBlank(tbItemJson)) {
				// 2.1设置过期时间
				System.out.println("缓存中有商品信息,直接返回...");
				client.expire(key, ITEM_INFO_KEY_EXPIRE);
				return JsonUtils.jsonToPojo(tbItemJson, TbItem.class);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 3.否则,将商品信息放入缓存,并设置过期时间
		TbItem tbItem = itemMapper.selectByPrimaryKey(itemId);
		try {
			if (tbItem != null) {
				System.out.println("缓存中没有商品信息,设置缓存...");
				client.set(key, JsonUtils.objectToJson(tbItem));
				client.expire(key, ITEM_INFO_KEY_EXPIRE);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tbItem;
	}

/**
	 * 根据商品id获取商品描述
	 */
	@Override
	public TbItemDesc getItemDescById(Long itemId) {
		// 1.封装成redis中的key
		String key = ITEM_INFO_KEY + ":"  + itemId + "" + ":DESC";
		// 2.根据key从缓存中查询是否存在该商品描述,如果存在,直接返回。
		try {
			String tbItemDescJson = client.get(key);
			if (StringUtils.isNotBlank(tbItemDescJson)) {
				// 2.1设置过期时间
				System.out.println("缓存中有商品描述,直接返回...");
				client.expire(key, ITEM_INFO_KEY_EXPIRE);
				return JsonUtils.jsonToPojo(tbItemDescJson, TbItemDesc.class);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 3.否则,将商品描述放入缓存,并设置过期时间
		TbItemDesc tbItemDesc = itemDescMapper.selectByPrimaryKey(itemId);
		try {
			if (tbItemDesc != null) {
				System.out.println("缓存中没有商品描述,设置缓存...");
				client.set(key, JsonUtils.objectToJson(tbItemDesc));
				client.expire(key, ITEM_INFO_KEY_EXPIRE);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return tbItemDesc;
	}

4.运行测试

在首页http://localhost:8082/ 搜索商品

进入商品搜索页面

点击其中一件商品详情查看

查看eclipse的console,缓存生效,

如果点击没有在缓存中的商品则会

猜你喜欢

转载自blog.csdn.net/pdsu161530247/article/details/82119208