谷粒学院
首页显示课程名师数据
一、后端部分
新建前端查询课程名师接口
- 在service-edu模块创建controller
(1)查询最新前4条讲师数据
(2)查询最新前8条课程数据
@RestController
@CrossOrigin
@RequestMapping("/eduservice/indexFront")
public class IndexFrontController {
@Autowired
private EduCourseService eduCourseService;
@Autowired
private EduTeacherService eduTeacherService;
//查询前8条热门课程,查询前4个名师
@GetMapping("/index")
public R index(){
//查询前8条热门课程
QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("view_count");
wrapper.last("limit 8");
List<EduCourse> courseList = eduCourseService.list(wrapper);
//查询前4张名师
QueryWrapper<EduTeacher> wrapper1 = new QueryWrapper<>();
wrapper1.orderByDesc("id");
wrapper1.last("limit 4");
List<EduTeacher> teacherList = eduTeacherService.list(wrapper1);
return R.ok().data("courseList",courseList).data("teacherList",teacherList);
}
}
二、前端部分
1、首页banner数据显示
- 创建api文件夹,创建banner.js文件
- banner.js
import request from '@/utils/request'
export default{
//查询前两条banner数据
getListBanner(){
return request({
url: '/cmsservice/bannerFront/getAll/',
method: 'get'
})
}
}
2、在首页面引入,调用实现
import banner from '@/api/banner';
export default {
data() {
return {
swiperOption: {
...
bannerList:[],
};
},
methods: {
getBannerList(){
banner.getListBanner().then(resp=>{
this.bannerList = resp.data.data.list
})
}
},
created() {
//获取两条banner数据
this.getBannerList();
},
};
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">
<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>
<!-- 幻灯片 结束 -->
4、nginx访问配置
server {
listen 9001;
server_name localhost;
......
location ~ /cmsservice/ {
proxy_pass http://localhost:8004;
}
}
5、首页显示课程和名师数据
- 创建api文件夹,创建index.js文件
- index.js
import request from '@/utils/request'
export default{
//查询热门课程和名师
getIndexData(){
return request({
url: '/eduservice/indexFront/index/',
method: 'get'
})
}
}
6、在首页面引入,调用实现
<script>
import banner from "@/api/banner";
import index from "@/api/index";
export default {
data() {
return {
swiperOption: {
//配置分页
pagination: {
el: ".swiper-pagination", //分页的dom节点
},
//配置导航
navigation: {
nextEl: ".swiper-button-next", //下一页dom节点
prevEl: ".swiper-button-prev", //前一页dom节点
},
},
bannerList: [],
teacherList: [],
courseList: [],
};
},
methods: {
//查询幻灯片
getBannerList() {
banner.getListBanner().then((resp) => {
this.bannerList = resp.data.data.list;
});
},
//查询热门课程和讲师
getHotCourseAndTeacher() {
index.getIndexData().then((resp) => {
this.courseList = resp.data.data.courseList;
this.teacherList = resp.data.data.teacherList;
});
},
},
created() {
//获取两条banner数据
this.getBannerList();
//获取热门课程和讲师
this.getHotCourseAndTeacher();
},
};
</script>
7、在页面遍历显示课程和名师、幻灯片遍历
<!-- 幻灯片 开始 -->
<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>
<!-- 幻灯片 结束 -->
<!-- 幻灯片 结束 -->
<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="#" 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="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">9634人学习</i>
|
<i class="c-999 f-fA">9634评论</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/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>
</ul>
<div class="clear"></div>
</article>
<section class="tac pt20">
<a href="#" title="全部讲师" class="comm-btn c-btn-2">全部讲师</a>
</section>
</div>
</section>
</div>
首页数据添加Redis缓存
二、项目集成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>
2 、在service-base模块添加redis配置类
@Configuration //配置类
@EnableCaching //开启缓存
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)) //设置缓存存在的时间 600s
.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
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不
存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法
上。
查看源码,属性值如下:
(2)缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存
中读取缓存数据,而不需要再去查询数据库。一般用在新增方法
上。
(3)缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法
上
查看源码,属性值如下:
3.2 启动redis服务
3.3连接redis服务可能遇到的问题
如果报:NOAUTH Authentication required
错误就是设置了密码
auth 你的密码
redis配置文件修改:
ps -ef|grep redis
kill 杀掉redis进程
重启redis服务
./redis-server
./redis-cli 你的配置文件配置
3.4 banner接口改造
(1)在service-cms模块配置文件添加redis配置
spring.redis.host=192.168.44.132
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.password=你设置的redis密码,没有可以不写
#最大阻塞等待时间(负数表示没限制)
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 {
//@Cacheable用于查询
@Cacheable(value = "banner", key = "'selectIndexList'")
@Override
public List<CrmBanner> selectIndexList() {
List<CrmBanner> list = baseMapper.selectList(new
QueryWrapper<CrmBanner>().orderByDesc("sort"));
return list;
}
@Override
public void pageBanner(Page<CrmBanner> pageParam, Object o) {
baseMapper.selectPage(pageParam,null);
}
@Override
public CrmBanner getBannerById(String id) {
return baseMapper.selectById(id);
}
@CacheEvict(value = "banner", allEntries=true)
@Override
public void saveBanner(CrmBanner banner) {
baseMapper.insert(banner);
}
//CacheEvict用于更新或删除,allEntries属性清楚缓存
@CacheEvict(value = "banner", allEntries=true)
@Override
public void updateBannerById(CrmBanner banner) {
baseMapper.updateById(banner);
}
//CacheEvict用于更新或删除,allEntries属性清楚缓存
@CacheEvict(value = "banner", allEntries=true)
@Override
public void removeBannerById(String id) {
baseMapper.deleteById(id);
}
- 整合到8001项目中
com.achang.eduservice.controller.front.IndexFrontController
@RestController
@CrossOrigin
@RequestMapping("/eduservice/indexFront")
public class IndexFrontController {
@Autowired
private EduCourseService eduCourseService;
@Autowired
private EduTeacherService eduTeacherService;
//查询前8条热门课程,查询前4个名师
@GetMapping("/index")
public R index(){
//调用查询前8热门课程的方法
List<EduCourse> courseList = eduCourseService.selectHotCourse();
//查询前4张热门讲师
List<EduTeacher> teacherList = eduTeacherService.selectHotTeacher();
return R.ok().data("courseList",courseList).data("teacherList",teacherList);
}
}
- com.achang.eduservice.service.impl.EduCourseServiceImpl
//查询8个热门课程
@Override
@Cacheable(key = "'selectHotCourse'",value = "course")
public List<EduCourse> selectHotCourse() {
//查询前8条热门课程
QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("view_count");
wrapper.last("limit 8");
return baseMapper.selectList(wrapper);
}
- com.achang.eduservice.service.impl.EduTeacherServiceImpl
//查询前4个热门讲师
@Override
@Cacheable(key = "'selectHotTeacher'",value = "teacher")
public List<EduTeacher> selectHotTeacher() {
QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
wrapper.last("limit 4");
return baseMapper.selectList(wrapper);
}
- 启动项目测试,测试
redis多了如下: