要开始做前台部分(用户环境)
之前我们用的后台前端框架是vue-admin-template
这次的前台框架是用的NUXT
轮播图实现
显示课程和老师
redis缓存
NUXT
服务端渲染技术
解压guli_site
在这里我们使用的是成品,页面也基本写好
然后下载依赖:
开始运行:
npm rum dev
后面出错了,原因是错误的回车,换行,缩进,按照提示改成对应的缩进,就行(在_id.vue里重新改一下缩进)
启动成功:
目录结构
.nuxt 编译后的文件
assets 静态文件(css,img等)
compents 项目使用相关组件
layout 定义网页布局
middleware 中间件
node_modules 组件
pages 页面
nuxt.config.js 配置文件
首页面
下载幻灯片插件
需要固定版本
npm install vue-awesome-swiper@3.1.3
幻灯片配置(已配好)
静态资源(已配好)
复制default.vue页面
banner接口
放到service-cms
创建模块
service_cms
启动类:
package com.lkw.cmsservice;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = {"com.lkw.*"})
@MapperScan("com.lkw.cmsservice.mapper")
public class CmsApplication {
public static void main(String[] args) {
SpringApplication.run(CmsApplication.class, args);
}
}
application.properties
service_acl
添加数据库(前面加过了)
代码生成
用的mybatisX
实体类可能需要小修改,需要检查一下
表改成id长度32
加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/guli?serverTimezone=GMT%2B8
username: root
password: 148963
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
cloud:
nacos:
discovery:
server-addr: 192.168.199.100:8848 #服务地址
mybatis-plus:
global-config:
db-config:
id-type: ASSIGN_UUID
相关接口
package com.lkw.cmsservice.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lkw.cmsservice.commonutils.R;
import com.lkw.cmsservice.entity.CrmBanner;
import com.lkw.cmsservice.service.CrmBannerService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 首页banner表 前端控制器
* </p>
*
* @author atguigu
* @since 2020-08-10
*/
@RestController
@RequestMapping("/educms/banneradmin")
@CrossOrigin
public class BannerAdminController {
@Autowired
private CrmBannerService crmBannerService;
//分页查询
@GetMapping()
public R pageBanner(@PathVariable long page, long limit){
Page<CrmBanner> bannerPage = new Page<>(page,limit);
IPage<CrmBanner> pages = crmBannerService.page(bannerPage, null);
List<CrmBanner> records = pages.getRecords();
long total = pages.getTotal();
return R.ok().data("items",records).data("total",total);
}
//添加banner
@PostMapping("addBanner")
public R addBanner(@RequestBody CrmBanner crmBanner){
crmBannerService.save(crmBanner);
return R.ok();
}
//根据id获取Banner
@ApiOperation(value = "获取Banner")
@GetMapping("get/{id}")
public R get(@PathVariable String id) {
CrmBanner banner = crmBannerService.getById(id);
return R.ok().data("item", banner);
}
//修改Banner
@ApiOperation(value = "修改Banner")
@PutMapping("update")
public R updateById(@RequestBody CrmBanner banner) {
crmBannerService.updateById(banner);
return R.ok();
}
//根据id删除Banner
@ApiOperation(value = "删除Banner")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {
crmBannerService.removeById(id);
return R.ok();
}
}
package com.lkw.cmsservice.controller;
import com.lkw.cmsservice.commonutils.R;
import com.lkw.cmsservice.entity.CrmBanner;
import com.lkw.cmsservice.service.CrmBannerService;
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.List;
/**
* <p>
* 首页banner表 前端控制器
* </p>
*
* @author atguigu
* @since 2020-08-10
*/
@RestController
@RequestMapping("/educms/bannerfront")
@CrossOrigin
public class BannerFrontController {
@Autowired
private CrmBannerService crmBannerService;
//查询所有banner
@GetMapping("getAllBanner")
public R getAllBanner(){
List<CrmBanner> List =crmBannerService.selectAllBanner();
return R.ok().data("list",List);
}
}
经典白写
impl
package com.lkw.cmsservice.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lkw.cmsservice.entity.CrmBanner;
import com.lkw.cmsservice.service.CrmBannerService;
import com.lkw.cmsservice.mapper.CrmBannerMapper;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author 李可文
* @description 针对表【crm_banner(首页banner表)】的数据库操作Service实现
* @createDate 2022-11-27 11:54:34
*/
@Transactional
@Service
public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService {
@Cacheable(value = "banner",key = "'selectIndexList'")
//查询所有banner
@Override
public List<CrmBanner> selectAllBanner() {
//根据id降序排列,显示排列之后的前两条记录
QueryWrapper<CrmBanner> bannerQueryWrapper = new QueryWrapper<>();
bannerQueryWrapper.orderByDesc("id");
//list拼接sql语句
bannerQueryWrapper.last("limit 2");
List<CrmBanner> list = baseMapper.selectList(null);
return list;
}
}
last方法
直接拼接到sql的最后
查询热门课程和名师的接口
package com.lkw.eduservice.controller.front;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lkw.cmsservice.commonutils.R;
import com.lkw.eduservice.entity.EduCourse;
import com.lkw.eduservice.entity.EduTeacher;
import com.lkw.eduservice.service.EduCourseService;
import com.lkw.eduservice.service.EduTeacherService;
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.List;
@CrossOrigin
@RestController
@RequestMapping("/eduservice/indexfront")
public class IndexFrontController {
//查询
@Autowired
EduCourseService eduCourseService;
@Autowired
private EduTeacherService eduTeacherService;
//查询前八条记录
@GetMapping("index")
public R index(){
QueryWrapper<EduCourse> courseQueryWrapper = new QueryWrapper<>();
courseQueryWrapper.orderByDesc("id");
courseQueryWrapper.last("limit 8");
List<EduCourse> courseList = eduCourseService.list(courseQueryWrapper);
//查询前四个名师
QueryWrapper<EduTeacher> teacherQueryWrapper = new QueryWrapper<>();
teacherQueryWrapper.orderByDesc("id");
teacherQueryWrapper.last("limit 4");
List<EduTeacher> teacherList = eduTeacherService.list(teacherQueryWrapper);
return R.ok().data("eduList",courseList).data("teacherList",teacherList);
}
}
前端banner
下载axios
封装axios
api
banner.js
import request from '@/utils/request'
export default{
getListBanner() {
return request({
url: 'http://localhost:8004/educms/bannerfront/getAllBanner',
method: 'get'
})
}
}
index.vue
<template>
<div>
<!-- 幻灯片 开始 -->
<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 :href="banner.linkUrl" target="_blank">
<img :src="banner.imageUrl" :alt="banner.title">
</a>
</div>
</div>
<div class="swiper-pagination swiper-pagination-white"/>
<div slot="button-prev" class="swiper-button-prev swiper-button-white"/>
<div slot="button-next" class="swiper-button-next swiper-button-white"/>
</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 id="bna" class="of">
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/01.jpg"
class="img-responsive"
alt="听力口语"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="听力口语" class="course-title fsize18 c-333">听力口语</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<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>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/02.jpg"
class="img-responsive"
alt="Java精品课程"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="Java精品课程" class="course-title fsize18 c-333">Java精品课程</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">501人学习</i>
|
<i class="c-999 f-fA">501评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/03.jpg"
class="img-responsive"
alt="C4D零基础"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="C4D零基础" class="course-title fsize18 c-333">C4D零基础</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">300人学习</i>
|
<i class="c-999 f-fA">300评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/04.jpg"
class="img-responsive"
alt="数学给宝宝带来的兴趣"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="数学给宝宝带来的兴趣" class="course-title fsize18 c-333">数学给宝宝带来的兴趣</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">256人学习</i>
|
<i class="c-999 f-fA">256评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/05.jpg"
class="img-responsive"
alt="零基础入门学习Python课程学习"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a
href="#"
title="零基础入门学习Python课程学习"
class="course-title fsize18 c-333"
>零基础入门学习Python课程学习</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">137人学习</i>
|
<i class="c-999 f-fA">137评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/06.jpg"
class="img-responsive"
alt="MySql从入门到精通"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="MySql从入门到精通" class="course-title fsize18 c-333">MySql从入门到精通</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">125人学习</i>
|
<i class="c-999 f-fA">125评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/07.jpg"
class="img-responsive"
alt="搜索引擎优化技术"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="搜索引擎优化技术" class="course-title fsize18 c-333">搜索引擎优化技术</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">123人学习</i>
|
<i class="c-999 f-fA">123评论</i>
</span>
</section>
</div>
</li>
<li>
<div class="cc-l-wrap">
<section class="course-img">
<img
src="~/assets/photo/course/08.jpg"
class="img-responsive"
alt="20世纪西方音乐"
>
<div class="cc-mask">
<a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a>
</div>
</section>
<h3 class="hLh30 txtOf mt10">
<a href="#" title="20世纪西方音乐" class="course-title fsize18 c-333">20世纪西方音乐</a>
</h3>
<section class="mt10 hLh20 of">
<span class="fr jgTag bg-green">
<i class="c-fff fsize12 f-fA">免费</i>
</span>
<span class="fl jgAttr c-ccc f-fA">
<i class="c-999 f-fA">34人学习</i>
|
<i class="c-999 f-fA">34评论</i>
</span>
</section>
</div>
</li>
</ul>
<div class="clear"/>
</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>
<section class="i-teach-wrap">
<div class="i-teach-pic">
<a href="/teacher/1" title="陈伟霆">
<img alt="陈伟霆" src="~/assets/photo/teacher/04.jpg" width="142">
</a>
</div>
<div class="mt10 hLh30 txtOf tac">
<a href="/teacher/1" title="陈伟霆" class="fsize18 c-666">陈伟霆</a>
</div>
</section>
</li>
<li>
<section class="i-teach-wrap">
<div class="i-teach-pic">
<a href="/teacher/1" title="周润发">
<img alt="周润发" src="~/assets/photo/teacher/01.jpg" width="142">
</a>
</div>
<div class="mt10 hLh30 txtOf tac">
<a href="/teacher/1" title="周润发" class="fsize18 c-666">周润发</a>
</div>
</section>
</li>
<li>
<section class="i-teach-wrap">
<div class="i-teach-pic">
<a href="/teacher/1" title="周杰伦">
<img alt="周杰伦" src="~/assets/photo/teacher/02.jpg" width="142">
</a>
</div>
<div class="mt10 hLh30 txtOf tac">
<a href="/teacher/1" title="周杰伦" class="fsize18 c-666">周杰伦</a>
</div>
</section>
</li>
<li>
<section class="i-teach-wrap">
<div class="i-teach-pic">
<a href="/teacher/1" title="刘德华">
<img alt="刘德华" src="~/assets/photo/teacher/03.jpg" width="142">
</a>
</div>
<div class="mt10 hLh30 txtOf tac">
<a href="/teacher/1" title="刘德华" class="fsize18 c-666">刘德华</a>
</div>
</section>
</li>
</ul>
<div class="clear"/>
</article>
<section class="tac pt20">
<a href="teacher" title="全部讲师" class="comm-btn c-btn-2">全部讲师</a>
</section>
</div>
</section>
</div>
<!-- /网校名师 结束 -->
</div>
</div>
</template>
<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节点
}
},
bannerList: []
}
},
created() {
// 调用查询
banner.getListBanner()
.then(response => {
this.bannerList = response.data.list
})
},
methods: {
// 查询banner数据
}
}
</script>
alt:光标放置显示(相当于名字了)
href:超链接地址
src:地址
启动效果
没有图,可能老师没交钱,我们改改数据库就行
换了数据库之后:
前端好像没加自适应,先不管了
热门课程和名师数据显示
为了加快进度,前端先不自己写了,我在github上直接导入了一个
index.js
import request from '@/utils/request'
export default{
getIndexData() {
return request({
url: 'http://localhost:8001//eduservice/indexfront/index',
method: 'get'
})
}
}
热门课程删掉部分
-
v-for遍历eduList
后端报错要检查nacos配置和nacos有没起来
Redis解放mysql
添加依赖:
<!-- 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>
创建redis配置类到common里
package com.lkw.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)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } }
注解:@cacheable
加到api方法上,
页面调用方法首先查redis ,redis没有再查后面的(mysql之类的)然后放到redis里
注意导报
注意key有两个引号
@Cacheable(value = "banner",key = "'selectIndexList'")
启动redis
连接redis可能的问题:
防火墙没关
配置文件注释掉 #127.0.0.1
修改protected-mode no
yml注释
spring: redis: host: 192.168.199.100 port: 6379 database: 0 timeout: 1800000 password: 123456 lettuce: pool: max-active: 20 max-wait: -1 #最大阻塞时间 max-idle: 5 min-idle: 0
controller不能加这个注解