壹立方商城-Day06

首页轮播图动态展示

效果展示

动态从数据库中获取广告内容

壹立方商城-Day06

前端分析

在e3-portal-web的index.jsp中,有一个首页读取广告信息的json格式的例子,所以前端只需要获得这样的json即可加载广告。

壹立方商城-Day06

后端代码实现

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
}
]

分析:在e3-content-service获取 tbcontent的内容列表 即:list<TbContent>,在e3-portal-web封装这样的json,封装这样的json就需要一个pojo从list<TbContent>中获取信息,并转为前端需要的json格式。

服务层

从tb_content表中取数据,根据(叶子节点)内容分类id查询列表(内容列表)。

dao层

使用****

service层

在e3-content-interface创建接口,接收categoryId返回List<TbContent>

ContentService.java

           /**
	 * 根据categoryId查询内容列表
	 * @param cid
	 * @return
	 */
	List<TbContent> getContentListByCid(long cid);

在e3-content-service实现接口

ContentServiceImpl.java

        /**
	 * 根据内容分类categoryId查询内容列表---内容列表显示
	 * @param cid
	 * @return
	 */
	@Override
	public List<TbContent> getContentListByCid(long cid) {
		TbContentExample example = new TbContentExample();
		Criteria criteria = example.createCriteria();
		//设置查询条件
		criteria.andCategoryIdEqualTo(cid);
		//执行查询
		List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);
		return list;
	}

表现层

在e3-portal-web工程中的pom.xml文件中添加manager-interface依赖

<dependency>
	<groupId>cn.e3mall</groupId>
	<artifactId>e3-content-interface</artifactId>
	<version>0.0.1-SNAPSHOT</version>
</dependency>

在e3-portal-web工程中的springmvc.xml文件中引入服务

<dubbo:reference interface="cn.e3mall.content.service.ContentService" id="contentService" />

配置resource.properties配置文件

#轮播图内容的分类
CONTENT_LUNBO_ID=89

在springmvc.xml文件中加载配置文件

注意,配置多个配置文件,加载以后只生效一个

<!-- 加载配置文件 -->
 <context:property-placeholder location="classpath:conf/resource.properties"/>

修改e3-portal-web工程下的index.jsp

删除静态的轮播图标签

壹立方商城-Day06

添加遍历的jstl标签

壹立方商城-Day06

小圆点地方做修改

壹立方商城-Day06

e3-portal-web工程下的IndexController.java

package cn.e3mall.portal.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.e3mall.content.service.ContentService;
import cn.e3mall.pojo.TbContent;

/**
 * 首页展示Controller
 * <p>Title: IndexController</p>
 * @version 1.0
 */
@Controller
public class IndexController {
	
	@Value("${CONTENT_LUNBO_ID}")
	private Long CONTENT_LUNBO_ID;
	
	@Autowired
	private ContentService contentService;

	@RequestMapping("/index")
	public String showIndex(Model model) {
		//查询内容列表
		List<TbContent> ad1List = contentService.getContentListByCid(CONTENT_LUNBO_ID);
		// 把结果传递给页面
		model.addAttribute("ad1List", ad1List);
		return "index";
	}
}

启动工程

启动e3-manager、e3-content、e3-portal-web

查看页面结果

壹立方商城-Day06

 

linux安装redis以及连接redis

redis的下载

官网地址:http://redis.io/

下载地址:http://download.redis.io/releases/redis-3.0.0.tar.gz

2.redis的安装

安装redis需要c语言的编译环境,如果没有gcc需要在线安装

yum -y install gcc-c++

测试是否有gcc环境

gcc: no input files  表示安装成功

[[email protected] ~]# gcc
gcc: no input files

安装步骤:

第一步:将redis的源码包上传到linux系统。选用e3-manager-dubbo-register-Redis服务器

用SecureCRT上传

清除之前安装的Redis

壹立方商城-Day06

第二步:解压缩redis的源码包。

tar -xvf redis-3.0.0.tar.gz


