redis 练习与缓存

题目:
模拟一个微博的热搜
表: tb_news id title
Redis: zset

例:
1.创建一个实体类 NewsEntity

package com.lanou3g.redisdemo.entity;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.io.Serializable;

/**
 * 创建人: 武奇
 * 创建事件: 2019/6/26
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "tb_news")
public class NewsEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @Transient
    private Double score;


}

2 创建. NewsRepository 接口继承JpaRepository 接口(继承后可根据方法名自动生成sql语句)
package com.lanou3g.redisdemo.repository;

import com.lanou3g.redisdemo.entity.NewsEntity;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

/**

  • 创建人: 武奇
  • 创建事件: 2019/6/26
    */
    public interface NewsRepository extends JpaRepository<NewsEntity, Long> {

    List findByIdIn(List idList);
    }

3.编写前端导入JQ 向后台发送请求

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <title>新闻列表</title>
</head>
<body>

<div id="news-list"></div>

<script>
    
    $.get("/news/list", function (items) {
        
        const newsList = $("#news-list");
        for (const item of items) {
            //列出从数据库中查出的数据
            const a = $("<a></a>").text(item.title);
            
            //点击查出的数据获取id 去redis中查出谁的点击量最高
            a.click(function () {
                const data = {id: item.id};
                $.post("/news/like", data, function (resp) {
                    console.log("点赞成功")
                })
            });

            //把每条数据放入div中 在放入br标签使每条数据都换行
            newsList.append(a);
            newsList.append($("<br>"))
        }
    })


</script>

</body>
</html>

4.创建controller 层接收前端发送过来的请求

@RestController
@RequestMapping("/news")
public class NewsController {

//    引入NewsService 接口
    @Resource
    private NewsService newsService;


//    查询所有
    @RequestMapping("/list")
    public List<NewsEntity> list() {
        return this.newsService.findAll();
    }

//  增加点击数量 (Id 的添加)
    @RequestMapping("/like")
    public Map<String, Object> like(Long id) {
        this.newsService.likeId(id);
        return Collections.singletonMap("message", "OK");
    }
//  向前端返回集合(id 的返回)
    @RequestMapping("/sort")
    public Collection<?> sort() {
        return this.newsService.getWithScoresId();
    }

创建 newservice 接口 (接口中写了两种添加 到 redis方式)

public interface NewsService {
//    查新所有新闻
    List<NewsEntity> findAll();
//  添加点击数量(对象做法)
    void like(Long id);
//  返回点击数量(对象做法)
    Set<?> getWithScores();
//  添加点击数量(id 做法)
    void likeId(Long id);
//  返回点击数量(id 做法)
    Collection<?> getWithScoresId();

创建 NewsService 接口的实现类

@Service("newsService")
public class NewsServiceImpl implements NewsService {

//    引入NewsRepository接口
    @Resource
    private NewsRepository newsRepository;

//    引入springframework.data.redis.core 包下的 实体类 RedisTemplate
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

//    查出所有
    @Override
    public List<NewsEntity> findAll() {
        return this.newsRepository.findAll();
    }

//    在redis中存入对象
    @Override
    public void like(Long id) {
        ZSetOperations<String, Object> opsZ = this.redisTemplate.opsForZSet();
//        使用id查询所有
        Optional<NewsEntity> optional = this.newsRepository.findById(id);
//        如果optional有值存在
        if (optional.isPresent()) {
//            取出查出NewsEntity 点击增加多少
            NewsEntity news = optional.get();
//            添加到redis 中  1,名字  2,对象  3每次
            opsZ.incrementScore("news:like", news, 1);
        }
    }


//  返回 按照scores排序好的数据
    @Override
    public Set<?> getWithScores() {
        ZSetOperations<String, Object> opsZ = this.redisTemplate.opsForZSet();
//        取出redis 中的按照scores排序好的数据  1,取出数据的名字  2,从0 开始  3,到第10 个结束
        Set<ZSetOperations.TypedTuple<Object>> set = opsZ.reverseRangeWithScores("news:like", 0, 10);
        return set;
    }



//    在redis中存入id
    @Override
    public void likeId(Long id) {
        ZSetOperations<String, Object> opsZ = this.redisTemplate.opsForZSet();
        opsZ.incrementScore("news:like:id", id, 1);
    }



//    从redis中取出 存入的id 与Scores
    @Override
    public Collection<?> getWithScoresId() {
        ZSetOperations<String, Object> opsZ = this.redisTemplate.opsForZSet();
//        取出存入id的集合
        Set<ZSetOperations.TypedTuple<Object>> tuple = opsZ.reverseRangeWithScores("news:like:id", 0, 10);
        // 这个tuple里保存的关键信息是每个新闻的分数和新闻的id的顺序.
        List<NewsEntity> items = new ArrayList<>();
        for (ZSetOperations.TypedTuple<Object> item : tuple) {
            Long id = Long.parseLong(String.valueOf(item.getValue()));
//            使用id查询 查询这条新闻的所有信息
            Optional<NewsEntity> optional = this.newsRepository.findById(id);
//            如果返回的对象不为空
            if (optional.isPresent()) {
                NewsEntity news = optional.get();
//                把分数加入对象
                news.setScore(item.getScore());
//                添加进list
                items.add(news);
            }

        }
        return items;
    }

创建 RedisConfig 配置 存储 redis 时 存入对象的配置

package com.lanou3g.redisdemo.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 创建人: 武奇
 * 创建事件: 2019/6/25
 */
@Configuration
public class RedisConfig {

//    配置key的序列化
    @Bean
    public RedisSerializer keySerializer() {
        return new StringRedisSerializer();
    }
    //    配置value的序列化
    @Bean
    public RedisSerializer valueSerializer() {
        // 当向Redis中存储一个对象时候,
        // 会把对象转换为json数据存储到Redis中
        return new GenericJackson2JsonRedisSerializer();
    }

//
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        // 如果不配置JSON的序列化, 还想保存对象,
        // 那么前提是这个对象是可以被序列化的, 也就是说
        // 对应的类必须是实现Serializable接口的
        // 如果需要使用JSON的序列化, 被保存的对象,
        // 必须得有默认的构造方法, 否则对象能被存上, 但是读不出来
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }



    /*
    <bean id="keySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

    <bean id="redisTemplate" class="com.xxx.RedisTemplate">
        <property key="connectionFactory" ref="redisConnectionFactory"/>
        <property key="keySerializer" ref="keySerializer" />
        <property key="hashKeySerializer" ref="keySerializer" />
    </bean>

  */
}

这样 模拟的微博热搜 就写完了


Redis缓存

需要在 application.yml 里配置(其实可以不配置,只要导包时 有导入redis 包 那么他会自动匹配可以不写)

 #若是已经导入redis框架 可以不写 (下面一段)它默认就是redis
  redis:
    host: localhost
    port: 6379
  #选择缓存器是 谁的缓存(可不写 加入redis框架后默认是redis
  #如不加redis框架也可以用缓存,会默认用simple
  cache:
    type: redis

在SpringBoot 项目开始创建时,自动创建的实体类中写 开始缓存的注解

package com.lanou3g.redisdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
//启用缓存
@EnableCaching
public class RedisDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisDemoApplication.class, args);
    }

}

在cotroller 层 中 做缓存

//  @Cacheable 该方法支持缓存  cacheNames缓存的名字
    @Cacheable(cacheNames = "cache:news")
//    在创建工程最初的被创建的实体类中开启缓存加上 @EnableCaching 注解
    @RequestMapping("/{id}")
    public NewsEntity getOne(@PathVariable Long id) {
        return this.newsService.findById(id);
    }


//    再缓存中真正的key 是由两部分组成的:
//    第一部分是缓存的名字,也cacheNames就是相应的值
//    第二部分是缓存的key, 也就是key的属性

    //在做数据更新的时候需要缓存进行同步
    //    @CacheEvict删掉某个缓存
    @CacheEvict(cacheNames = "cache:news",key = "#news.id")
    @RequestMapping("/update")
    public NewsEntity update(NewsEntity news) {

        return this.newsService.update(news);
    }

//    添加数据
//    @CachePut  直接更新缓存
//    key的参数是 返回值的id
    @CachePut(cacheNames = "cache:news",key = "#result.id")
    @RequestMapping("/save")
    public  NewsEntity save(NewsEntity news){

        return NewsEntity.builder()
                .id(10001L)
                .build();
    }


只要加上注解 redis 就会开始缓存
@Cacheable 该方法支持缓存
@CachePut 直接更新缓存
@CacheEvict删掉某个缓存

缓存相关的注解,不一定非写在controller层
写在service或Dao层都可以
根据实际需求灵活使用

service 层和以前一样 写

转载于:https://www.cnblogs.com/lxx-1843693653/p/11107217.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值