谷粒学院(十四)轮播图前后台 | 整合Redis | 单点登录

2023-05-16

一、首页显示banner数据 – 前后台的后端

1、在service模块下创建子模块service-cms

2、使用代码生成器生成banner代码

(1)创建crm_banner表

在这里插入图片描述

(2)生成代码

在这里插入图片描述

3、配置application.properties

# 服务端口
server.port=8004
# 服务名
spring.application.name=service-cms

# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456

#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8

#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/kuang/educms/mapper/xml/*.xml

#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

4、创建启动类

创建CmsApplication.java

@SpringBootApplication
@ComponentScan({"com.kuang"})//指定扫描位置
@MapperScan("com.kuang.educms.mapper")
public class CmsApplication {

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

5、编写Controller接口

banner后台分页查询、添加、修改、删除接口

@Api(description = "后台轮播图接口")
@RestController
@RequestMapping("/educms/banneradmin")
@CrossOrigin
public class BannerAdminController {

    @Autowired
    private CrmBannerService bannerService;

    @ApiOperation(value = "获取Banner分页列表")
    @GetMapping("pageBanner/{page}/{limit}")
    public R pageBanner(@PathVariable long page,@PathVariable long limit) {
        Page<CrmBanner> pageBanner = new Page<>(page,limit);
        bannerService.page(pageBanner,null);
        return R.ok().data("items",pageBanner.getRecords()).data("total",pageBanner.getTotal());
    }

    @ApiOperation(value = "添加Banner")
    @PostMapping("addBanner")
    public R addBanner(@RequestBody CrmBanner crmBanner) {
        bannerService.save(crmBanner);
        return R.ok();
    }

    @ApiOperation(value = "获取banner")
    @GetMapping("get/{id}")
    public R get(@PathVariable String id) {
        CrmBanner banner = bannerService.getById(id);
        return R.ok().data("item",banner);
    }

    @ApiOperation(value = "更新Banner")
    @PutMapping("updateBanner")
    public R updateBanner(@RequestBody CrmBanner crmBanner) {
        bannerService.updateById(crmBanner);
        return R.ok();
    }

    @ApiOperation(value = "删除Banner")
    @DeleteMapping("removeBanner/{id}")
    public R removeBanner(@PathVariable String id) {
        bannerService.removeById(id);
        return R.ok();
    }

}

banner前台首页获取数据

@Api(description = "后台轮播图接口")
@RestController
@RequestMapping("/educms/bannerfront")
@CrossOrigin
public class BannerFrontController {

    @Autowired
    private CrmBannerService bannerService;

    @ApiOperation(value = "查询所有banner")
    @GetMapping("getAllBanner")
    public R getAllBanner() {
        List<CrmBanner> list = bannerService.selectBanner();
        return R.ok().data("list",list);
    }
}

6、实现后台的前端页面这里仿照课程模块

实现banner后台的添加修改删除和分页查询操作,和其他后台管理模块类似

7、首页显示课程名师数据

在service_edu 模块的Controller包下创建front包的IndexFrontController 类

@Api(description = "前台查询课程名师")
@RestController
@RequestMapping("/eduservice/indexfront")
@CrossOrigin
public class IndexFrontController {

    @Autowired
    private EduCourseService courseService;

    @Autowired
    private EduTeacherService teacherService;

