day72_淘淘商城项目_05_匠心笔记

文章目录 1、首页轮播图的展示 1.1、功能分析 1.2、Dao层 1.3、Service层 1.4、表现层 1.5、测试 2、首页大广告展示流程图 3、Redis的安装及使用 3.1、redis的下载 3.2、redis的安装 3.3、连接redis 3.4、redis五种数据类型 3.5、key 命令 3.6、redis持久化方案 4、Redis集群的搭建 4.1、redis-cluster架构图 4.2、redis集群的搭建 4.3、集群的使用方法 5、Java客户端Jedis的使用方法 5.1、通过单实例连接redis服务器单机版 5.2、通过连接池连接redis服务器单机版 5.3、使用spring整合JedisPool连接redis服务器单机版 5.4、使用JedisCluster类连接redis集群版 5.5、使用spring整合JedisCluster连接redis服务器集群版 6、向业务逻辑中添加缓存 6.1、接口封装 6.2、封装代码测试 6.3、向业务逻辑中添加缓存 6.4、缓存同步 课程计划: 第五天 1、首页轮播图的展示 2、首页大广告展示流程图 3、Redis的安装及使用 4、Redis集群的搭建 5、向业务逻辑中添加缓存 6、Jedis的使用(redis的客户端) 7、缓存同步 8、Solr服务器安装 回到顶部 1、首页轮播图的展示 taotao-portal-web工程中,动态展示内容信息。 前端团队:负责JS,html等开发。 后端团队:负责后台的开发并提供数据给前端。 1.1、功能分析 只需要动态生成一个json数据,轮播图就可以动态展示。 taotao-portal-web工程下的index.jsp中: Json数据格式: [ { "srcB": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg", "height": 240, "alt": "", "width": 670, "src": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg", "widthB": 550, "href": "http://sale.jd.com/act/e0FMkuDhJz35CNt.html?cpdad=1DLSUE", "heightB": 240 }, { "srcB": "http://image.taotao.com/images/2015/03/03/2015030304353109508500.jpg", "height": 240, "alt": "", "width": 670, "src": "http://image.taotao.com/images/2015/03/03/2015030304353109508500.jpg", "widthB": 550, "href": "http://sale.jd.com/act/UMJaAPD2VIXkZn.html?cpdad=1DLSUE", "heightB": 240 }, ...... ] 分析:   taotao-portal-web 需要自己自定义的POJO的类型数据的列表。   taotao-content 是服务层公用的,可以被其他的系统(表现层的系统)来调用。   为了通用性:taotao-content 服务层中获取tb_content的内容列表 即:list   taotao-portal-web 表现层需要拿到tb_content的列表,然后进行转换成自定义的类型的数据列表即可。   从tb_content表中取数据,根据(叶子节点)内容分类id查询列表(内容列表)。   内容分类id固定,需要配置在属性文件中。   图片的width、height配置在属性文件中。   alt属性从字段sub_title中获取。   src --> pic   srcB --> pic2   href --> url URL:/index 参数:无。 返回值:首页页面(数据是JSON,设置在Model中) 业务逻辑:   1、根据分类的id 查询内容列表(List)   2、服务层发布服务。   3、表现层引入服务。   4、调用服务,转换成自定义的数据类型(Ad1Node)的列表。   5、将数据列表设置到Model中,返回给页面。 需要创建一个pojo转换成页面需要的json数据格式。放入taotao-portal-web工程的com.taotao.portal.pojo中。 AD1Node.java /** * 前台大广告位需要的pojo数据类型 * @author chenmingjun * @date 2018年11月18日下午4:03:34 * @version 1.0 */ public class AD1Node implements Serializable { private static final long serialVersionUID = 1L; private String srcB; private Integer height; private String alt; private Integer width; private String src; private Integer widthB; private String href; private Integer heightB; public String getSrcB() { return srcB; } public void setSrcB(String srcB) { this.srcB = srcB; } public Integer getHeight() { return height; } public void setHeight(Integer height) { this.height = height; } public String getAlt() { return alt; } public void setAlt(String alt) { this.alt = alt; } public Integer getWidth() { return width; } public void setWidth(Integer width) { this.width = width; } public String getSrc() { return src; } public void setSrc(String src) { this.src = src; } public Integer getWidthB() { return widthB; } public void setWidthB(Integer widthB) { this.widthB = widthB; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public Integer getHeightB() { return heightB; } public void setHeightB(Integer heightB) { this.heightB = heightB; } @Override public String toString() { return "AD1Node [srcB=" + srcB + ", height=" + height + ", alt=" + alt + ", width=" + width + ", src=" + src + ", widthB=" + widthB + ", href=" + href + ", heightB=" + heightB + "]"; } } 1.2、Dao层 从tb_content表中取出数据,根据内容分类id查询内容列表。可以使用逆向工程生成的Mapper。 1.3、Service层 参数:Long categoryId 返回值:List @Override public List getContentListByCategoryId(Long categoryId) { TbContentExample contentExample = new TbContentExample(); Criteria criteria = contentExample.createCriteria(); criteria.andCategoryIdEqualTo(categoryId); List list = contentMapper.selectByExample(contentExample); return list; } 1.3.1、发布服务 在taotao-content-service工程applicationContext-service.xml中发布服务 1.4、表现层 在taotao-portal-web中实现,查询首页轮播图的内容。 1.4.1、引用服务 先在taotao-protal-web项目中引入对taotao-content-interface的依赖,如图: 在taotao-content-web工程springmvc.xml中引入服务 1.4.2、Controller 在首页展示之前,对数据进行处理,然后展示首页,需要在IndexController中实现。 /** * 前台首页展示Controller * @author chenmingjun * @date 2018年11月14日下午11:22:22 * @version 1.0 */ @Controller public class IndexController { @Autowired private ContentService contentService; @Value("${AD1_CATEGORY_ID}") private Long AD1_CATEGORY_ID; @Value("${AD1_HEIGHT}") private Integer AD1_HEIGHT; @Value("${AD1_HEIGHT_B}") private Integer AD1_HEIGHT_B; @Value("${AD1_WIDTH}") private Integer AD1_WIDTH; @Value("${AD1_WIDTH_B}") private Integer AD1_WIDTH_B; /** * 展示前台首页,并展示首页轮播图 * @return */ @RequestMapping("/index") public String showIndex(Model model) { // 1、引入服务 // 2、注入服务 // 3、调用方法查询TbContent的列表 List contentList = contentService.getContentListByCategoryId(AD1_CATEGORY_ID); // 4、把TbContent的列表转换为AD1Node列表 List aD1NodeList = new ArrayList<>(); for (TbContent tbContent : contentList) { AD1Node aD1Node = new AD1Node(); aD1Node.setAlt(tbContent.getSubTitle()); aD1Node.setHref(tbContent.getUrl()); aD1Node.setSrc(tbContent.getPic()); aD1Node.setSrcB(tbContent.getPic2()); aD1Node.setHeight(AD1_HEIGHT); aD1Node.setHeightB(AD1_HEIGHT_B); aD1Node.setWidth(AD1_WIDTH); aD1Node.setWidthB(AD1_WIDTH_B); aD1NodeList.add(aD1Node); } // 5、把AD1Node列表转换为JSON数据 String json = JsonUtils.objectToJson(aD1NodeList); // 6、把JSON数据设置到request域中去(Model) model.addAttribute("ad1", json); return "index"; } } 属性文件所在位置: 在taotao-portal-web中的springmvc.xml中还需要配置: 1.5、测试 后台数据如下图所示: 前台浏览器显示界面: 其他广告位同理。 回到顶部 2、首页大广告展示流程图   首页是系统的门户,也就是系统的入口。所以首页的访问量是这个系统最大的。如果每次展示首页都从数据库中查询首页的内容信息,那么势必会对数据库造成很大的压力,所以需要使用缓存来减轻数据库压力。   实现缓存的工具有很多,现在比较流行的是redis。   首页大广告展示流程:   展示流程:先从缓存取,如果不存在,从数据库取出来,写入缓存,再返回页面;如果存在key,直接从缓存中取出来,展示到页面。   同步缓存:当事务提交(更新,删除,插入)后,需要同步缓存,直接根据Key删除redis的key(清空缓存),再展示时 由上边的流程展示。 回到顶部 3、Redis的安装及使用 3.1、redis的下载   官网地址:http://redis.io/   下载地址:http://download.redis.io/releases/redis-3.0.0.tar.gz 3.2、redis的安装   安装redis需要c语言的编译环境,如果没有gcc需要在线安装。如下命令: [root@itheima ~]# yum -y install gcc-c++   检测是否有gcc环境,只需输入命令: [root@itheima ~]# gcc [root@itheima ~]# gcc gcc: 致命错误:没有输入文件 编译中断。 [root@itheima ~]# 出现如上所述内容,表示gcc安装成功。 安装步骤:   第一步:将redis的源码包上传到linux系统。   第二步:解压缩redis的源码包。   第三步:进行编译。cd到解压后的目录,输入命令:make   第四步:进行安装。输入命令:make install PREFIX=/usr/local/redis   第五步:检查目录是否存在。在/usr/local/redis下有bin目录,则说明安装成功。 3.3、连接redis 3.3.1、redis的启动 前端启动:在redis的安装目录下直接启动redis-server [root@itheima ~]# ./redis-server 后台启动: 把/root/redis-3.0.0/redis.conf复制到/usr/local/redis/bin目录下 [root@itheima redis-3.0.0]# cp redis.conf /usr/local/redis/bin/ 修改配置文件:将daemonize由no改为yes 再次启动redis: [root@itheima bin]# ./redis-server redis.conf 查看redis进程: [root@itheima bin]# ps aux | grep redis root 5845 0.4 0.2 140888 2104 ? Ssl 22:51 0:00 ./redis-server *:6379 root 5858 0.0 0.0 112720 980 pts/1 R+ 22:51 0:00 grep --color=auto redis [root@itheima bin]# 前端启动,不能更换终端,影响下一步操作。而后台启动,只在进程中悄悄启动。推荐使用后台启动。 3.3.2、客户端redis-cli连接redis 使用redis-cli建立连接: [root@itheima bin]# ./redis-cli 127.0.0.1:6379> ping PONG 127.0.0.1:6379> 默认连接localhost运行在6379端口的redis服务。 连接其他ip和端口: [root@itheima bin]# ./redis-cli -h 192.168.25.153 -p 6379 192.168.25.153:6379> ping PONG 192.168.25.153:6379>   -h:连接的服务器的地址   -p:服务的端口号 3.3.3、使用redis的桌面程序连接redis 先安装:redis-desktop-manager-0.7.9.809.exe 安装好后,双击打开软件 redis默认有16个库,如果不指定库,默认存储在索引为0的库中。 退出连接: 第一种方式: [root@itheima bin]# ./redis-cli 127.0.0.1:6379> quit [root@itheima bin]# 第二种方式: [root@itheima bin]# ./redis-cli 127.0.0.1:6379> exit [root@itheima bin]# 第三种方式: Ctrl+C 3.3.4、关闭redis服务 第一种:通过连接上客户端进行关闭,使用shutdown 命令。 [root@itheima bin]# ./redis-cli 127.0.0.1:6379> shutdown not connected> 第二种:使用 kill 命令。 找到对应的redis的进程id 然后使用命令:(pid为进程id) [root@itheima bin]# kill -9 pid 3.4、redis五种数据类型 3.4.1、String:key-value redis命令不区分大小写,但是key区分大小写的。 redis中所有的数据都是字符串。 redis是单线程的,所以不适合存储比较大的数据,最好要存小且能快速处理完的东西。 使用incr命令,如果key不存在,会自动创建key并自动+1。   set key value   设置值   get key   获取值   incr key   加一   decr key   减一 127.0.0.1:6379> set key1 2 OK 127.0.0.1:6379> set key2 value2 OK 127.0.0.1:6379> get key1 "2" 127.0.0.1:6379> get key2 "value2" 127.0.0.1:6379> Get key2 "value2" 127.0.0.1:6379> incr key1 (integer) 3 127.0.0.1:6379> decr key1 (integer) 2 127.0.0.1:6379> 3.4.2、Hash: key-field-value 相当于一个key对应一个map (map中又是key-value),一般应用于归类。   hset key field value   hget key field   hincrby key field num 127.0.0.1:6379> hset hkey1 filed1 value1 (integer) 1 127.0.0.1:6379> hset hkey1 filed2 2 (integer) 1 127.0.0.1:6379> hget hkey1 filed1 "value1" 127.0.0.1:6379> hget hkey1 filed2 "2" 127.0.0.1:6379> hincrby hkey1 filed2 1 (integer) 3 127.0.0.1:6379> hincrby hkey1 filed2 -1 (integer) 2 127.0.0.1:6379> 3.4.3、List List是有顺序可重复(数据结构中的:双链表,队列)。 可作为链表,可以从左添加元素,也可以从右添加元素。   lpush list a b c d   (从左添加元素)   rpush list 1 2 3 4   (从右边添加元素)   lrange list 0 -1   (从 0 到 -1 元素查看:也就表示查看所有)   lpop list   (从左边取,删除)   rpop list   (从右边取,删除) 127.0.0.1:6379> lpush list1 a b c d (integer) 4 127.0.0.1:6379> lrange list1 0 -1 1) "d" 2) "c" 3) "b" 4) "a" 127.0.0.1:6379> rpush list1 1 2 3 4 (integer) 8 127.0.0.1:6379> lrange list1 0 -1 1) "d" 2) "c" 3) "b" 4) "a" 5) "1" 6) "2" 7) "3" 8) "4" 127.0.0.1:6379> lpop list1 "d" 127.0.0.1:6379> lrange list1 0 -1 1) "c" 2) "b" 3) "a" 4) "1" 5) "2" 6) "3" 7) "4" 127.0.0.1:6379> rpop list1 "4" 127.0.0.1:6379> lrange list1 0 -1 1) "c" 2) "b" 3) "a" 4) "1" 5) "2" 6) "3" 127.0.0.1:6379> 3.4.4、Set Set无顺序,不能重复。   sadd set1 a b c d d   (向set1中添加元素)元素不重复   smembers set1   (查询元素)   srem set1 a   (删除元素) 127.0.0.1:6379> sadd set1 a a a b b c (integer) 3 127.0.0.1:6379> smembers set1 1) "c" 2) "b" 3) "a" 127.0.0.1:6379> srem set1 a (integer) 1 127.0.0.1:6379> smembers set1 1) "c" 2) "b" 127.0.0.1:6379> 3.4.5、SortedSet(zset) SortedSet有顺序,不能重复。 适合做排行榜 排序需要一个分数属性。   zadd zset1 8 a 4 b 5 c 1 d   (添加元素:zadd key score member)   zrange key start stop [WITHSCORES]   (查看所有元素:zrange key 0 -1 withscores)     如果要查看分数,需要加上withscores   zrange zset1 0 -1   (从小到大)   zrevrange zset1 0 -1   (从大到小)   zincrby zset1 score member   (对元素 member 增加 score) 127.0.0.1:6379> zadd zset1 8 a 4 b 5 c 1 d (integer) 4 127.0.0.1:6379> zrange zset1 0 -1 1) "d" 2) "b" 3) "c" 4) "a" 127.0.0.1:6379> zadd zset1 9 a (integer) 0 127.0.0.1:6379> zrange zset1 0 -1 1) "d" 2) "b" 3) "c" 4) "a" 127.0.0.1:6379> zrange zset1 0 -1 withscores 1) "d" 2) "1" 3) "b" 4) "4" 5) "c" 6) "5" 7) "a" 8) "9" 127.0.0.1:6379> zrevrange zset1 0 -1 1) "a" 2) "c" 3) "b" 4) "d" 127.0.0.1:6379> zrevrange zset1 0 -1 withscores 1) "a" 2) "9" 3) "c" 4) "5" 5) "b" 6) "4" 7) "d" 8) "1" 127.0.0.1:6379> 3.5、key 命令 expire key second 设置key的过期时间 ttl key 查看剩余时间(-2 表示不存在,-1 表示已被持久化(永不过期),正数表示剩余的时间) persist key 清除过期时间,也即持久化,持久化成功体提示 1,不成功提示 0 del key 删除key exists key 若key存在,返回1,否则返回0。 select 0 表示选择0号数据库。默认是0号数据库。 redis 默认有16个库 select num 从0开始换库 keys * 获取redis里面所有的key dbsize 查看当前数据库的key的数量 flushdb 清空当前库的所有key flushall 清空所有库的key exists key 是否存在该key move key db 把当前库的key移到db号库中 type key 查看key的类型 3.6、redis持久化方案 redis 数据都放在内存中。如果机器挂掉,内存的数据就不存在。 需要做持久化处理,将内存中的数据保存在磁盘,下一次启动的时候就可以恢复数据到内存中。   方案1:RDB 快照形式(定期将当前时刻的数据保存磁盘中)会产生一个dump.rdb文件。     特点:会存在数据丢失,性能较好,数据备份。   方案2:AOF:append only file (所有对redis的操作命令记录在aof文件中),恢复数据,重新执行一遍即可。     特点:每秒保存(也可能会存在数据丢失),数据比较完整,耗费性能。其实也可以设置成每次保存,但是此就失去了缓存的意义了。 redis默认开启RDB。如下图: redis.conf 中默认设置了保存规则及时间间隔。 save 开头的一行就是持久化配置,可以配置多个条件(每行配置一个条件),每个条件之间是“或”的关系。 save 900 1 表示15分钟(900秒)内至少1个键被更改则进行快照。 save 300 10 表示5分钟(300秒)内至少10个键被更改则进行快照。 save 60 10000 表示1分钟(60秒)内至少10000个键被更改则进行快照。 AOF开启设置,修改 redis.conf 文件,如下图: 将appendonly设置为yes即可。 同时开启两个持久化方案,则按照AOF的持久化放案恢复数据。 默认是按照RDB的方式恢复数据,如果开启了AOF,就是用AOF恢复数据,数据是存在于/usr/local/redis/bin/appendonly.aof文件中。 回到顶部 4、Redis集群的搭建 4.1、redis-cluster架构图 架构细节详解如下: 架构细节: (1) 所有的 redis 节点彼此互联(`PING-PONG机制`),内部使用`二进制协议`优化传输速度和带宽。 (2) 节点的 fail(失败) 是通过集群中`超过半数的节点检测失效`时才生效。即`集群搭建中主机的个数为奇数`。 (3) 客户端与 redis 节点直连,不需要中间 proxy层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。 (4) redis-cluster 把所有的物理节点映射到 [0-16383]slot(槽) 上,cluster 负责维护 node<-->slot<-->value Redis 集群中内置了 `16384 个哈希槽`,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果`对 16384 求余数`,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量`大致均等`的将哈
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信