微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”七、redis数据库缓存页面数据、使用NUXT框架搭建前台系统环境、前台系统页面、首页轮播图(banner数据显示)、首页热门课程,名师推荐

文章目录

一、NUXT前台环境搭建

NUXT?
服务端渲染技术
就是将页面先在服务端渲染完成,然后再显示页面
为什么这么做?
我们以前全部使用异步请求的形式渲染页面,这样的页面初始是没有数据的
而搜索引擎(百度等)是根据关键字个数检索,给网站排序
而异步初始没有太多数据,关键字自然就很少,SEO(排名)就很低
试问,你百度的时候看过多少次第2页
而NUXT会先渲染然后一次性返回所有数据,关键字匹配度自然就高,排名就更高

1、如何学习NUXT

百度NUXT进入中文网

在这里插入图片描述

2、下载安装使用NUXT入门模板starter-template

GitHub网址:http://www.github.com/nuxt-community/starter-template
进不去就直接百度starter-template

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、机制

NUXT网站的特性
布局页面先将位置布局好,然后通过nuxt标签引入需要的页面内容
一般的NUXT网站都是具有两个页面(“这里不是指数量”,一个页面掌管页面布局,而另一个页面写内容(可以当成是多个不同的组件))
写内容的页面渲染完成后,会放置到布局页面的指定位置
如何指定位置,布局页面中有nuxt标签,帮助其找位置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、编写静态页面

1、设置布局(首尾固定,中间用nuxt引用组件)

代码和资源到我的GitHub里面拿

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、首页轮播图

1、安装swiper插件

swiper?
swiper是一个提供网页特效的一个组件,而我们使用的这个是vue二次封装的
相比起来配置难度相仿,使用起来更简单
使用步骤
1、安装依赖:npm install vue-awesome-swiper --save

在这里插入图片描述

2、在vue中引入:main.js或者plugins中配置(后面会有详细配置说明)
	import VueAwesomeSwiper from 'vue-awesome-swiper'
	import 'swiper/css/swiper.css'
	Vue.use(VueAwesomeSwiper)

|3、vue页面中使用|

<template>
<!-- 幻灯片 开始 -->
    <div v-swiper:mySwiper="swiperOption">
        <div class="swiper-wrapper">
            <div class="swiper-slide" style="background: #040B1B;">
                <a target="_blank" href="/">
                    <img src="~/assets/photo/banner/1525939573202.jpg" alt="首页banner">
                </a>
            </div>
            <div class="swiper-slide" style="background: #F3260B;">
                <a target="_blank" href="/">
                    <img src="~/assets/photo/banner/153525d0ef15459596.jpg" alt="首页banner">
                </a>
            </div>
        </div>
        <div class="swiper-pagination swiper-pagination-white"></div>
        <div class="swiper-button-prev swiper-button-white" slot="button-prev"></div>
        <div class="swiper-button-next swiper-button-white" slot="button-next"></div>
    </div>
    <!-- 幻灯片 结束 -->
</template>

<script>
export default {
  data () {
    return {
      swiperOption: {
        //配置分页
        pagination: {
          el: '.swiper-pagination'//分页的dom节点
        },
        //配置导航
        navigation: {
          nextEl: '.swiper-button-next',//下一页dom节点
          prevEl: '.swiper-button-prev'//前一页dom节点
        },
        //自动轮播
        autoplay: {
          delay: 2000,
          //当用户滑动图片后继续自动轮播
          disableOnInteraction: false,
        },
        //开启循环模式
        loop: true
      }
    }
  },

}
</script>

2、配置插件(我们使用的NUXT的模板项目,配置稍微有些不一样,但原理相同)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、实现轮播(代码都在上面)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

3、课程和名师页面

这里涉及了nuxt路由切换
nuxt路由分静态路由和动态路由
静态路由指,此路由永远指向固定地址,固定页面
动态路由指,此路由指向地址不固定,可以动态渲染

1、整合课程页面

在这里插入图片描述

2、整合讲师页面

在这里插入图片描述

3、编写课程和讲师静态页面(GitHub有)

在这里插入图片描述

4、编写动态路由

在这里插入图片描述
在这里插入图片描述

三、首页banner轮播图(后端)

1、创建子模块

在这里插入图片描述

2、application.yml

