(一)RedisTemplate各种数据类型演示(基于Junit)
1.key value类型
@Autowired
private RedisTemplate
/
设置值
ValueTest类
*/
@Test
public void setValue() {
//redis是key-value格式的数据库
//redisTemplate.boundValueOps(“valuetest”).set(“赵云”);
//参数一:指定key 参数二:有效时间 参数三:时间单位:秒、分钟等
//时间过了就会被清掉
redisTemplate.boundValueOps(“valuetest”).set(“关羽”, 30l, TimeUnit.SECONDS);
}
/
基于key获取value值
ValueTest类
/
@Test
public void getValue() {
//指定key获取value
System.out.println(redisTemplate.boundValueOps(“valuetest”).get());
}
/**
基于key删除value
ValueTest类
/
@Test
public void deleteValue() {
//redis是key-value格式的数据库
redisTemplate.delete(“valuetest”);
}
}
2.set集合
@Autowired
private RedisTemplate
/
设置值
SetTest.class
*/
@Test
public void setValue() {
//第一个参数是指定key值
redisTemplate.boundSetOps(“settest”).add(“唐僧”);
redisTemplate.boundSetOps(“settest”).add(“悟空”);
redisTemplate.boundSetOps(“settest”).add(“八戒”);
redisTemplate.boundSetOps(“settest”).add(“悟净”);
}
/
根据key取值,取出的值是无序的,
SetTest.class
/
@Test
public void getValue() {
System.out.println(redisTemplate.boundSetOps(“settest”).members());
}
/**
指定value值删除值
SetTest.class
/
@Test
public void deleteOne() {
redisTemplate.boundSetOps(“settest”).remove(“唐僧”);
}
/
全部删除,指定key删除全部的值
SetTest.class
*/
@Test
public void** deleteValue() {
//redis是key-value格式的数据库
redisTemplate.delete(“settest”);
}
3.list集合
Redis中的List其实就是链表(redis 使用双端链表实现的 List),相信学过数据结构知识的人都应该能理解其结构。
使用 List 结构,我们可以轻松地实现最新消息排行等功能(比如新浪微博的 TimeLine )。List 的另一个应用就是消息队列,可以利用 List 的 PUSH 操作,将任务存在 List 中,然后工作线程再用 POP 操作将任务取出进行执行。
list麻烦点.因为list是有序的,可以选择在当前值的前面插入值,或者是在当前值的后面来插入值
@Autowired
private RedisTemplate
/
在左面加值
ListTest.class
*/
@Test
public void setLeftValue() {
//redis是key-value格式的数据库 金莲 大郎 武松
redisTemplate.boundListOps(“listtest”).leftPush(“武松”);
redisTemplate.boundListOps(“listtest”).leftPush(“大郎”);
redisTemplate.boundListOps(“listtest”).leftPush(“金莲”);
}
/
在右面加值
ListTest.class
/
@Test
public void setRightValue() {
//redis是key-value格式的数据库 金莲 大郎 武松 武松 大郎 金莲
redisTemplate.boundListOps(“listtest”).rightPush(“武松”);
redisTemplate.boundListOps(“listtest”).rightPush(“大郎”);
redisTemplate.boundListOps(“listtest”).rightPush(“金莲”);
}
/**
取值
ListTest.class
/
@Test
public void getValue() {
//.range(0, 10)); 中第0个开始查询,查第十个
System.out.println(redisTemplate.boundListOps(“listtest”).range(0, 10));
}
/
删除指定的元素
ListTest.class
*/
@Test
public void delete() {
//redis是key-value格式的数据库 [金莲, 大郎, 武松, 武松, 大郎, 金莲]
//参数一:删除几个指定元素,这样是删除两个金莲
redisTemplate.boundListOps(“listtest”).remove(2l, “金莲”);
}
@Test
public void** deleteValue() {
//redis是key-value格式的数据库
redisTemplate.delete(“listtest”);
}
4.hash散列类型
/**
- 基于模板类操作redis, 所以需要注入进来
*/
@Autowired
private RedisTemplate
/**
- 添加值
HashTest.class
*/
@Test
public void setValue() {
redisTemplate.boundHashOps(“hashtest”).put(“name1”, “宝玉”);
redisTemplate.boundHashOps(“hashtest”).put(“name2”, “黛玉”);
redisTemplate.boundHashOps(“hashtest”).put(“name3”, “宝钗”);
}
/**
- 各种获取
HashTest.class
*/
@Test
public void getValue() {
//基于key获取value
System.out.println(redisTemplate.boundHashOps(“hashtest”).get(“name1”));
//获取所有的key
System.out.println(redisTemplate.boundHashOps(“hashtest”).keys());
//获取所有的value
System.out.println(redisTemplate.boundHashOps(“hashtest”).values());
}
/**
- 基于小key删除redis数据
HashTest.class
*/
@Test
public void delete() {
//redis是key-value格式的数据库 [金莲, 大郎, 武松, 武松, 大郎, 金莲]
//基于key删除
redisTemplate.boundHashOps(“hashtest”).delete(“name1”);
}
/**
- 基于大Key删除整个redis数据
*/
@Test
public void deleteValue() {
//redis是key-value格式的数据库
redisTemplate.delete(“hashtest”);
5.RedisConnection
/*Spring Boot 提供了RedisConnection 抽象,用于低级别API 操作Redis ,具体实现有JRedis或者Lettuce
*由于Redis 所有数据结构都是二进制的.Spring Boot 对StringRedis Template 做了一定抽象,通过内置的序列化机制将字符串序列化成byte 。Spring Boot 也提供了RedisTemplate
, 默认使用Java 的序列化机制将Redis 数据序列化成byte 。RedisConnection 提供了低级别的API 操作,用byte 数组作为参数操作Red is 服务器。
* 在这个例子中, 也可以直接将RedisConnection 转为StringRedi sConnection:((StringRedisConnection) conn ection ) . set (key, value );
/
@RequestMapping(“/connectionset.html”)
public @ResponseBody String connectionSet (final String key,final String value) throws Exception{
redisClient.execute(new RedisCallback(){
**public **Object doInRedis(RedisConnection connection) **throws **DataAccessException {
**try **{
connection.set(key.getBytes(**"UTF-8"**), value.getBytes(**"UTF-8"**));
} **catch **(UnsupportedEncodingException e) {
**throw new **RuntimeException(e);
}<br /> **return null**;
}<br /> <br /> });<br /> <br /> **return "success"**;
(二)在项目中实现
1.Spring整合SpringDataRedis
思考依赖存放位置问题: 建议依赖放在common工程,因为多个模块可能都会用到缓存,如果只是考虑只用一次缓存,不思考通用问题的话,坐标依赖就放dao层合适
理由:因为缓存也是操作数据的,正常情况下,操作数据都是在dao层来实现.
但是如果是只有这一个功能使用,也可以把依赖放在service层.
2.给首页添加缓存功能
功能其实很简单,先把redis整合在项目之后才能接着开始
1.先加入依赖 依赖参考上面的入门demo演示,完全可以拿过来
2.再加入SpringRedis.xml文件 参考上面入门demo ,然后修改下路径
3.再加入properties文件 参考上面入门demo
4.把RedisTemplate模版注入进你所需要的编写的service层代码里面就开始写业务代码了
思考用map结构是因为: 前台需要通过categoryid来查询获取广告数据, 这样的情况和map结构很类似,
思路,先从缓存里面尝试着查询数据,如果缓存没有再去数据库里面查询,再放入redis里面
@Autowired
private RedisTemplate redisTemplate;
/**
把广告数据放入redis缓存里面
思路:思路,先从缓存里面尝试着查询数据,如果缓存没有再去数据库里面查询,再放入redis里面
*数据类型用hash类型的,可以hash的基于key(广告的类型)来获取value(广告的具体信息)
ContentServiceImpl.class
**@param categoryId
*@return
*
/
@Override
public List
/*
1.从缓存中查询数据,基于广告分类查询广告数据<br /> 指定一个大key : content 基于categoryId来获取值<br /> */<br /> List<TbContent> contentList = (List<TbContent>) **redisTemplate**.boundHashOps(**"content"**).get(categoryId);
//2.没有从缓存中获取数据<br /> **if **(contentList == **null**) {
System.**_out_**.println(**"从数据库中获取广告数据"**);<br />
TbContentExample example = **new **TbContentExample();<br />
Criteria criteria = example.createCriteria();<br /> //基于分类id查询广告<br /> criteria.andCategoryIdEqualTo(categoryId);
criteria.andStatusEqualTo(**"1"**);//有效状态<br /> example.setOrderByClause(**"sort_order"**);
contentList = **contentMapper**.selectByExample(example);<br />
//3.将结果放入缓存<br /> **redisTemplate**.boundHashOps(**"content"**).put(categoryId, contentList);
} else {
System.**_out_**.println(**"从缓存中获取广告数据"**);
}
return contentList;
3.广告数据发生变化怎么更新redis缓存
思路:先清除指定类型的广告数据,在访问存在广告页面,将最新的广告数据重新加入缓存。
细节中
改变广告可能改变广告类型.
开始从广告的增删改查开始下手操作
/
新增操作
清除redis:目的是清理所有的缓存,防止数据错乱,
key就是传过来的值
ContentServiceImpl.class
*@param content
*/
@Override
public void add(TbContent content) {
contentMapper.insert(content);
//清除指定广告分类的缓存数据
redisTemplate.boundHashOps(“content”).delete(content.getCategoryId());
}
/
修改
执行删除之前先把category查询到
修改需要判断一下
ContentServiceImpl.class
*@param content
/
@Override
public void update(TbContent content){
//先查询原来广告分类id
Long categoryId = contentMapper.selectByPrimaryKey(content.getId()).getCategoryId();
//清除原来广告分类数据(上面查询的是原来的数据,防止数据错乱,先全部清理掉)
redisTemplate.boundHashOps(“content”).delete(categoryId);
contentMapper.updateByPrimaryKey(content);
//判断修改前和修改后广告分类是否一致,如果不一致就清理
//longValue是将包装数据类型转换成基本数据类型
if(categoryId.longValue()!=content.getCategoryId().longValue()) {
//清除改变之后的广告分类数据
redisTemplate.boundHashOps(“content”).delete(content.getCategoryId());
}
}
/**
批量删除广告
为什么先删除缓存再清理, 考虑极端的线程问题了
在删除的时候万一别人访问了怎么办,(所以先清理缓存再删除)
ContentServiceImpl.class
**@param ids
*/
@Override
public void delete(Long[] ids) {
for**(Long id:ids){
//先查询广告数据
TbContent content = contentMapper.selectByPrimaryKey(id);
Long categoryId = content.getCategoryId();
//清除原来广告分类数据(上面查询的是原来的数据,防止数据错乱,先全部清理掉)
redisTemplate.boundHashOps(“content”).delete(categoryId);
contentMapper.deleteByPrimaryKey(id);
}
}
4.查询文章,没有就查询缓存
/**
- 根据ID查询实体
先从redis里面获取,如果有的话就直接返回,如果没有就从数据库里面查询,
- 再设置进redis里面,再返回
需要注意,修改和删除都得清理redis缓存,否则会出现数据错乱问题
- 再设置进redis里面,再返回
@param **id
* @return
*/
public **Article findById(String id) {//1.判断缓存中是否有文章
Article article = (Article)redisTemplate.opsForValue().get(“article_”+id);
if(article == null){
System.**_out_**.println(**"去数据库获取的"**);
//2.去数据库查询
article = **articleDao**.findById(id).get();
//3.存入redis(设置过期时间)<br /> **redisTemplate**.opsForValue().set(**"article_"**+id,article,30, TimeUnit.**_SECONDS_**);<br />
}else{
//只是用于演示
System.**_out_**.println(**"从缓存获取的"**);
}
return article;
}
/**
- 修改
- @param **article
*
/
public void update(Article article) {
articleDao.save(article);
//清除缓存
redisTemplate.delete(“article_”+article.getId());
}
/**
- 删除
- @param **id
*
/
public void deleteById(String id) {
articleDao.deleteById(id);
//清除缓存
redisTemplate.delete(“article_”+id);
}