day11【首页数据显示和添加Redis缓存】

1 搭建项目前端环境(NUXT)

01-服务端渲染技术NUXT-初始化NUXT

一、服务端渲染技术NUXT

1、什么是服务端渲染

服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。

服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。

如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。

另外,使用服务器端渲染,我们可以获得更快的内容到达时间(time-to-content),无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验,对于那些「内容到达时间(time-to-content)与转化率直接相关」的应用程序而言,服务器端渲染(SSR)至关重要。

2、什么是NUXT

Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。

官网网站:

https://zh.nuxtjs.org/

二、NUXT环境初始化

安装 nuxt.js:vue init nuxt-community/starter-template <你项目的名字>

运行Nuxt: npm install          npm run dev

1、NUXT目录结构

(1)资源目录 assets

     用于组织未编译的静态资源如 LESS、SASS 或 JavaScript。

(2)组件目录 components

    用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。

(3)布局目录 layouts

    用于组织应用的布局组件

(4)页面目录 pages

    用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。

(5)插件目录 plugins

    用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。

(6)nuxt.config.js 文件

    nuxt.config.js 文件用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。

三、幻灯片插件

1、安装插件

npm install vue-awesome-swiper

查看安装:

2、配置插件

在 plugins 文件夹下新建文件 nuxt-swiper-plugin.js,内容是

import Vue from 'vue'

import VueAwesomeSwiper from 'vue-awesome-swiper/dist/vue-awesome-swiper.js'

Vue.use(VueAwesomeSwiper)

在 nuxt.config.js 文件中配置插件

将 plugins 和 css节点 复制到 module.exports节点下

  plugins: [

    { src: '~/plugins/nuxt-swiper-plugin.js', ssr: false }

  ],

  css: [

    'swiper/dist/css/swiper.css'

  ]


02-首页静态效果整合和NUXT路由

一、页面布局

1、复制静态资源

将静态原型中的css、img、js、photo目录拷贝至assets目录下

2、定义布局

我们可以把页头和页尾提取出来,形成布局页

修改layouts目录下default.vue,从静态页面中复制首页,修改了原始文件中的资源路径为~/assets/,将主内容区域的内容替换成<nuxt />

3、定义首页面

(不包含幻灯片)

修改pages/index.vue:

修改了原始文件中的资源路径为~/assets/

4、幻灯片插件

<!-- 幻灯片 开始 -->

    <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>

    <!-- 幻灯片 结束 -->

script

<script>

export default {

  data () {

    return {

      swiperOption: {

        //配置分页

        pagination: {

          el: '.swiper-pagination'//分页的dom节点

        },

        //配置导航

        navigation: {

          nextEl: '.swiper-button-next',//下一页dom节点

          prevEl: '.swiper-button-prev'//前一页dom节点

        }

      }

    }

  }

}

</script>

重新启动:npm run dev

访问网页:

二、路由

1、固定路由

(1)使用router-link构建路由,地址是/course

(2)在page目录创建文件夹course ,在course目录创建index.vue

点击导航,测试路由

2、动态路由

(1)创建方式

如果我们需要根据id查询一条记录,就需要使用动态路由。NUXT的动态路由是以下划线开头的vue文件,参数名为下划线后边的文件名

在pages下的course目录下创建_id.vue

三、封装axios

我们可以参考guli-admin将axios操作封装起来

下载axios ,使用命令:

npm install axios

创建utils文件夹,utils下创建request.js

import axios from 'axios'

// 创建axios实例

const service = axios.create({

  baseURL: 'http://localhost:9001', // api的base_url

  timeout: 20000 // 请求超时时间

})

export default service


03-名师页面静态效果整合

一、列表页面

创建 pages/teacher/index.vue

二、详情页面

创建 pages/teacher/_id.vue

修改资源路径为~/assets/


04-课程页面静态效果整合

一、列表页面

创建 pages/course/index.vue

二、详情页面

创建 pages/course/_id.vue



2 首页显示数据【前后端实现】