server:
  port: 8004 #微服务端口

spring:
  application:
    name: service-cms #服务名
  profiles:
    active: dev #环境设置 dev表示构建阶段,test表示测试阶段,prod表示发布阶段
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/gulischool?serverTimeZone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: 123456
  jackson: #我们的时区是东八区,应该加8个小时,时区显示格式也需要改成我们想要的
    date-format: yyyy-MM-DD HH:mm:ss
    time-zone: GMT+8 #GMT%2B8
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #nacos

mybatis-plus:
  mapper-locations: classpath:com/yzpnb/cmsservice/mapper/xml/*.xml #配置mapper xml文件的路径
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis日志



3、创建数据库表

# Host: localhost  (Version 5.7.19)
# Date: 2019-11-18 15:49:41
# Generator: MySQL-Front 6.1  (Build 1.26)


#
# Structure for table "crm_banner"
#

CREATE TABLE `crm_banner` (
  `id` char(19) NOT NULL DEFAULT '' COMMENT 'ID',
  `title` varchar(20) DEFAULT '' COMMENT '标题',
  `image_url` varchar(500) NOT NULL DEFAULT '' COMMENT '图片地址',
  `link_url` varchar(500) DEFAULT '' COMMENT '链接地址',
  `sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
  `is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='首页banner表';

#
# Data for table "crm_banner"
#

INSERT INTO `crm_banner` VALUES ('1194556896025845762','test1','https://online-teach-file.oss-cn-beijing.aliyuncs.com/cms/2019/11/14/297acd3b-b592-4cfb-a446-a28310369675.jpg','/course',1,0,'2019-11-13 18:05:32','2019-11-18 10:28:22'),('1194607458461216769','test2','https://online-teach-file.oss-cn-beijing.aliyuncs.com/cms/2019/11/13/8f80790d-d736-4842-a6a4-4dcb0d684d4e.jpg','/teacher',2,0,'2019-11-13 21:26:27','2019-11-14 09:12:15');

在这里插入图片描述

4、搭建关于轮播表的环境(不使用代码生成器)

在这里插入图片描述

1、创建实体

package com.yzpnb.cmsservice.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.util.Date;

@Data
@EqualsAndHashCode(callSuper = false)//生成equals和hashCode方法,callSuper = false 表示不调用父类的方法,避免错误
@Accessors(chain = true)//配置set方法具有返回值,返回值为当前对象CrmBanner
@ApiModel(value="CrmBanner对象", description="轮播图对象")
public class CrmBanner {
    
    @ApiModelProperty(value="id")
    @TableId(value = "id",type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty("标题")
    private String title;

    @ApiModelProperty("图片地址")
    private String imageUrl;

    @ApiModelProperty("链接地址")
    private String linkUrl;

    @ApiModelProperty("排序")
    private Integer sort;

    @ApiModelProperty(value = "逻辑删除 1(true)已删除, 0(false)未删除")
    private Integer isDeleted;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;
}

2、创建controller


package com.yzpnb.cmsservice.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController//以Rest风格注入前端控制器
@RequestMapping(value="/cmsservice/crm-banner/after-end/")//请求映射
@CrossOrigin
public class CrmBannerController {

}

3、创建mapper

package com.yzpnb.cmsservice.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yzpnb.cmsservice.entity.CrmBanner;
import org.mapstruct.Mapper;

@Mapper
public interface CrmBannerMapper extends BaseMapper<CrmBanner> {//继承通用mapper,简单的单表查询就不用自己写了
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yzpnb.cmsservice.mapper.CrmBannerMapper">

</mapper>

4、service

package com.yzpnb.cmsservice.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.yzpnb.cmsservice.entity.CrmBanner;

public interface CrmBannerService extends IService<CrmBanner> {//继承通用service,简单接口不用我们自己写了
}

package com.yzpnb.cmsservice.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzpnb.cmsservice.entity.CrmBanner;
import com.yzpnb.cmsservice.mapper.CrmBannerMapper;
import com.yzpnb.cmsservice.service.CrmBannerService;
import org.springframework.stereotype.Service;

@Service
public class CrmBannerServiceImpl  extends ServiceImpl<CrmBannerMapper, CrmBanner>  implements CrmBannerService {
    //继承通用接口实现类,通用接口实现类不用我们自己写了


}

5、创建启动类

package com.yzpnb.cmsservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages={"com.yzpnb"})//这样它会将所有com.yzpnb包下内容扫描,而不只是扫描子文件或同级文件
@MapperScan(value = "com.yzpnb.cmsservice.mapper")//自动扫描mapper指定mapper映射的扫描位置
@EnableDiscoveryClient //nacos注册
public class CrmBannerApplication {
    public static void main(String[] args) {
        SpringApplication.run(CrmBannerApplication.class);
    }
}

综上所述
没什么技术含量的,重复性高,而且很麻烦的,还是直接用代码生成器
代码生成器教程

5、编写后端接口CRUD(后台管理系统)

package com.yzpnb.cmsservice.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yzpnb.cmsservice.entity.CrmBanner;
import com.yzpnb.cmsservice.service.CrmBannerService;
import com.yzpnb.common_utils.Result;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController//以Rest风格注入前端控制器
@RequestMapping(value="/cmsservice/crm-banner/after-end/")//请求映射
@CrossOrigin
public class CrmBannerController {

    @Autowired
    private CrmBannerService crmBannerService;

    /**
     * 查询
     */

    @ApiOperation(value = "根据id获取Banner")
    @GetMapping("selectById/{id}")
    public Result selectById(@ApiParam(name = "id",value = "BannerID")
                            @PathVariable String id) {
        CrmBanner banner = crmBannerService.getById(id);
        return Result.ok().data("banner", banner);
    }

    @ApiOperation(value = "获取Banner分页列表")
    @GetMapping("limit/{page}/{limit}")
    public Result index(@ApiParam(name = "page", value = "当前页码", required = true)
                       @PathVariable Long page,
                        @ApiParam(name = "limit", value = "每页记录数", required = true)
                       @PathVariable Long limit) {
        Page<CrmBanner> pageParam = new Page<>(page, limit);
        crmBannerService.page(pageParam);
        return Result.ok().data("banners", pageParam.getRecords());
    }

    /**
     * 修改
     */
    @ApiOperation(value = "根据id修改Banner")
    @PutMapping("updateById")
    public Result updateById(@RequestBody CrmBanner banner) {
        crmBannerService.updateById(banner);
        return Result.ok();
    }

    /**
     * 添加
     */
    @ApiOperation(value = "新增Banner")
    @PostMapping("insert")
    public Result insert(@RequestBody CrmBanner banner) {
        crmBannerService.save(banner);
        return Result.ok();
    }

    /**
     * 删除
     */
    @ApiOperation(value = "根据id删除Banner")
    @DeleteMapping("deleteById/{id}")
    public Result deleteById(@PathVariable String id) {
        crmBannerService.removeById(id);
        return Result.ok();
    }
}

6、编写后端接口展示Banner(客户端前台系统)

package com.yzpnb.cmsservice.controller.api;

import com.yzpnb.cmsservice.entity.CrmBanner;
import com.yzpnb.cmsservice.service.CrmBannerService;
import com.yzpnb.common_utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;

@RestController
@RequestMapping("/cmsservice/crm-banner/api/")
@Api("网站首页Banner列表")
@CrossOrigin //跨域
public class CrmBannerApiController {
    
    @Autowired
    private CrmBannerService crmBannerService;
    
    @ApiOperation(value = "获取首页所有banner")
    @GetMapping("selectAllBanner")
    public Result selectAllBanner() {
        List<CrmBanner> list = crmBannerService.list();
        return Result.ok().data("bannerList", list);
    }
    
}

在这里插入图片描述

7、编写后端接口展示最新加入的名师和最新添加的课程

在这里插入图片描述

和课程和讲师有关,需要到service-edu微服务中添加接口
package com.yzpnb.eduservice.controller.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yzpnb.common_utils.Result;
import com.yzpnb.eduservice.entity.EduCourse;
import com.yzpnb.eduservice.entity.EduTeacher;
import com.yzpnb.eduservice.service.EduCourseService;
import com.yzpnb.eduservice.service.EduTeacherService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;

@RestController
@RequestMapping("/eduservice/api/")
@CrossOrigin
public class ApiController {
    @Autowired
    private EduCourseService courseService;
    @Autowired
    private EduTeacherService teacherService;
    
    
    @ApiOperation("获取最新添加的8门课程和4名教师")
    @GetMapping("selectNewRecommended")
    public Result selectNewRecommended() {
        //查询前8条热门课程
        QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        wrapper.last("limit 8");
        List<EduCourse> courseList = courseService.list(wrapper);
        
        //查询前4条名师
        QueryWrapper<EduTeacher> wrapperTeacher = new QueryWrapper<>();
        wrapperTeacher.orderByDesc("id");
        wrapperTeacher.last("limit 4");
        List<EduTeacher> teacherList = teacherService.list(wrapperTeacher);
        
        Map<String,Object> map=new HashMap<>();
        map.put("courseList",courseList);
        map.put("teacherList",teacherList);
        return Result.ok().data("newRecommended",map);
    }
}

在这里插入图片描述

8、测试(注意你需要将其配置到nacos,因为service整个模块,我的引入了nacos的依赖)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、首页banner轮播图(前端)

1、后台管理系统(对banner轮播图的增删改查页面)

1、api接口

在这里插入图片描述

2、编写页面

<template>
  <div class="dashboard-container">
    <div class="dashboard-text" >你好: {{ name }}</div>
      <h3>首页轮播图展示:单击图片修改轮播内容</h3>

      <el-button type="primary" icon="el-icon-edit" @click="clickInsertButton"></el-button>
      <el-button type="primary" icon="el-icon-delete"></el-button>

      <el-carousel :interval="4000" type="card" height="240px" style="width: 1200px;">
        <el-carousel-item v-for="banner in banners" :key="banner.id">
          <el-image :src="banner.imageUrl" @click="clickImage(banner)" style="width: 600px;height: 240px;"></el-image>
        </el-carousel-item>
      </el-carousel>
      <el-dialog :visible.sync="dialogChapterFormVisible">
          <el-form :model="url" label-width="120px">
            <el-upload
              :show-file-list="false"
              :on-success="handleAvatarSuccess"
              :before-upload="beforeAvatarUpload"
              :action="BASE_API+'/ossservice/uploadFile'"
              class="avatar-uploader">
              <img :src="url.imageUrl" style="width: 50%;">
            </el-upload>
            <br />
            <br />
            <br />
            <el-form-item label="轮播名字">
                <el-input v-model="url.title" :min="0" controls-position="center"/>
            </el-form-item>
              <el-form-item label="轮播排序">
                  <el-input-number v-model="url.sort" :min="0" controls-position="center"/>
              </el-form-item>
          </el-form>
          <div slot="footer" class="dialog-footer">
              <el-button @click="dialogChapterFormVisible = false">取 消</el-button>
              <el-button type="primary" @click="saveOrUpdate">确 定</el-button>
          </div>
      </el-dialog>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import banner from '@/api/banner/banner.js'
export default {
  name: 'Dashboard',
  data() {
    return {
      BASE_API:process.env.VUE_APP_BASE_API,//将http://localhost:9001赋值给BASE_API
      dialogChapterFormVisible:false,
      banners: [],
      url:{},
      flag:true,//true表示修改,false表示添加
    }
  },
  created() {
    this.init();
  },
  methods:{
    /* 初始化函数*/
    init(){
      this.getBannerList();
    },
    /* 获取轮播图*/
    getBannerList(){
      banner.getBannerList()
      .then(response=>{
          this.banners=response.data.banners;
      })
    },
    /*修改轮播图*/
    updateById(){
      banner.updateById(this.url)
      .then(response=>{
        this.$message({//提示
          type: 'success',
          message: '修改成功!',
        })
        this.getBannerList();
      });
    },
    /* 添加轮播图*/
    insertBanner(){
      banner.insertBanner(this.url)
      .then(response=>{
        this.$message({//提示
          type: 'success',
          message: '添加成功!'
        })
      })
    },
    /* 点击添加按钮后*/
    clickInsertButton(){
      if(this.banners.length<6){//最多六个轮播
        this.flag=false;//表示添加操作
        this.url={};//将url清空
        this.url.imageUrl="https://yzpnb-edu-1010.oss-cn-beijing.aliyuncs.com/2020/06/01/bdba970926a24245bf1f1362f7c8c0c2banner-2-green.jpg";
        this.url.title="你需要输入轮播名字才能上传图片,并预览"
        this.dialogChapterFormVisible=true;//开弹窗
      }else{
        this.$message({//提示
          type: 'error',
          message: '轮播不可多于6个!'
        })
      }
    },
    /*点击图片后*/
    clickImage(banner){//将当前轮播对象传过来
      this.flag=true;//表示修改
      this.dialogChapterFormVisible=true//弹出弹窗
      this.url=banner;//将当前对象给url
    },
    /* 上传成功调用*/
    handleAvatarSuccess(res, file) {
      console.log(res)// 上传响应
      console.log(URL.createObjectURL(file.raw))// base64编码
      this.url.imageUrl = res.data.url
    },
    /* 上传之后调用*/
    beforeAvatarUpload(file) {
      const isJPG = file.type === 'image/jpeg'
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!')
      }
      return isJPG && isLt2M
    },
    /* 点击确定按钮后*/
    saveOrUpdate(){
      if(this.flag===true){
        this.dialogChapterFormVisible=false;//关闭弹窗
        this.updateById();//修改轮播
      }else{
        this.insertBanner()//添加
        this.dialogChapterFormVisible=false;//关闭弹窗
        this.getBannerList();//刷新轮播
      }
      //3、刷新页面(为了保险,多刷一次)
      this.init();
    },
  },
  computed: {
    ...mapGetters([
      'name'
    ])
  }
}
</script>

<style lang="scss" scoped>
.dashboard {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
  .el-carousel__item:nth-child(2n) {
    background-color: #99a9bf;
  }

  .el-carousel__item:nth-child(2n+1) {
    background-color: #d3dce6;
  }
</style>

在这里插入图片描述

4、测试

在这里插入图片描述

2、前台客户端系统(首页数据展示)

你需要进行如下操作
1、封装axios请求
import axios from 'axios'
// 创建axios实例
const service = axios.create({
  baseURL: 'http://localhost:9001', // api的base_url
  timeout: 20000 // 请求超时时间
})
export default service

在这里插入图片描述

2、安装axios:npm install axios
3、安装element ui:npm install element-ui --save

1、api

在这里插入图片描述

2、代码(所有代码都在github中)

轮播图
在这里插入图片描述
在这里插入图片描述
课程和讲师
在这里插入图片描述
在这里插入图片描述

3、测试

在这里插入图片描述
在这里插入图片描述

五、添加Redis缓存首页数据

redis详细笔记
适合缓存经常查,但不经常改的数据

1、环境搭建

1、引入依赖(全局配置)

 <!--redis 与 spirng boot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <!--spring boot 集成 redis所需common pool-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.8.0</version>
        </dependency>

在这里插入图片描述

2、Redis配置类

package com.yzpnb.service_base_config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@EnableCaching//开启缓存注解
@Configuration//声明为配置类
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

在这里插入图片描述

3、添加spring boot 注解,实现数据缓存

@Cacheable(value=“缓存名”,key=“缓存键值”)
声明在处理请求的方法上,对方法返回结果缓存,适合查询方法
请求时,有缓存,直接缓存取数据,无缓存,直接执行方法,并存入缓存(达到我们规定的过期时间后,清除)
@CachePut(value=“缓存名”,key=“缓存键值”)
执行时,直接将数据存入缓存,这时其它方法使用数据,无需再从数据库查,直接就可以再缓存中读取到,适合添加方法(就是添加完,直接将数据放到缓存,查询方法不用再查数据库,直接从缓存拿数据)
@CacheEvict(value=“缓存名”,key=“缓存键值”)
使用该注解标志的方法,会清空指定的缓存,适合修改或删除方法
一个很重要的问题

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、启动redis

1、启动redis数据库服务端

在这里插入图片描述

2、启动客户端

在这里插入图片描述

3、使用Linux的常见问题

在这里插入图片描述

3、配置application.yml文件

spring:
  redis: #redis配置
    host: 127.0.0.1 #你的redis地址
    port: 6379 #端口号
    database: 0
    timeout: 1800000
    lettuce:
      pool:
        max-active: 20
        max-wait: -1
        max-idle: 5 #最大阻塞等待时间(负数表示没限制)
        min-idle: 0

在这里插入图片描述
在这里插入图片描述

4、测试

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/grd_java/article/details/106439249
今日推荐