易课寄在线购课系统开发笔记(二十五)–完成课程详情页面展示相关功能(应用Redis缓存)
课程详情页面展示
创建一个课程详情页面展示的工程,是一个表现层工程。
工程搭建
ecourses-item-web。打包方式 war。
可以参考
ecourses-bms-web 工程的搭建过程。
pom 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.ecourses</groupId>
<artifactId>ecourses-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>cn.ecourses</groupId>
<artifactId>ecourses-item-web</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>cn.ecourses</groupId>
<artifactId>ecourses-bms-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
</dependencies>
<!-- 配置tomcat插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>8086</port>
</configuration>
</plugin>
</plugins>
</build>
</project>
功能分析
在搜索结果页面点击课程图片或者课程标题,展示课程详情页面。
请求的 url:/item/{itemId}
参数:课程 id
返回值:String 逻辑视图
业务逻辑:
1、从 url 中取参数,课程 id
2、根据课程 id 查询课程信息 (ecourses_item) 得到一个 EcoursesItem 对象,缺少 images 属性,可以创建一个pojo 继承 EcoursesItem,添加一个 getImages 方法。在 ecourses-item-web 工程中。
package cn.ecourses.item.pojo;
public class Item extends EcoursesItem {
public Item(EcoursesItem ecoursesItem) {
this.setId(ecoursesItem.getId());
this.setTitle(ecoursesItem.getTitle());
this.setSellPoint(ecoursesItem.getSellPoint());
this.setPrice(ecoursesItem.getPrice());
this.setNum(ecoursesItem.getNum());
this.setBarcode(ecoursesItem.getBarcode());
this.setImage(ecoursesItem.getImage());
this.setCid(ecoursesItem.getCid());
this.setStatus(ecoursesItem.getStatus());
this.setCreated(ecoursesItem.getCreated());
this.setUpdated(ecoursesItem.getUpdated());
}
public String[] getImages() {
String image2 = this.getImage();
if (image2 != null && !"".equals(image2)) {
String[] strings = image2.split(",");
return strings;
}
return null;
}
}
3、根据课程 id 查询课程描述。
4、展示到页面。
Dao 层
查询 ecourses_item, ecourses_item_desc 两个表,都是单表查询,可以使用逆向工程。
1.2. Service层
1、根据课程 id 查询课程信息
参数:课程 id
返回值:EcoursesItem
2、根据课程 id 查询课程描述
参数:课程 id
返回值:EcoursesItemDesc
@Override
public EcoursesItemDesc getItemDescById(long itemId) {
//查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_PRE + ":" + itemId + ":DESC");
if(StringUtils.isNotBlank(json)) {
EcoursesItemDesc ecoursesItemDesc = JsonUtils.jsonToPojo(json, EcoursesItemDesc.class);
return ecoursesItemDesc;
}
} catch (Exception e) {
e.printStackTrace();
}
EcoursesItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
//把结果添加到缓存
try {
jedisClient.set(REDIS_ITEM_PRE + ":" + itemId + ":DESC", JsonUtils.objectToJson(itemDesc));
//设置过期时间
jedisClient.expire(REDIS_ITEM_PRE + ":" + itemId + ":DESC", ITEM_CACHE_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return itemDesc;
}
@Override
public EcoursesItem getItemById(long itemId) {
//查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_PRE + ":" + itemId + ":BASE");
if(StringUtils.isNotBlank(json)) {
EcoursesItem ecoursesItem = JsonUtils.jsonToPojo(json, EcoursesItem.class);
return ecoursesItem;
}
} catch (Exception e) {
e.printStackTrace();
}
//缓存中没有,查询数据库
//根据主键查询
//EcoursesItem ecoursesItem = itemMapper.selectByPrimaryKey(itemId);
EcoursesItemExample example = new EcoursesItemExample();
Criteria criteria = example.createCriteria();
//设置查询条件
criteria.andIdEqualTo(itemId);
//执行查询
List<EcoursesItem> list = itemMapper.selectByExample(example);
if (list != null && list.size() > 0) {
//把结果添加到缓存
try {
jedisClient.set(REDIS_ITEM_PRE + ":" + itemId + ":BASE", JsonUtils.objectToJson(list.get(0)));
//设置过期时间
jedisClient.expire(REDIS_ITEM_PRE + ":" + itemId + ":BASE", ITEM_CACHE_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return list.get(0);
}
return null;
}
表现层
Controller
请求的 url:/item/{itemId}
参数:课程 id
返回值:String 逻辑视图
package cn.ecourses.item.controller;
//详情页面展示Controller
@Controller
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping("/item/{itemId}")
public String showItemInfo(@PathVariable Long itemId, Model model) {
//调用服务取基本信息
EcoursesItem ecoursesItem = itemService.getItemById(itemId);
Item item = new Item(ecoursesItem);
//取商品描述信息
EcoursesItemDesc itemDesc = itemService.getItemDescById(itemId);
//把信息传递给页面
model.addAttribute("item", item);
model.addAttribute("itemDesc", itemDesc);
//返回逻辑视图
return "item";
}
}
向业务逻辑中添加缓存
缓存添加分析
使用 Redis 做缓存。
业务逻辑:
1、根据课程 id 到缓存中命中;
2、查到缓存,直接返回;
3、查不到,查询数据库;
4、把数据放到缓存中;
5、返回数据。
缓存中缓存热点数据,提供缓存的使用率。需要设置缓存的有效期。一般是一天的时间,可以根据实际情况调整。
需要使用 String 类型来保存课程数据。
可以加前缀方法对象 Redis 中的 key 进行归类。
ITEM_INFO:123456:BASE
ITEM_INFO:123456:DESC
如果把二维表保存到 Redis 中:
1、表名就是第一层;
2、主键是第二层;
3、字段名第三次;
三层使用 “:” 分隔作为 key,value 就是字段中的内容。
把 Redis 相关的 jar 包添加到工程
<!-- ecourses-common pom.xml -->
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
添加缓存
@Override
public EcoursesItem getItemById(long itemId) {
//查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_PRE + ":" + itemId + ":BASE");
if(StringUtils.isNotBlank(json)) {
EcoursesItem ecoursesItem = JsonUtils.jsonToPojo(json, EcoursesItem.class);
return ecoursesItem;
}
} catch (Exception e) {
e.printStackTrace();
}
//缓存中没有,查询数据库
//根据主键查询
//EcoursesItem ecoursesItem = itemMapper.selectByPrimaryKey(itemId);
EcoursesItemExample example = new EcoursesItemExample();
Criteria criteria = example.createCriteria();
//设置查询条件
criteria.andIdEqualTo(itemId);
//执行查询
List<EcoursesItem> list = itemMapper.selectByExample(example);
if (list != null && list.size() > 0) {
//把结果添加到缓存
try {
jedisClient.set(REDIS_ITEM_PRE + ":" + itemId + ":BASE", JsonUtils.objectToJson(list.get(0)));
//设置过期时间
jedisClient.expire(REDIS_ITEM_PRE + ":" + itemId + ":BASE", ITEM_CACHE_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return list.get(0);
}
return null;
}
取课程描述添加缓存:
@Override
public EcoursesItemDesc getItemDescById(long itemId) {
//查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_PRE + ":" + itemId + ":DESC");
if(StringUtils.isNotBlank(json)) {
EcoursesItemDesc ecoursesItemDesc = JsonUtils.jsonToPojo(json, EcoursesItemDesc.class);
return ecoursesItemDesc;
}
} catch (Exception e) {
e.printStackTrace();
}
EcoursesItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
//把结果添加到缓存
try {
jedisClient.set(REDIS_ITEM_PRE + ":" + itemId + ":DESC", JsonUtils.objectToJson(itemDesc));
//设置过期时间
jedisClient.expire(REDIS_ITEM_PRE + ":" + itemId + ":DESC", ITEM_CACHE_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return itemDesc;
}