    @ApiOperation(value = "查询前8条热门课程,查询前4条讲师")
    @GetMapping("index")
    public R index() {
        //根据id进行降序排列,显示列表之后前8条热门课程记录
        QueryWrapper<EduCourse> wrapperCourse = new QueryWrapper<>();
        wrapperCourse.orderByDesc("id");
        wrapperCourse.last("limit 8");
        List<EduCourse> courseList = courseService.list(wrapperCourse);

        //根据id进行降序排列,显示列表之后前4条讲师
        QueryWrapper<EduTeacher> wrapperTeacher = new QueryWrapper<>();
        wrapperTeacher.orderByDesc("id");
        wrapperTeacher.last("limit 4");
        List<EduTeacher> teacherList = teacherService.list(wrapperTeacher);

        return R.ok().data("courseList",courseList).data("teacherList",teacherList);
    }

}

二、首页显示banner数据 – 前台的前端

1、准备工作

(1)使用命令,下载axios依赖

npm install axios

(2)封装axios

在这里插入图片描述

import axios from 'axios'
// 创建axios实例
const service = axios.create({
  baseURL: 'http://localhost:9001', // api的base_url
  timeout: 20000 // 请求超时时间
})
export default service

2、首页banner 数据显示

(1)创建api 文件夹,在api文件夹创建js文件,定义调用接口路径

import request from '@/utils/request'

export default {
    //查询前两条banner数据
  getListBanner() {
    return request({
        url: `/educms/bannerfront/getAllBanner`,
        method: 'get'
      })
  }
}

(2)在页面调用接口得到数据进行显示

在index.vue 中

<script>
import banner from '@/api/banner'
export default {
  data () {
    return {
      swiperOption: {
        //配置分页
        pagination: {
          el: '.swiper-pagination'//分页的dom节点
        },
        //配置导航
        navigation: {
          nextEl: '.swiper-button-next',//下一页dom节点
          prevEl: '.swiper-button-prev'//前一页dom节点
        }
      },
      //banner数组
      bannerList:[]
    }
  },
  created() {
    //调用查询banner的方法
    this.getBannerList()
  },
  methods:{
    getBannerList() {
      banner.getListBanner()
        .then(response => {
          this.bannerList = response.data.data.list
        })
    }
  }
}
</script>

修改轮播图展示页面

<!-- 幻灯片 开始 -->
<div v-swiper:mySwiper="swiperOption">
    <div class="swiper-wrapper">

        <div v-for="banner in bannerList" :key="banner.id" class="swiper-slide" style="background: #040B1B;">
            <a target="_blank" :href="banner.linkUrl">
                <img :src="banner.imageUrl" :alt="banner.title">
            </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>
<!-- 幻灯片 结束 -->

3、nginx进行访问规则配置

在这里插入图片描述

4、首页显示课程名师数据

(1)在api中定义接口

命名:index.js

import request from '@/utils/request'

export default {
  //查询热门课程和讲师
  getListBanner() {
    return request({
        url: `/eduservice/indexfront/index`,
        method: 'get'
      })
  }
}

(2)在页面定义js文件

data () {
  return {
    //....
    eduList:[],
    teacherList:[]
  }
},
created() {
  //.....
  //调用查询热门课程和名师
  this.getHotCourseTeacher()
},
methods:{
  //查询热门课程和名师
  getHotCourseTeacher() {
    index.getListBanner()
      .then(response => {
        this.eduList = response.data.data.courseList
        this.teacherList = response.data.data.teacherList
      })
  },
  //....
}

(3)课程页面遍历显示

<li v-for="course in eduList" :key="course.id">
  <div class="cc-l-wrap">
    <section class="course-img">
      <img
        :src="course.cover"
        class="img-responsive"
        :alt="course.title"
      >
      <div class="cc-mask">
        <a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
      </div>
    </section>
    <h3 class="hLh30 txtOf mt10">
      <a href="#" :title="course.title" class="course-title fsize18 c-333">{{course.title}}</a>
    </h3>
    <section class="mt10 hLh20 of">
      <span class="fr jgTag bg-green" v-if="Number(course.price) === 0">
        <i class="c-fff fsize12 f-fA">免费</i>
      </span>
      <span class="fr jgTag bg-green" v-else>
        <i class="c-fff fsize12 f-fA">¥{{course.price}}</i>
      </span>
      <span class="fl jgAttr c-ccc f-fA">
        <i class="c-999 f-fA">{{course.buyCount}} 人学习</i>
        |
        <i class="c-999 f-fA">{{course.viewCount}} 人浏览</i>
      </span>
    </section>
  </div>
</li>

(4)名师页面遍历显示

<li v-for="teacher in teacherList" :key="teacher.id">
  <section class="i-teach-wrap">
    <div class="i-teach-pic">
      <a href="/teacher/1" :title="teacher.name">
        <img :alt="teacher.name" :src="teacher.avatar">
      </a>
    </div>
    <div class="mt10 hLh30 txtOf tac">
      <a href="/teacher/1" :title="teacher.name" class="fsize18 c-666">{{teacher.name}}</a>
    </div>
    <div class="hLh30 txtOf tac">
      <span class="fsize14 c-999">{{teacher.career}}</span>
    </div>
    <div class="mt15 i-q-txt">
      <p
        class="c-999 f-fA"
      >{{teacher.intro}}</p>
    </div>
  </section>
</li>

三、首页数据添加Redis缓存

1、Redis介绍

Redis是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语言编写的key-value存储系统(区别于MySQL的二维表格的形式存储)。和Memcache类似,但很大程度补偿了Memcache的不足。和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的应用场景适用于缓存无需持久化的数据。而Redis不同的是它会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,实现数据的持久化。

Redis的特点:

  • Redis读取的速度是110000次/s,写的速度是81000次/s;
  • 原子 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
  • 支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)
  • 持久化,集群部署
  • 支持过期时间,支持事务,消息订阅

一般来说,把经常进行查询,不经常修改,不是特别重要的数据放在redis作为缓存。

2、项目集成Redis

(1)在common模块添加依赖

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- spring2.X集成redis所需common-pool2-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.0</version>
</dependency>

(2)在service_base模块添加redis配置文件

RedisConfig.java

@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、在接口中添加redis缓存

由于首页数据变化不是很频繁,而且首页访问量相对较大,所以我们有必要把首页接口数据缓存到redis缓存中,减少数据库压力和提高访问速度。

改造service-cms模块首页banner接口,首页课程与讲师接口类似

Spring Boot缓存注解说明

(1)缓存@Cacheable

根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

查看源码,属性值如下:
在这里插入图片描述
(2)缓存@CachePut

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。

查看源码,属性值如下:
在这里插入图片描述

(3)缓存@CacheEvict

使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上

查看源码,属性值如下:
在这里插入图片描述

启动redis服务

4、service_cms模块接口改造

(1)在service-cms模块配置文件添加redis配置

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000

spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0

(2)修改CrmBannerServiceImpl类中的方法,添加redis缓存注解

@Cacheable(value = "banner",key = "'selectIndexList'")

(3)在redis添加了key

在这里插入图片描述

四、单点登录与用户业务介绍

1、单一服务器模式

早期单一服务器,用户认证。

在这里插入图片描述
使用session对象实现;登录成功之后,把用户数据放到session里面;判断是否登录,从session获取数据,可以获取到登录。

缺点:单点性能压力,无法扩展。

2、 SSO(single sign on) 模式【也叫单点登录】

在这里插入图片描述

缺点:认证服务器访问压力较大。

单点登录三种常见方式

  • session广播机制实现

简单说就是session复制。

  • 使用cookie + redis 实现

在项目中任何一个模块进行登录,登录之后,把数据放在两个地方
(1)redis,在key:生成唯一随机值,在value:用户数据
(2)cookie,把redis里面生成key值放到cookie里面
访问项目中其他模块,发送请求带着cookie进行发送,获取cookie值,拿着cookie做事情;把cookie获取值,到redis进行查询,根据key进行查询,如果查询数据就是登陆

  • 使用token实现

在项目某个模块进行登录,登录之后,按照规则生成字符串,把登录之后用户包含到生成字符串里面,把字符串返回
(1)可以把字符串通过cookie返回
(2)把字符串通过地址栏返回
再去访问项目其他模块,每次访问在地址栏带着生成字符串,在访问模块里面获取地址栏字符串,根据字符串获取用户信息。如果可以获取到,就是登陆

3、Token模式

token【令牌】是什么:按照一定规则生成字符串,字符串可以包含用户信息。

缺点:占用带宽;无法在服务器端销毁;

注:基于微服务开发,选择token的形式相对较多,因此我使用token作为用户认证的标准


如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷粒学院(十四)轮播图前后台 | 整合Redis | 单点登录 的相关文章

  • PyTorch:torch.Tensor.repeat()、expand()

    目录 1 torch Tensor repeat 2 torch Tensor expand 1 torch Tensor repeat 函数定义 xff1a repeat sizes Tensor 作用 xff1a 在指定的维度上重复这个
  • Cookie学习笔记

    1 cookie 简介 1 1 什么是 cookie cookie xff0c 有时我们也用其复数形式 cookies xff0c 是服务端保存在浏览器端的数据片段 以 key value 的形式进行保存 每次请求的时候 xff0c 请求头
  • mybatis中关于example类详解

    一 什么是example类 mybatis generator会为每个字段产生如上的Criterion xff0c 如果表的字段比较多 产生的Example类会十分庞大 理论上通过example类可以构造你想到的任何筛选条件 在mybati
  • springmvc实现文件上传与下载【单张及多张图片】

    一 springmvc实现文件上传的步骤 1 实现上传单张图片 1 导入pom 坐标 span class token comment lt 文件上传 gt span span class token tag span class toke
  • SpringBoot 搭建的个人博客

    介绍 blog是基于SpringBoot 搭建的个人博客 xff0c 响应式 前端技术 xff1a html css js jq bootstrap 后台技术 xff1a springboot thymeleaf mybatis mysql
  • SpringCloud(一)微服务概述

    文章目录 微服务概述什么是微服务微服务与微服务架构微服务的优缺点优点缺点 微服务的技术栈为什么选SpringCloud作为微服务架构选型依据当前各大IT公司的微服务架构各微服务的框架对比 SpringCloud入门概述SpringCloud
  • SpringCloud(二)入门案例之支付模块与订单模块的调用

    SpringCloud xff08 一 xff09 微服务概述 xff1a https blog csdn net weixin 45606067 article details 108481733 构建SpringCloud工程 概述 x
  • SpringCloud(三)Eureka服务注册中心

    文章目录 1 Eureka基础知识什么是服务治理什么是服务注册Eureka两大组件 2 Eureka介绍及原理理解介绍原理 3 单机版Eureka 构建步骤4 集群版Eureka 构建步骤Eureka集群原理说明EurekaServer集群
  • SpringCloud(四)zookeeper介绍及原理

    SpringCloud xff08 四 xff09 zookeeper介绍及原理 xff1a https blog csdn net weixin 45606067 article details 108499344 Zookeeper服务
  • docker 的安装 - 常用命令 - 应用部署

    文章目录 1 Docker简介什么是虚拟化什么是Docker容器与虚拟化比较Docker 组件1 Docker服务器与客户端2 Docker镜像与容器3 Register xff08 注册中心 xff09 2 Docker安装与启动安装Do
  • SpringCloud(六)Ribbon负载均衡服务调用

    Ribbon负载均衡 概述 是什么 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡工具 简单的说 xff0c Ribbon是Netflix发布的开源项目 xff0c 主要功能是提供客户端的
  • Python:map()函数使用详解

    1 函数定义 xff1a map function iterable 2 作用 xff1a 该函数通过接收一个函数function作为处理函数 xff0c 然后接收一个参数序列iterable xff0c 并使用处理函数对序列中的每个元素逐
  • SpringCloud(五)Consul服务注册与发现

    SpringCloud xff08 四 xff09 zookeeper介绍及原理 xff1a https blog csdn net weixin 45606067 article details 108538357 Consul简介 是什
  • SpringCloud(七)OpenFeign负载均衡服务调用

    1 概述 1 OpenFeign是什么 官网解释 xff1a https cloud spring io spring cloud static Hoxton SR1 reference htmlsingle spring cloud op
  • Zookeeper概述 | 安装部署(Windows和Linux)

    Zookeeper 一 Zokeeper 门 1 概述 Zookeeper是一个开源的分布式的 xff0c 为分布式应用提供协调服务的Apache项目 ZooKeeper is a centralized service for maint
  • Zookeeper内部原理

    Zookeeper概述 安装部署 xff08 Windows和Linux xff09 xff1a https blog csdn net weixin 45606067 article details 108619378 1 选举机制 面试
  • jsp和servlet的区别

    基本介绍 Servlet xff1a Servlet 是一种服务器端的Java应用程序 xff0c 具有独立于平台和协议的特性 xff0c 可以生成动态的Web页面 它担当客户请求 xff08 Web浏览器或其他HTTP客户程序 xff09
  • Session学习笔记

    1 session 简介 session 是我们 jsp 九大隐含对象的一个对象 session 称作域对象 xff0c 他的作用是保存一些信息 xff0c 而 session 这个域对象是一次会话期间使用同一个对象 所以这个对象可以用来保
  • session和cookie 区别【面试】

    说说Cookie和Session的区别 xff1f 1 存取方式的不同 xff08 Cookie只能保存ASCII xff0c Session可以存任意数据类型 xff09 Cookie中只能保管ASCII字符串 xff0c 假如需求存取U
  • JSP 九大内置对象,四大域对象

    JSP的九大内置对象 内置对象名 类型 request HttpServletRequest response HttpServletResponse session HttpSession application ServletConte

随机推荐