第三步:进行编译。 cd到解压后的目录 输入命令:make   

cd /redis-3.0.0

执行:make命令

make


第四步:进行安装。 输入命令:

make install PREFIX=/usr/local/redis


PREFIX 必须是大写的。

cd /usr/local/redis


有bin目录说明安装成功 
壹立方商城-Day06

3.连接redis

3.1redis服务端启动

第一种:前端启动模式

bin的目录

cd /usr/local/redis/

在bin目录下执行

./redis-server 

这种方法启动后,这个终端就不能用了,只能新开一个终端了。

壹立方商城-Day06

第二种:后台启动模式

第一步:将redis.conf配置文件复制到redis/bin下

redis.conf是配置文件

cp /su/redis-3.0.0/redis.conf /usr/local/redis/bin/


第二步:使用vim编辑redis.conf文件

 将daemonize no修改为daemonize yes

壹立方商城-Day06

第三步:启动redis

./redis-server redis.conf

第四步:检查redis进程

ps -ef|grep redis
或者
ps aux|grep redis

壹立方商城-Day06

3.2客户端redis-cli连接redis


在redis/bin下,默认连接127.0.0.1:6379的本地redis服务

./redis-cli

健康检查

出现PONG表示正常

壹立方商城-Day06
redi 也可以指定连接ip:端口

-h:连接的服务器的地址

-p:服务的端口号

./redis-cli -h 192.168.25.153 -p 6379

3.3关闭redis服务


第一种:通过客户端关闭

在redis/bin下

./redis-cli shutdown


第二种:使用kill命令

找到对应的redis的进程id 然后使用命令:(pid为进程id)

kill -9 pid

Redis的数据类型操作

Redis的持久化方案

Redis集群原理

redis-cluster架构图

壹立方商城-Day06

redis-cluster投票:容错

壹立方商城-Day06

架构细节:

(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 会根据节点数量大致均等的将哈希槽映射到不同的节点
壹立方商城-Day06

将key均匀的放在这些服务器上,让这些服务器都干活

 

Redis集群的搭建

 

环境搭建

制作6个redis实例

每个实例运行在不同的端口。需要修改redis.conf配置文件。配置文件中还需要把cluster-enabled yes前的注释去掉。

Redis集群中至少应该有三个节点。要保证集群的高可用,需要每个节点有一个备份机。

Redis集群至少需要6台服务器。搭建伪分布式。

搭建伪分布式。可以使用一台虚拟机运行6个redis实例。需要修改redis的端口号7001-7006

进入redis目录

[[email protected] redis]# cd /usr/local/redis/

在上一级目录下创建一个目录

[[email protected] redis]# mkdir ../redis-cluster

此时在local目录下就有一个redis-cluster目录

壹立方商城-Day06

复制redis/bin 目录到redis-cluster/redis01目录下

[[email protected] local]# cp redis/bin/ redis-cluster/redis01 -r

进入redis01目录下

壹立方商城-Day06

因为创建集群需要的是一个干净的redis目录,所以要删除这个目录下的appendonly.aof 和 dump.rdb文件,这两个文件时两种持久化方式创建的数据文件,一般情况下只有dump.rdb文件

执行命令删除文件:

[[email protected] redis01]# rm -f dump.rdb 
[[email protected] redis01]# rm -f appendonly.aof

修改配置文件redis.conf

vim redis.conf

壹立方商城-Day06

修改上面的端口号     

壹立方商城-Day06将这里的注释打开

壹立方商城-Day06复制五个redis得到留个redis

壹立方商城-Day06                                                                            修改每个redis的配置文件redis.conf的端口号7002 7003 7004 7005 7006

[[email protected] redis-cluster]# vim redis06/redis.conf 

进去以后如果找不到端口号,就输入/port进行查找

启动每个redis实例

可以一个个的启动,也可以写一个批处理将所有的redis服务启动

vim start-all.sh

   壹立方商城-Day06         

上面的批处理是执行在redis-cluster文件里的,下面的这个批处理更通用                                                          

cd /usr/local/redis-cluster/redis01/bin
./redis-server redis.conf
 
cd /usr/local/redis-cluster/redis02/bin
./redis-server redis.conf
 
cd /usr/local/redis-cluster/redis03/bin
./redis-server redis.conf
 
cd /usr/local/redis-cluster/redis04/bin
./redis-server redis.conf
 
cd /usr/local/redis-cluster/redis05/bin
./redis-server redis.conf
 
cd /usr/local/redis-cluster/redis06/bin
./redis-server redis.conf

授权执行文件权限

chmod u+x start-all.sh

壹立方商城-Day06                                                                                       启动redis服务

在redis-cluster目录下

./start-all.sh

查看服务是否启动

ps aux|grep redis

壹立方商城-Day06                                                                

关闭集群

创建关闭集群的脚本

首先使用:vim 命令创建一个文件 redis-cluster-stop-all.sh

vim redis-cluster-stop-all.sh 

内容如下

 
cd /usr/local/redis-cluster/redis01/bin
./redis-cli -p 7001 shutdown
 
cd /usr/local/redis-cluster/redis02/bin
./redis-cli -p 7002 shutdown
 
cd /usr/local/redis-cluster/redis03/bin
./redis-cli -p 7003 shutdown
 
cd /usr/local/redis-cluster/redis04/bin
./redis-cli -p 7004 shutdown
 
cd /usr/local/redis-cluster/redis05/bin
./redis-cli -p 7005 shutdown
 
cd /usr/local/redis-cluster/redis06/bin
./redis-cli -p 7006 shutdown

给权限

chmod u+x redis-cluster-stop-all.sh

 

进入[[email protected] src]# cd /su/redis-3.0.0/src目录下

找到.rb结尾的文件redis-trip.rb

壹立方商城-Day06                                                                  将这个脚本文件复制到 /usr/local/redis-cluster/目录下

[[email protected] src]# cp redis-trib.rb /usr/local/redis-cluster/

或者
[[email protected] redis-cluster]# cp /su/redis-3.0.0/src/*.rb /usr/local/redis-cluster/redis-trib.rb

壹立方商城-Day06                                                   

至此,redis实例制作完成!!!

rubby运行环境搭建

使用ruby脚本搭建集群。需要ruby的运行环境。

1、安装ruby

yum install ruby 环境安装

yum install rubygems  包管理器安装

2、安装ruby脚本运行使用的包。

上传redis-3.0.0.gem

壹立方商城-Day06

进入redis-3.0.0.gem文件所在的目录su

cd /su/

执行指令

gem install redis-3.0.0.gem

壹立方商城-Day06

此时redis-trib.rb脚本就可以运行了

使用ruby脚本搭建集群。

执行./redis-trib.sh

./redis-trib.rb create --replicas 1 192.168.25.129:7001 192.168.25.129:7002 192.168.25.129:7003 192.168.25.129:7004 192.168.25.129:7005 192.168.25.129:7006

分配方案确定

壹立方商城-Day06

输入yes后开始搭建

壹立方商城-Day06

集群搭建成功!!!

 

集群的使用方法

连接集群

Redis-cli连接集群,任意连接其中一台就可操作整个集群。

[[email protected] redis-cluster]# redis01/redis-cli -p 7004 -c

-c:代表连接的是redis集群

壹立方商城-Day06

重定向到15495槽,192,168,25,129服务器的7003端口,然后把key放进去

壹立方商城-Day06

使用java的jedis连接单机redis及redis集群

添加缓存

添加jedis依赖

添加到e3-content-service工程中的pom.xml文件中

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

连接单机redis

第一步:创建一个Jedis对象。需要指定服务端的ip及端口。

第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。

第三步:打印结果。

第四步:关闭Jedis

在e3-content-service工程中的test中新建一个测试

JedisTest.java

package cn.e3mall.jedis;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

public class JedisTest {

	@Test
	public void testJedis() throws Exception {
		//创建一个连接Jedis对象,参数:host、port
		Jedis jedis = new Jedis("192.168.25.129", 6379);
		//直接使用jedis操作redis。所有jedis的命令都对应一个方法。
		jedis.set("test123", "my first jedis test");
		String string = jedis.get("test123");
		System.out.println(string);
		//关闭连接
		jedis.close();
	}
}

运行测试得到

壹立方商城-Day06

使用连接池连接单机redis

第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。

第二步:从JedisPool中获得Jedis对象。

第三步:使用Jedis操作redis服务器。

第四步:操作完毕后关闭jedis对象,连接池回收资源。

第五步:关闭JedisPool对象。

//使用连接池连接单击redis
	@Test
	public void testJedisPool() throws Exception {
		//创建一个连接池对象,两个参数host、port
		JedisPool jedisPool = new JedisPool("192.168.25.129", 6379);
		//从连接池获得一个连接,就是一个jedis对象。
		Jedis jedis = jedisPool.getResource();
		//使用jedis操作redis
		String string = jedis.get("test123");
		System.out.println(string);
		//关闭连接,每次使用完毕后关闭连接。连接池回收资源。
		jedis.close();
		//关闭连接池。
		jedisPool.close();
	}

连接集群redis

第一步:使用JedisCluster对象。需要一个Set<HostAndPort>参数。Redis节点的列表。

第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。

第三步:打印结果

第四步:系统关闭前,关闭JedisCluster对象。单例的

@Test
	public void testJedisCluster() throws Exception {
		//创建一个JedisCluster对象。有一个参数nodes是一个set类型。set中包含若干个HostAndPort对象。
		Set<HostAndPort> nodes = new HashSet<>();
		nodes.add(new HostAndPort("192.168.25.129", 7001));
		nodes.add(new HostAndPort("192.168.25.129", 7002));
		nodes.add(new HostAndPort("192.168.25.129", 7003));
		nodes.add(new HostAndPort("192.168.25.129", 7004));
		nodes.add(new HostAndPort("192.168.25.129", 7005));
		nodes.add(new HostAndPort("192.168.25.129", 7006));
		JedisCluster jedisCluster = new JedisCluster(nodes);
		//直接使用JedisCluster对象操作redis。
		jedisCluster.set("test", "123");
		String string = jedisCluster.get("test");
		System.out.println(string);
		//关闭JedisCluster对象
		jedisCluster.close();
	}

使用spring管理通用连接redis的接口

将jedis的接口和实现类放到e3-common工程中的cn.e3mall.common.jedis包内

壹立方商城-Day06

 文件错误的原因是因为缺少JedisCluster和JedisPool的依赖

在e3-common工程中的pom.xml中添加JedisCluster和JedisPool的依赖

将e3-content-service工程中的pom.xml中的redis依赖剪切到e3-common工程中的pom.xml中

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

此时所有工程中都会有这个依赖

接口定义

JedisClient.java

package cn.e3mall.common.jedis;

import java.util.List;

public interface JedisClient {
	// Redis SET命令用于在Redis键中设置一些字符串值
	String set(String key, String value);

	// 根据key去查询相应的值
	String get(String key);

	// 判断key在Redis缓存中是否存在
	Boolean exists(String key);

	// 设置key的过期时间
	Long expire(String key, int seconds);

	// Redis TTL 命令以秒为单位返回 key 的剩余过期时间
	Long ttl(String key);

	// Redis Incr 命令将 key 中储存的数字值增一
	Long incr(String key);

	/**
	 * Redis Hset 命令用于为哈希表中的字段赋值 。 如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。
	 * 如果字段已经存在于哈希表中,旧值将被覆盖。
	 * 
	 * @param key
	 * @param field
	 * @param value
	 * @return
	 */
	Long hset(String key, String field, String value);

	// Redis Hget 命令用于返回哈希表中指定字段的值
	String hget(String key, String field);

	// Redis Hdel 命令用于删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。
	Long hdel(String key, String... field);

	// 查询所有的hash类型的列表
	Boolean hexists(String key, String field);

	List<String> hvals(String key);

	Long del(String key);
}

连接单机redis实现类

封装常用的redis命令

JedisClientPool.java

package cn.e3mall.common.jedis;

import java.util.List;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class JedisClientPool implements JedisClient {

	private JedisPool jedisPool;

	public JedisPool getJedisPool() {
		return jedisPool;
	}

	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

	@Override
	public String set(String key, String value) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.set(key, value);
		jedis.close();
		return result;
	}

	@Override
	public String get(String key) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.get(key);
		jedis.close();
		return result;
	}

	@Override
	public Boolean exists(String key) {
		Jedis jedis = jedisPool.getResource();
		Boolean result = jedis.exists(key);
		jedis.close();
		return result;
	}

	@Override
	public Long expire(String key, int seconds) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.expire(key, seconds);
		jedis.close();
		return result;
	}

	@Override
	public Long ttl(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.ttl(key);
		jedis.close();
		return result;
	}

	@Override
	public Long incr(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.incr(key);
		jedis.close();
		return result;
	}

	@Override
	public Long hset(String key, String field, String value) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hset(key, field, value);
		jedis.close();
		return result;
	}

	@Override
	public String hget(String key, String field) {
		Jedis jedis = jedisPool.getResource();
		String result = jedis.hget(key, field);
		jedis.close();
		return result;
	}

	@Override
	public Long hdel(String key, String... field) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.hdel(key, field);
		jedis.close();
		return result;
	}

	@Override
	public Boolean hexists(String key, String field) {
		Jedis jedis = jedisPool.getResource();
		Boolean result = jedis.hexists(key, field);
		jedis.close();
		return result;
	}

	@Override
	public List<String> hvals(String key) {
		Jedis jedis = jedisPool.getResource();
		List<String> result = jedis.hvals(key);
		jedis.close();
		return result;
	}

	@Override
	public Long del(String key) {
		Jedis jedis = jedisPool.getResource();
		Long result = jedis.del(key);
		jedis.close();
		return result;
	}

}