01-首页显示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.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false

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/atguigu/cmsservice/mapper/xml/*.xml

#mybatis日志

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

#配置mapper xml文件的路径

#如果需要在xml中写sql语句,需要添加两个配置,1在pom中 2在application中

mybatis-plus.mapper-locations=classpath:com/atguigu/educms/mapper/xml/*.xml

4、创建启动类

创建CmsApplication.java

package com.atguigu.educms;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.ComponentScan;


@SpringBootApplication

@ComponentScan({"com.atguigu"}) //指定扫描位置

public class CmsApplication {

    public static void main(String[] args) {

        SpringApplication.run(CmsApplication.class, args);

    }

}

@SpringBootApplication

@ComponentScan({"com.atguigu"}) //指定扫描位置

@MapperScan("com.atguigu.cmsservice.mapper")//操作数据库中有mapper,所以需要添加MapperScan扫描,添加到1配置类 或 2启动类

public class CmsApplication {

    public static void main(String[] args) {

        SpringApplication.run(CmsApplication.class, args);

    }

}


二、创建banner服务接口

1、创建banner后台管理接口

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

@RestController

@RequestMapping("/educms/banneradmin")

@CrossOrigin

public class BannerAdminController {

    @Autowired

    private CrmBannerService bannerService;

    //1 分页查询banner

    @ApiOperation(value = "获取Banner分页列表")

    @GetMapping("pageBanner/{page}/{limit}")

    public R pageBanner(@PathVariable long page,

                        @PathVariable long limit){

        Page<CrmBanner> crmBannerPage = new Page<>(page,limit);

        bannerService.page(crmBannerPage,null);

        return R.ok().data("items",crmBannerPage.getRecords()).data("total",crmBannerPage.getTotal());

    }

    //2 获取

    @ApiOperation(value = "获取Banner")

    @GetMapping("get/{id}")

    public R get(@PathVariable String id){

        CrmBanner crmBanner = bannerService.getBannerById(id);

        return R.ok().data("item",crmBanner);

    }

    //3 添加

    @ApiOperation(value = "新增Banner")

    @PostMapping("save")

    public R save(@RequestBody CrmBanner banner){

        bannerService.saveBanner(banner);

        return R.ok();

    }

    //4 修改

    @ApiOperation(value = "修改Banner")

    @PostMapping("update")

    public R updateById(@RequestBody CrmBanner banner){

        bannerService.updateBannerById(banner);

        return R.ok();

    }

    //5 删除

    @ApiOperation(value = "删除Banner")

    @DeleteMapping("remove/{id}")

    public R remove(@PathVariable String id){

        bannerService.removeBannerById(id);

        return R.ok();

    }

}

CrmBannerServiceImpl.java

@Override

    public CrmBanner getBannerById(String id) {

        CrmBanner crmBanner = baseMapper.selectById(id);

        return crmBanner;

    }

    @Override

    public void saveBanner(CrmBanner banner) {

        baseMapper.insert(banner);

    }

    @Override

    public void updateBannerById(CrmBanner banner) {

        baseMapper.updateById(banner);

    }

    @Override

    public void removeBannerById(String id) {

        baseMapper.deleteById(id);

    }

2、创建banner前台查询接口

首页获取banner数据接口

@RestController

@RequestMapping("/educms/bannerfront")

@Api(description = "网站首页Banner列表")

@CrossOrigin

public class BannerFrontController {

    @Autowired

    private CrmBannerService bannerService;

    @ApiOperation(value = "获取首页banner")

    @GetMapping("getAllBanner")

    public R index() {

        List<CrmBanner> list = bannerService.selectIndexList();

        return R.ok().data("list", list);

    }

}

@Override

    public List<CrmBanner> selectIndexList() {

        List<CrmBanner> crmBanners = baseMapper.selectList(null);

        return crmBanners;

    }

三、实现banner后台管理前端

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


02-首页显示课程名师数据【后端】

(1)查询前2条baner数据

CrmBannerServiceImpl

@Override

    public List<CrmBanner> selectIndexList() {

        //根据id进行降序排列,显示排列之后的前两条记录

        QueryWrapper<CrmBanner> wrapper = new QueryWrapper<>();

        wrapper.orderByDesc("id");

        //last方法,拼接sql语句

        wrapper.last("limit 2");

        List<CrmBanner> crmBanners = baseMapper.selectList(null);

        return crmBanners;

    }

一、新建前端查询课程名师接口

1、在service-edu模块controller中创建包front

(1)查询最新前4条讲师数据

(2)查询最新前8条课程数据

@RestController

@RequestMapping("/eduservice/index")

@CrossOrigin

public class IndexController {

    //查询前8条热门课程,查询前4条名师

    @Autowired

    private EduCourseService courseService;

    @Autowired

    private EduTeacherService teacherService;

    @GetMapping("index")

    public R index() {

        //查询前8条热门课程

        QueryWrapper<EduCourse> courseQueryWrapper = new QueryWrapper<>();

        courseQueryWrapper.orderByDesc("id");

        courseQueryWrapper.last("limit 8");

        List<EduCourse> courseList = courseService.list(courseQueryWrapper);

        //查询前4条名师

        .......

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

    }

}


03-首页显示banner和课程名师数据【前端】

一、首页banner数据显示

1、创建api文件夹,创建banner.js文件

banner.js

import request from '@/utils/request'

export default {

  //获取首页banner

  getList() {

    return request({

      url: `/educms/bannerfront/getAllBanner`,

      method: 'get'

    })

  }

}

2、在首页面引入,调用实现

框架的结构中,由两个页面构成,layouts/default.vue(头和尾)和pages/index.vue(首页)

<script>

import banner from "@/api/banner"

export default {

  data () {

    return {

      bannerList: {},

      swiperOption: {

        //配置分页

        pagination: {

          el: '.swiper-pagination'//分页的dom节点

        },

        //配置导航

        navigation: {

          nextEl: '.swiper-button-next',//下一页dom节点

          prevEl: '.swiper-button-prev'//前一页dom节点

        }

      }

    }

  },

  created(){

      this.initDataBanner()

  },

  methods: {

    initDataBanner() {

      banner.getList()

            .then(response=>{

                this.bannerList = response.data.data.list

            })

    }

  }

}

</script>

3、在页面遍历显示banner

   <!-- 幻灯片 开始 -->

    <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"> 

                <!-- linkUrl对应实体类中的字段 -->

                    <img width="100%"

                        :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>

    <!-- 幻灯片 结束 -->

nginx访问规则配置:

二、首页显示课程和名师数据

1、创建api文件夹,创建index.js文件

index.js

import request from '@/utils/request'

export default {

  //获取首页banner

  getList() {

    return request({

      url: `/eduservice/index/index`,

      method: 'get'

    })

  }

}

2、在首页面引入,调用实现

<script>

import banner from "@/api/banner"

import index from '@/api/index'

export default {

  data () {

    return {

      courseList: {},

      teacherList: {},

      bannerList: {},

      swiperOption: {

        //配置分页

        pagination: {

          el: '.swiper-pagination'//分页的dom节点

        },

        //配置导航

        navigation: {

          nextEl: '.swiper-button-next',//下一页dom节点

          prevEl: '.swiper-button-prev'//前一页dom节点

        }

      }

    }

  },

  created(){

    this.initDataBanner()

    this.initDataObj()

  },

  methods: {

    initDataBanner() {

      banner.getList()

            .then(response=>{

              this.bannerList = response.data.data.list

            })

    },

    initDataObj(){

      index.getList()

        .then(response=>{

            this.teacherList = response.data.data.teacherList

            this.courseList = response.data.data.courseList

        })

    }

  }

}

</script>

3、在页面遍历显示课程和名师

 <div id="aCoursesList">

      <!-- 网校课程 开始 -->

      <div>

        <section class="container">

          <header class="comm-title">

            <h2 class="tac">

              <span class="c-333">热门课程</span>

            </h2>

          </header>

          <div>

            <article class="comm-course-list">

              <ul class="of" id="bna">

                <li v-for="course in courseList" :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="'/course/'+course.id" 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>


              </ul>

              <div class="clear"></div>

            </article>

            <section class="tac pt20">

              <a href="#" title="全部课程" class="comm-btn c-btn-2">全部课程</a>

            </section>

          </div>

        </section>

      </div>

      <!-- /网校课程 结束 -->

      <!-- 网校名师 开始 -->

      <div>

        <section class="container">

          <header class="comm-title">

            <h2 class="tac">

              <span class="c-333">名师大咖</span>

            </h2>

          </header>

          <div>

            <article class="i-teacher-list">

              <ul class="of">

                <li v-for="teacher in teacherList" :key="teacher.id">

                  <section class="i-teach-wrap">

                    <div class="i-teach-pic">

                      <a :href='"/teacher/"+teacher.id' :title="teacher.name">

                        <img :alt="teacher.name" :src="teacher.avatar">

                      </a>

                    </div>

                    <div class="mt10 hLh30 txtOf tac">

                      <a :href='"/teacher/"+teacher.id' :title="teacher.name" class="fsize18 c-666">{{teacher.name}}</a>

                    </div>

                    <div class="hLh30 txtOf tac">

                      <span class="fsize14 c-999">{{teacher.intro}}</span>

                    </div>

                    <div class="mt15 i-q-txt">

                      <p

                        class="c-999 f-fA"

                      >{{teacher.career}}</p>

                    </div>

                  </section>

                </li>


              </ul>

              <div class="clear"></div>

            </article>

            <section class="tac pt20">

              <a href="#" title="全部讲师" class="comm-btn c-btn-2">全部讲师</a>

            </section>

          </div>

        </section>

      </div>

      <!-- /网校名师 结束 -->

测试:http://localhost:3000



3 首页显示数据添加Redis缓存

        需求:解决访问量大的问题

01-首页数据添加Redis缓存

一、Redis介绍

        Redis是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语言编写的key-value存储系统(区别于MySQL的二维表格的形式存储。)。和Memcache类似,但很大程度补偿了Memcache的不足。

        和Memcache一样,Redis数据都是缓存在计算机内存中,不同的是,Memcache只能将数据缓存到内存中,无法自动定期写入硬盘,这就表示,一断电或重启,内存清空,数据丢失。所以Memcache的应用场景适用于缓存无需持久化的数据。而Redis不同的是它会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,实现数据的持久化。

Redis的特点:

1,Redis读取的速度是110000次/s,写的速度是81000次/s;

2,原子 。Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

3,支持多种数据结构:string(字符串);list(列表);hash(哈希),set(集合);zset(有序集合)

4,持久化,集群部署

5,支持过期时间,支持事务,消息订阅

二、项目集成Redis

1、在common模块添加依赖

由于redis缓存是公共应用,所以我们把依赖与配置添加到了common模块下面,在common模块pom.xml下添加以下依赖

        <!-- 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>

    </dependencies>

2、在service-base模块添加redis配置类

RedisConfig.java

package com.atguigu.servicebase;

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))  //设置数据过期时间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接口,首页课程与讲师接口类似。

需要引入:

3.1 Spring Boot缓存注解

(1)缓存@Cacheable

根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;

如果缓存不存在,则执行方法,并把返回的结果存入缓存中。

一般用在查询方法上

查看源码,属性值如下:value(缓存名)和key(可选属性) 这两个值会构成保存到redis中的key的名称,Redis基于key-value进行存储的。

(2)缓存@CachePut

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中

其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。

一般用在新增方法上。

查看源码,属性值如下:

(3)缓存@CacheEvict

使用该注解标志的方法,会清空指定的缓存

一般用在更新或者删除方法上

查看源码,属性值如下:

3.2 启动redis服务

在windows下安装redis:

解压安装:将下载的Redis-x64-3.2.100.zip 解压到某个地址。

解压后目录如下:

启动命令:

通过cmd指定到该redis目录。

使用命令:redis-server.exe 启动服务

启动另一个cmd,在该redis目录下,使用命令:redis-cli.exe 启动客户端,连接服务器

出现这种效果,表明启动客户度成功。

3.3(虚拟机)连接redis服务可能遇到的问题

(1)关闭liunx防火墙

(2)找到redis配置文件, 注释一行配置

(3)如果出现下面错误提示

fangwen

修改 protected-mode yes

改为

protected-mode no

3.4 banner接口改造

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

#redis配置 windows采用本机127.0.0.1 虚拟机采用虚拟机的IP

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缓存注解

@Service

public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService {

    @Override

    public CrmBanner getBannerById(String id) {

        CrmBanner crmBanner = baseMapper.selectById(id);

        return crmBanner;

    }

    @CacheEvict(value = "banner", allEntries=true)

    @Override

    public void saveBanner(CrmBanner banner) {

        baseMapper.insert(banner);

    }

    @CacheEvict(value = "banner", allEntries=true)

    @Override

    public void updateBannerById(CrmBanner banner) {

        baseMapper.updateById(banner);

    }

    @CacheEvict(value = "banner", allEntries=true)

    @Override

    public void removeBannerById(String id) {

        baseMapper.deleteById(id);

    }

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

    @Override

    public List<CrmBanner> selectIndexList() {

        //根据id进行降序排列,显示排列之后的前两条记录

        QueryWrapper<CrmBanner> wrapper = new QueryWrapper<>();

        wrapper.orderByDesc("id");

        //last方法,拼接sql语句

        wrapper.last("limit 2");

        List<CrmBanner> crmBanners = baseMapper.selectList(null);

        return crmBanners;

    }

}

(3)在redis添加了key

第一次查询执行了sql语句,再次获取页面没有执行sql语句,而是查询redis缓存中的数据。

查询:

(4)通过源码查看到key生成的规则

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351