服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。
服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
另外,使用服务器端渲染,我们可以获得更快的内容到达时间(time-to-content),无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验,对于那些「内容到达时间(time-to-content)与转化率直接相关」的应用程序而言,服务器端渲染(SSR)至关重要。
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
官网网站:
https://zh.nuxtjs.org/
https://github.com/nuxt-community/starter-template/archive/master.zip
将template中的内容复制到 guli
将guli-admin项目下的.eslintrc.js配置文件复制到当前项目下
name、description、author(必须修改这里,否则项目无法安装)
"name": "guli",
"version": "1.0.0",
"description": "谷粒学院前台网站",
"author": "Helen <[email protected]>",
修改title: ‘{{ name }}’、content: ‘{{escape description }}’
这里的设置最后会显示在页面标题栏和meta数据中
head: {
title: '谷粒学院 - Java视频|HTML5视频|前端视频|Python视频|大数据视频-自学拿1万+月薪的IT在线视频课程,谷粉力挺,老学员为你推荐',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'keywords', name: 'keywords', content: '谷粒学院,IT在线视频教程,Java视频,HTML5视频,前端视频,Python视频,大数据视频' },
{ hid: 'description', name: 'description', content: '谷粒学院是国内领先的IT在线视频学习平台、职业教育平台。截止目前,谷粒学院线上、线下学习人次数以万计!会同上百个知名开发团队联合制定的Java、HTML5前端、大数据、Python等视频课程,被广大学习者及IT工程师誉为:业界最适合自学、代码量最大、案例最多、实战性最强、技术最前沿的IT系列视频课程!' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
npm install
npm run dev
(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 应用的个性化配置,以便覆盖默认配置。
npm install vue-awesome-swiper
在 plugins 文件夹下新建文件 nuxt-swiper-plugin.js,内容是
import Vue from 'vue'
import VueAwesomeSwiper from 'vue-awesome-swiper/dist/ssr'
Vue.use(VueAwesomeSwiper)
在 nuxt.config.js 文件中配置插件
将 plugins 和 css节点 复制到 module.exports节点下
module.exports = {
// some nuxt config...
plugins: [
{ src: '~/plugins/nuxt-swiper-plugin.js', ssr: false }
],
css: [
'swiper/dist/css/swiper.css'
]
}
将静态原型中的css、img、js、photo目录拷贝至assets目录下
将favicon.ico复制到static目录下
我们可以把页头和页尾提取出来,形成布局页
修改layouts目录下default.vue,从静态页面中复制首页,修改了原始文件中的资源路径为~/assets/,将主内容区域的内容替换成
内容如下:
完整的内容如下
(不包含幻灯片)
修改pages/index.vue:
修改了原始文件中的资源路径为~/assets/
内容如下:
热门课程
名师大咖
-
北京师范大学法学院副教授
北京师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。
-
资深课程设计专家,专注10年AACTP美国培训协会认证导师
十年课程研发和培训咨询经验,曾任国企人力资源经理、大型外企培训经理,负责企业大学和培训体系搭建;曾任专业培训机构高级顾问、研发部总监,为包括广东移动、东莞移动、深圳移动、南方电网、工商银行、农业银行、民生银行、邮储银行、TCL集团、清华大学继续教育学院、中天路桥、广西扬翔股份等超过200家企业提供过培训与咨询服务,并担任近50个大型项目的总负责人。
-
上海师范大学法学院副教授
上海师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。
-
考研政治辅导实战派专家,全国考研政治命题研究组核心成员。
法学博士,北京师范大学马克思主义学院副教授,长期从事考研辅导。出版著作两部,发表学术论文30余篇,主持国家社会科学基金项目和教育部重大课题子课题各一项,参与中央实施马克思主义理论研究和建设工程项目。
全部讲师
script
(1)使用router-link构建路由,地址是/course
(2)在page目录创建文件夹course ,在course目录创建index.vue
课程列表
如果我们需要根据id查询一条记录,就需要使用动态路由。NUXT的动态路由是以下划线开头的vue文件,参数名为下划线后边的文件名
在pages下的course目录下创建_id.vue
讲师详情
我们可以参考guli-admin将axios操作封装起来
下载axios ,使用命令 npm install axios
创建utils文件夹,utils下创建request.js
import axios from 'axios'
// 创建axios实例
const service = axios.create({
baseURL: 'http://localhost:8201', // api的base_url
timeout: 20000 // 请求超时时间
})
export default service
创建 pages/teacher/index.vue
全部讲师
全部
没有相关数据,小编正在努力整理中...
-
北京师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。
北京师范大学法学院副教授
-
十年课程研发和培训咨询经验,曾任国企人力资源经理、大型外企培训经理,负责企业大学和培训体系搭建;曾任专业培训机构高级顾问、研发部总监,为包括广东移动、东莞移动、深圳移动、南方电网、工商银行、农业银行、民生银行、邮储银行、TCL集团、清华大学继续教育学院、中天路桥、广西扬翔股份等超过200家企业提供过培训与咨询服务,并担任近50个大型项目的总负责人。
资深课程设计专家,专注10年AACTP美国培训协会认证导师
-
上海师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。
上海师范大学法学院副教授
-
法学博士,北京师范大学马克思主义学院副教授,长期从事考研辅导。出版著作两部,发表学术论文30余篇,主持国家社会科学基金项目和教育部重大课题子课题各一项,参与中央实施马克思主义理论研究和建设工程项目。
考研政治辅导实战派专家,全国考研政治命题研究组核心成员。
-
具备深厚的数学思维功底、丰富的小学教育经验,授课风格生动活泼,擅长用形象生动的比喻帮助理解、简单易懂的语言讲解难题,深受学生喜欢
毕业于师范大学数学系,热爱教育事业,执教数学思维6年有余
-
中国科学院数学与系统科学研究院应用数学专业博士,研究方向为数字图像处理,中国工业与应用数学学会会员。参与全国教育科学“十五”规划重点课题“信息化进程中的教育技术发展研究”的子课题“基与课程改革的资源开发与应用”,以及全国“十五”科研规划全国重点项目“掌上型信息技术产品在教学中的运用和开发研究”的子课题“用技术学数学”。
中国人民大学附属中学数学一级教师
-
中教一级职称。讲课极具亲和力。
毕业于北京大学数学系
-
政治学博士、管理学博士后,北京师范大学马克思主义学院副教授。多年来总结出了一套行之有效的应试技巧与答题方法,针对性和实用性极强,能帮助考生在轻松中应考,在激励的竞争中取得高分,脱颖而出。
长期从事考研政治课讲授和考研命题趋势与应试对策研究。考研辅导新锐派的代表。
创建 pages/teacher/_id.vue
修改资源路径为~/assets/
讲师介绍
姚晨 高级讲师
北京师范大学法学院副教授
北京师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。
创建 pages/course/index.vue
全部课程
没有相关数据,小编正在努力整理中...
-
-
-
-
-
-
-
-
创建 pages/course/_id.vue
首页
\
课程列表
\
Java精品课程
课程介绍
Java的发展历史,可追溯到1990年。当时Sun Microsystem公司为了发展消费性电子产品而进行了一个名为Green的项目计划。该计划
负责人是James Gosling。起初他以C++来写一种内嵌式软件,可以放在烤面包机或PAD等小型电子消费设备里,使得机器更聪明,具有人工智
能。但他发现C++并不适合完成这类任务!因为C++常会有使系统失效的程序错误,尤其是内存管理,需要程序设计师记录并管理内存资源。这给设计师们造成
极大的负担,并可能产生许多bugs。
为了解决所遇到的问题,Gosling决定要发展一种新的语言,来解决C++的潜在性危险问题,这个语言名叫Oak。Oak是一种可移植性语言,也就是一种平台独立语言,能够在各种芯片上运行。
1994年,Oak技术日趋成熟,这时网络正开始蓬勃发展。Oak研发小组发现Oak很适合作为一种网络程序语言。因此发展了一个能与Oak配合的浏
览器--WebRunner,后更名为HotJava,它证明了Oak是一种能在网络上发展的程序语言。由于Oak商标已被注册,工程师们便想到以自己常
享用的咖啡(Java)来重新命名,并于Sun World 95中被发表出来。
课程大纲
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=root
#返回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
创建CmsApplication.java
@SpringBootApplication
@ComponentScan({"com.atguigu"}) //指定扫描位置
@MapperScan("com.atguigu.cmsservice.mapper")
public class CmsApplication {
public static void main(String[] args) {
SpringApplication.run(CmsApplication.class, args);
}
}
banner后台分页查询、添加、修改、删除接口
@RestController
@RequestMapping("/eduservice/banner")
@CrossOrigin
public class CrmBannerController {
@Autowired
private CrmBannerService bannerService;
@ApiOperation(value = "获取Banner分页列表")
@GetMapping("{page}/{limit}")
public R index(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit) {
Page pageParam = new Page<>(page, limit);
bannerService.pageBanner(pageParam,null);
return R.ok().data("items", pageParam.getRecords()).data("total", pageParam.getTotal());
}
@ApiOperation(value = "获取Banner")
@GetMapping("get/{id}")
public R get(@PathVariable String id) {
CrmBanner banner = bannerService.getBannerById(id);
return R.ok().data("item", banner);
}
@ApiOperation(value = "新增Banner")
@PostMapping("save")
public R save(@RequestBody CrmBanner banner) {
bannerService.saveBanner(banner);
return R.ok();
}
@ApiOperation(value = "修改Banner")
@PutMapping("update")
public R updateById(@RequestBody CrmBanner banner) {
bannerService.updateBannerById(banner);
return R.ok();
}
@ApiOperation(value = "删除Banner")
@DeleteMapping("remove/{id}")
public R remove(@PathVariable String id) {
bannerService.removeBannerById(id);
return R.ok();
}
}
首页获取banner数据接口
@RestController
@RequestMapping("/educms/banner")
@Api(description = "网站首页Banner列表")
@CrossOrigin //跨域
public class BannerApiController {
@Autowired
private CrmBannerService bannerService;
@ApiOperation(value = "获取首页banner")
@GetMapping("getAllBanner")
public R index() {
List list = bannerService.selectIndexList();
return R.ok().data("bannerList", list);
}
}
实现banner后台的添加修改删除和分页查询操作,和其他后台管理模块类似
(1)查询最新前4条讲师数据
(2)查询最新前8条课程数据
@RestController
@RequestMapping("/eduservice/index")
@CrossOrigin
public class IndexController {
@Autowired
private EduCourseService courseService;
@Autowired
private EduTeacherService teacherService;
//查询前8条热门课程,查询前4条名师
@GetMapping("index")
public R index() {
//查询前8条热门课程
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
wrapper.last("limit 8");
List eduList = courseService.list(wrapper);
//查询前4条名师
QueryWrapper wrapperTeacher = new QueryWrapper<>();
wrapperTeacher.orderByDesc("id");
wrapperTeacher.last("limit 4");
List teacherList = teacherService.list(wrapperTeacher);
return R.ok().data("eduList",eduList).data("teacherList",teacherList);
}
}
banner.js
import request from '@/utils/request'
export default {
getList() {
return request({
url: `/educms/banner/getAllBanner`,
method: 'get'
})
}
}
index.js
import request from '@/utils/request'
export default {
getList() {
return request({
url: `/eduservice/index`,
method: 'get'
})
}
}
热门课程
名师大咖
-
{{teacher.intro}}
{{teacher.career}}
全部讲师
08-首页数据添加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下添加以下依赖
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.6.0
2、在service-base模块添加redis配置类
RedisConfig.java
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate<>();
RedisSerializer 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 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接口,首页课程与讲师接口类似
3.1 Spring Boot 缓存注解
(1)缓存@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
查看源码,属性值如下:
属性/方法名
解释
value
缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames
与 value 差不多,二选一即可
key
可选属性,可以使用 SpEL 标签自定义缓存的key
(2)缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
查看源码,属性值如下:
属性/方法名
解释
value
缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames
与 value 差不多,二选一即可
key
可选属性,可以使用 SpEL 标签自定义缓存的key
(3)缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
查看源码,属性值如下:
属性/方法名
解释
value
缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames
与 value 差不多,二选一即可
key
可选属性,可以使用 SpEL 标签自定义缓存的key
allEntries
是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存
beforeInvocation
是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存
3.2 启动redis服务
3.3连接redis服务可能遇到的问题
(1)关闭liunx防火墙
(2)找到redis配置文件, 注释一行配置
(3)如果出现下面错误提示
修改 protected-mode yes改为protected-mode no
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.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
(2)修改CrmBannerServiceImpl,添加redis缓存注解
@Service
public class CrmBannerServiceImpl extends ServiceImpl implements CrmBannerService {
@Cacheable(value = "banner", key = "'selectIndexList'")
@Override
public List selectIndexList() {
List list = baseMapper.selectList(new QueryWrapper().orderByDesc("sort"));
return list;
}
@Override
public void pageBanner(Page 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(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);
}
}
(3)在redis添加了key
(4)通过源码查看到key生成的规则