连接集群redis实现类

JedisClientCluster.java

package cn.e3mall.common.jedis;

import java.util.List;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {
	
	private JedisCluster jedisCluster;
	

	public JedisCluster getJedisCluster() {
		return jedisCluster;
	}

	public void setJedisCluster(JedisCluster jedisCluster) {
		this.jedisCluster = jedisCluster;
	}

	@Override
	public String set(String key, String value) {
		return jedisCluster.set(key, value);
	}

	@Override
	public String get(String key) {
		return jedisCluster.get(key);
	}

	@Override
	public Boolean exists(String key) {
		return jedisCluster.exists(key);
	}

	@Override
	public Long expire(String key, int seconds) {
		return jedisCluster.expire(key, seconds);
	}

	@Override
	public Long ttl(String key) {
		return jedisCluster.ttl(key);
	}

	@Override
	public Long incr(String key) {
		return jedisCluster.incr(key);
	}

	@Override
	public Long hset(String key, String field, String value) {
		return jedisCluster.hset(key, field, value);
	}

	@Override
	public String hget(String key, String field) {
		return jedisCluster.hget(key, field);
	}

	@Override
	public Long hdel(String key, String... field) {
		return jedisCluster.hdel(key, field);
	}

	@Override
	public Boolean hexists(String key, String field) {
		return jedisCluster.hexists(key, field);
	}

	@Override
	public List<String> hvals(String key) {
		return jedisCluster.hvals(key);
	}

	@Override
	public Long del(String key) {
		return jedisCluster.del(key);
	}

}

