把jedis依赖的jar包添加到工程中。Maven工程中需要把jedis的坐标添加到依赖。
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
推荐添加到服务层。*-content-service工程中
测试
连接单机版
第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
第三步:打印结果。
第四步:关闭Jedis
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class JedisTest {
@Test
public void testJedis() throws Exception {
// 创建一个连接Jedis对象, 指定服务的ip及端口 参数:host, port
Jedis jedis = new Jedis("192.168.25.3", 6379);
// 直接使用jedis操作redis, 每个redis命令都对应一个方法
jedis.set("test1", "my first jedis test");
String result = jedis.get("test1");
System.out.println(result);
// 关闭连接
jedis.close();
}
}
连接单机版使用连接池
第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。
第二步:从JedisPool中获得Jedis对象。
第三步:使用Jedis操作redis服务器。
第四步:操作完毕后关闭jedis对象,连接池回收资源。
第五步:关闭JedisPool对象。
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisTest {
@Test
public void testJedisPool() throws Exception {
// 创建连接池对象, 两个参数host, port
JedisPool jedisPool = new JedisPool("192.168.25.3", 6379);
// 从连接池获得一个连接, 就是一个jedis对象
Jedis jedis = jedisPool.getResource();
// 使用jedis操作redis
String result = jedis.get("test1");
System.out.println(result);
// 每次使用完毕后关闭连接,连接池回收资源
jedis.close();
// 关闭连接池.
jedisPool.close();
}
}
连接集群版
第一步:使用JedisCluster对象。需要一个Set参数。Redis节点的列表。
第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。
第三步:打印结果
第四步:系统关闭前,关闭JedisCluster对象。
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class JedisTest {
@Test
public void testJedisCluster() throws Exception {
// 创建一个JedisCluster对象, 有一个参数nodes,是一个set类型 set中包含若干个HostAndPort
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.25.3", 7001));
nodes.add(new HostAndPort("192.168.25.3", 7002));
nodes.add(new HostAndPort("192.168.25.3", 7003));
nodes.add(new HostAndPort("192.168.25.3", 7004));
nodes.add(new HostAndPort("192.168.25.3", 7005));
nodes.add(new HostAndPort("192.168.25.3", 7006));
JedisCluster jedisCluster = new JedisCluster(nodes);
// 直接使用JedisCluster对象操作redis
jedisCluster.set("test", "123");
String result = jedisCluster.get("test");
System.out.println(result);
// 系统关闭之前, 关闭JedisCluster对象
jedisCluster.close();
}
}
然后我们可以把单机版和集群版各自封装一个实现类, 两个实现类共用一个接口; 我们面向接口开发, 将来要换的时候, 只用切换实现类, 代码不用改动
jedis的一个接口和两个实现类下载页面
redis应用比较广泛, 可能多个项目都需要用, 所以我们放到common中
报错是因为没加依赖, 在common中把jar包依赖过来
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.0</version>
</dependency>
然后把单机版和集群版配置到spring容器中, 配置一个bean, 用的时候把bean注入到工程里面直接用就好了
<?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="jedisPoll"></property>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.25.3"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
</bean>
<!-- 连接redis集群 -->
<!-- <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
<property name="jedisCluster" ref="jedisCluster"></property>
</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.3"></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.3"></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.3"></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.3"></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.3"></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.3"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
</bean> -->
</beans>
在spring中配置了两个bean, 使用哪个就把哪个bean的注释打开
用测试方法试一下, 单机版集群版都可以运行
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 s = jedisClient.get("mytest");
System.out.println(s);
}
}
添加缓存
在表现层添加缓存, 只有这个表现层能用, 其他的表现层调用这个服务, 还得添加缓存. 如果在服务层添加缓存, 只要调用这个服务, 就能添加缓存
功能分析
查询内容列表时添加缓存。
1、查询数据库之前先查询缓存。
2、查询到缓存,直接响应结果。
3、查询不到缓存,需要查询数据库。
4、把查询结果添加到缓存中。
5、返回结果。
package cn.e3mall.content.service.impl;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import cn.e3mall.common.jedis.JedisClient;
import cn.e3mall.common.util.E3Result;
import cn.e3mall.common.util.JsonUtils;
import cn.e3mall.content.service.ContentService;
import cn.e3mall.mapper.TbContentMapper;
import cn.e3mall.pojo.TbContent;
import cn.e3mall.pojo.TbContentExample;
import cn.e3mall.pojo.TbContentExample.Criteria;
/**
* 内容管理service
*
* @author 11501
*
*/
@Service
public class ContentServiceImpl implements ContentService {
@Autowired
private TbContentMapper contentMapper;
@Autowired
private JedisClient jedisClient;
@Value("${CONTENT_LIST}")
private String CONTENT_LIST;
/**
* 根据内容分类id查询内容列表
*/
@Override
public List<TbContent> getContentListByCid(long cid) {
// 查询缓存
try {
// 如果缓存中有直接相应结果
String json = jedisClient.hget(CONTENT_LIST, cid + "");
if (StringUtils.isNoneBlank(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 {
jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
CONTENT_LIST可以提取到属性文件中, 内容如下
如果你有多个配置文件, 记得加载所有配置文件
缓存同步
在数据库中添加一条数据, 缓存中没有更新, 是旧的数据, 应该把对应的缓存的列表对应的key删掉, 查询的时候缓存中没有数据, 就会从数据库查询添加到缓存中, 就把最新的数据添加到缓存中了, 相当于缓存同步了
添加内容的时候做缓存同步
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import cn.e3mall.common.jedis.JedisClient;
import cn.e3mall.common.util.E3Result;
import cn.e3mall.common.util.JsonUtils;
import cn.e3mall.content.service.ContentService;
import cn.e3mall.mapper.TbContentMapper;
import cn.e3mall.pojo.TbContent;
import cn.e3mall.pojo.TbContentExample;
import cn.e3mall.pojo.TbContentExample.Criteria;
/**
* 内容管理service
*/
@Service
public class ContentServiceImpl implements ContentService {
@Autowired
private TbContentMapper contentMapper;
@Autowired
private JedisClient jedisClient;
@Value("${CONTENT_LIST}")
private String CONTENT_LIST;
@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();
}
}