spring配置

将单机版集群版配置,配置到spring容器中

在e3-content-service中创建spring/applicationContext-redis.xml

在单机版的配置中,我们使用构造方法创建JedisPool对象,参数为host和port。JedisPool对象要注入到JedisClientPool的依赖中,然后创建JedisClientPool对象

在集群版的配置中,使用构造方法创建jedisCluster对象,参数为set<HostAndPort>。使用构造方法创建HostAndPort对象时,需要参数host和post。最后创建JedisClientCluster对象,并将jedisCluster注入依赖。

applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
	
	<!-- 连接redis单机版 -->
	<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">
		<property name="jedisPool" ref="jedisPool"></property>
	</bean>
	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
		<constructor-arg name="host" value="192.168.25.129"/>
		<constructor-arg name="port" value="6379"/>
	</bean>
	<!-- 连接redis集群 -->
	<!-- <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
		<property name="jedisCluster" ref="jedisCluster"/>
	</bean>
	<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
		<constructor-arg name="nodes">
			<set>
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7001"></constructor-arg>
				</bean> 
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7002"></constructor-arg>
				</bean> 
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7003"></constructor-arg>
				</bean> 
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7004"></constructor-arg>
				</bean> 
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7005"></constructor-arg>
				</bean> 
				<bean class="redis.clients.jedis.HostAndPort">
					<constructor-arg name="host" value="192.168.25.129"></constructor-arg>
					<constructor-arg name="port" value="7006"></constructor-arg>
				</bean> 
			</set>
		</constructor-arg>
	</bean> -->
</beans>

测试访问

单机redis配置测试

我们注释掉集群redis配置,并在applicationContext-redis.xml里面加上<context:annotation-config/>,编写测试类。

可以成功访问redis

在e3-content-service工程的test里写一个测试代码

JedisClientTest.java

package cn.e3mall.jedis;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.e3mall.common.jedis.JedisClient;

public class JedisClientTest {

	@Test
	public void testJedisClient() throws Exception {
		// 初始化spring容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				"classpath:spring/applicationContext-redis.xml");
		// 从容器中获得JedisClient对象
		JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
		jedisClient.set("mytest", "jedisClient");
		String string = jedisClient.get("mytest");
		System.out.println(string);

	}
}

集群redis配置测试

集群测试的时候不需要改java代码,只需要把applicationContext-redis.xml中集群的配置文件打开,把单机的配置文件注释即可

所以单机版和集群版的切换只需要更改一下配置文件就可以了

注意:单机版和集群版不能共存,使用单机版时注释集群版的配置。使用集群版,把单机版注释。

 

向业务逻辑中添加缓存

为什么要添加缓存?我们在加载首页大广告时,由于大广告在数据库中的内容,并不是每时每刻都在变化,所以我们每次都从数据库中获取会很消耗资源,所以我们使用redis做缓存。

用户访问首页时:每次先从缓存中获取,如果缓存中没有广告的内容,就从数据库中获取,并将获取的广告内容放入缓存中,以便下次从缓存中获取,减少访问数据库的次数。

管理人员在商城后台做内容修改、增加、删除时:由于管理人员是修改数据库中的内容,并不能修改缓存中的内容,用户很有可能每次访问看到的都是没有更改前的广告内容,所以管理人员是修改数据库中的内容时,删除缓存中的内容即可。然后又回到用户访问首页时

HASH_KEY:HASH

            |--KEY:VALUE

            |--KEY:VALUE

            |--KEY:VALUE

            |--KEY:VALUE

缓存加的位置

加缓存主要是为了减小数据库的压力,如果缓存加在表现层,那么就跟服务层和数据库都没有关系了,如果加在服务层,那么就与数据库无关

所以缓存的添加位置在服务层和表现层加都可以,但是如果加在表现层,那么只能是这个表现层用的到,其他的表现层就用不到了

service层添加缓存

在e3-content-service的ContentServiceImpl中添加缓存

首先我们防止redis中的String类型(或者list、set)的key:cid=89太过简单,使用hash类型(ps:hash类型,通过key找到feild,通过feild找到value)

我们自定义一个key叫做TBCONTENT_KEY,feild使用cid,value就是转换为json后的List<TbContent>。(你也可以直接使用String、list、set类型,key使用categoryId,value=转换为json后的List<TbContent>)

将key放入配置文件中

新建一个resource/resource.properties,专门存放key。

壹立方商城-Day06

内容如下

#内容列表在redis中缓存的key
CONTENT_LIST=CONTENT_LIST

加载properties文件

在e3-content-service工程中的applicationContext-dao.xml文件中配置

壹立方商城-Day06

配置文件的加载,如果加载多个,只认一个,我们的配置文件加载在dao层加载,所以将文件名用*代替,表示加载所有properties文件

<!-- 加载属性文件 -->
<context:property-placeholder location="classpath:conf/*.properties" />

注入key和jedisClient对象

壹立方商城-Day06

@Autowired
private JedisClient jedisClient;
//从缓存中获取大广告的key
@Value("${CONTENT_KEY}")
private String CONTENT_KEY;

编写添加缓存代码

每次先从缓存中获取,如果缓存中没有广告的内容,就从数据库中获取,并将获取的广告内容放入缓存中,以便下次从缓存中获取

中间可以加上System.out.println("xxxx");方便查看效果

壹立方商城-Day06

e3-content-service工程中的ContentServiceImpl.java

/**
	 * 根据内容分类categoryId查询内容列表---内容列表显示
	 * 
	 * @param cid
	 * @return
	 */
	@Override
	public List<TbContent> getContentListByCid(long cid) {
		// 查询缓存
		try {
			// 如果缓存中有直接响应结果
			String json = jedisClient.hget(CONTENT_LIST, cid + "");
			if (StringUtils.isNotBlank(json)) {
				List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
				return list;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 如果没有查询数据库
		TbContentExample example = new TbContentExample();
		Criteria criteria = example.createCriteria();
		// 设置查询条件
		criteria.andCategoryIdEqualTo(cid);
		// 执行查询
		List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);
		// 把结果添加到缓存
		try {
			// 这里类似于 hset hash1 field1 2 对应下面的
			// hset CONTENT_LIST cid JsonUtils.objectToJson(list)
			// 这个方法JsonUtils.objectToJson(list)就是将list转换成字符串,因为hashset中存的是字符串
			jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

启动

启动zookpeer

进入zookpeer目录

[[email protected] bin]# cd /su/zookeeper-3.4.6/bin/

启动zookpeer

[[email protected] bin]# ./zkServer.sh start

maven install e3-common 启动e3-content  e3-manager e3-portal-web

 

第一次访问网站的时候,所有的数据都来自数据库

第二次访问的时候,就会从redis缓存中取出数据,这样就可以减少每一次访问都查询数据库,对数据库的压力

缓存同步

逻辑解析

首先在后台内容管理里面添加内容--例如大广告本来有四个,再添加一个

壹立方商城-Day06

添加过后,按照理论来说,前台页面的大广告位值会有五张图片

壹立方商城-Day06

可以看到,前台大广告位还是只有四张图片

这是因为前台的数据在第二次访问的时候都是从redis缓存中取出的,后台改了数据,但是前台取数据的时候不是从后台取出的,所以大广告位依然只有四张图

这时就要用到缓存同步技术让后台中的数据同步到redis缓存中

缓存同步实现

实现原理,在后台做增删改操作的时候都要在增删改操作中实现缓存同步---删除缓存中同步的相应的数据

相应的数据:缓存中会存在很多缓存,例如大广告,小广告等,我们要做的是删除我们修改数据的缓存(就是hash1中的field1,2,3.。。),其他缓存保持不变

实现缓存同步的位值

壹立方商城-Day06

	/**
	 * 内容管理----添加
	 */
	@Override
	public E3Result addContent(TbContent content) {
		//将内容数据插入到内容表
		content.setCreated(new Date());
		content.setUpdated(new Date());
		//插入到数据库
		contentMapper.insert(content);
		//缓存同步,删除缓存中对应的数据。
		jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
		return E3Result.ok();
	}

 

 

 

 

 

 

参考文章

原文https://blog.****.net/pdsu161530247/article/details/81901507#t0

原文https://blog.****.net/pdsu161530247/article/details/81902341

原文:https://blog.****.net/pdsu161530247/article/details/81903944