添加课程基本信息
添加课程信息后端
1、使用代码生成器生成课程相关的代码
2、
细节问题:
-
创建vo实体类用于表单数据封装
-
把表单提交过来的数据添加数据库
向两张表添加数据:课程表和课程描述表
-
把讲师和分类使用下列列表显示
课程分类 做成二级联动效果
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
@Autowired
private EduCourseDescriptionService courseDescriptionService;
//添加课程基本信息的方法
@Override
public void saveCourseInfo(CourseInfoVo courseInfoVo) {
// 向课程表添加课程基本信息
//CourseInfoVo对象转换eduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo, eduCourse);
int insert = baseMapper.insert(eduCourse);
if (insert == 0){
//添加失败
throw new GuliException(20001,"添加课程信息失败");
}
//获取添加之后课程id
String cid = eduCourse.getId();
// 向课程简介表添加课程简介
EduCourseDescription courseDescription = new EduCourseDescription();
courseDescription.setDescription(courseInfoVo.getDescription());
//设置描述id就是课程id
courseDescription.setId(cid);
courseDescriptionService.save(courseDescription);
}
}
更改描述里面的策略:
添加课程信息前端
1、对菜单栏的内容进行增加
2、新建对应的页面并完善其内容
3、连接后端
细节问题:
添加之后,返回课程id
整合文本编辑器
1、复制文本编辑器组件,相关组件进行复制到项目里面
2、配置html变量
3、在index.html引入Js脚本
4、在页面使用文本编辑器
课程大纲列表
1、创建两个实体类:章节和小节,在章节实体类使用list表示小节
类似于上一节
修改课程信息
前端内容:
后端:
//修改课程信息
@Override
public void updateCourseInfo(CourseInfoVo courseInfoVo) {
//修改课程表
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoVo,eduCourse);
int update = baseMapper.updateById(eduCourse);
if (update == 0){
throw new GuliException(20001,"修改课程信息失败");
}
//修改描述表
EduCourseDescription description = new EduCourseDescription();
description.setId(courseInfoVo.getId());
description.setDescription(courseInfoVo.getDescription());
courseDescriptionService.updateById(description);
}
删除课程信息
按钮已经有,后端也实现了,等项目做完需要将连上前端
阿里云视频
API:阿里云提供固定的地址,只需要调用这个固定的地址,向地址传递参数,实现功能
SDK:sdk对api方式进行封装,更方便使用。之前使用EasyExcel调用阿里云提供类或者接口里面的方法实现视频功能
阿里云视频点播SDK
1、获取视频播放地址
因为上传视频可以进行加密,加密之后,使用加密之后地址不能进行视频播放,在数据库存储不存地址,而是存储
根据视频id获取视频播放地址:
public class TestVod {
public static void main(String[] args) throws Exception{
//1 根据视频的ID获取视频播放地址
// 创建初始化对象
DefaultAcsClient client = InitObject.initVodClient("LTAI5tR617LEVVNgxTPz8dDk","AEcqAHfCr3ergCtyRCumbGso42pnJ3");
// 创建获取视频地址request和response
GetPlayInfoRequest request = new GetPlayInfoRequest();
GetPlayInfoResponse response = new GetPlayInfoResponse();
// 向request对象里面设置视频id
request.setVideoId("fb75ed5eb8d440899bb551d15dc03d8e");
// 使用初始化对象里面的方法,传递request,获取数据
response = client.getAcsResponse(request);
List<GetPlayInfoResponse.PlayInfo> playInfoList = response.getPlayInfoList();
//播放地址
for (GetPlayInfoResponse.PlayInfo playInfo : playInfoList) {
System.out.print("PlayInfo.PlayURL = " + playInfo.getPlayURL() + "\n");
}
//Base信息
System.out.print("VideoBase.Title = " + response.getVideoBase().getTitle() + "\n");
}
}
2、获取视频播放凭证
public static void getPlayAuth() throws Exception{
//根据视频Id获取视频播放凭证
//创建初始化对象
DefaultAcsClient client = InitObject.initVodClient("LTAI5tR617LEVVNgxTPz8dDk","AEcqAHfCr3ergCtyRCumbGso42pnJ3");
//创建获取视频凭证request和response
GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
GetVideoPlayAuthResponse response = new GetVideoPlayAuthResponse();
//向request中设置视频id
request.setVideoId("fb75ed5eb8d440899bb551d15dc03d8e");
//调用初始化对象的方法得到凭证
response = client.getAcsResponse(request);
System.out.println("playauth:" +response.getPlayAuth());
}
3、上传视频到阿里云视频点播服务
在之前引入jar包时,aliyun-java-vod-upload-1.4.11.jar的导入出错,所以我用了1.4.14版本的,原因是这个包不是开源的,不能通过maven仓库下载。。
但是使用1.4.14版本官网说明如下,还需要更改oss包的版本,不然不兼容
下载了1.4.11的版本,但是还是报错
把官网中的需要的xml依赖复制过来,就可以运行了。。
测试成功
整合前端 视频上传
上传视频时,数据库里的video_source_id为空
删除视频
后端接口:
//根据视频id删除阿里云视频
@DeleteMapping("removeAlyVideo/{id}")
public R removeAlyVideo(@PathVariable String id){
try{
//初始化对象
DefaultAcsClient client = InitVodClient.initVodClient(
ConstantVodUtils.ACCESS_KEY_ID,
ConstantVodUtils.ACCESS_KEY_SECRET);
//创建删除视频的request对象
DeleteVideoRequest request = new DeleteVideoRequest();
//向request设置视频id
request.setVideoIds(id);
//调用初始化对象的方法实现删除
client.getAcsResponse(request);
return R.ok();
}catch (Exception e){
e.printStackTrace();
throw new GuliException(20001,"删除视频失败");
}
}
nacos配置
1、安装并启动nacos
使用docker安装nacos
docker run --env MODE=standalone --name mynacos -d -p 8848:8848 docker.io/nacos/nacos-server:1.3.1
2、在需要配置服务的配置文件中
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=192.168.1.118:8848
3、在其主启动类上加上注解
@EnableDiscoveryClient
4、在nacos中查看是否注册成功
删除小节和删除视频
把互相调用的服务(service-edu和service-vod)在nacos中进行注册
1、引入依赖在service模块
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在调用端service-edu服务启动类添加注解
@EnableFeignClients
3、在调用端 创建interface,使用注解指定调用服务名称,定义调用的方法路径
SpringCloud调用接口流程
熔断机制的使用
1、添加熔断器依赖
<!--hystrix依赖,主要是用 @HystrixCommand -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、在调用端配置文件中开启熔断器
#开启熔断机制
feign.hystrix.enabled=true
# 设置hystrix超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
3、在创建Interface之后,还需要创建interface对应实现类,在实现类实现方法,出错了输出内容
@Component
public class VodFileDegradeFeignClient implements VodClient {
//出错之后会执行
@Override
public R removeAlyVideo(String id) {
return R.error().message("删除视频出错了");
}
@Override
public R deleteBatch(List<String> videoList) {
return R.error().message("删除多个视频出错了");
}
}
4、在Interface上面添加注释和属性
@Component
@FeignClient(name = "service-vod",fallback = VodFileDegradeFeignClient.class) //调用的服务名称
public interface VodClient {
...
}
搭建项目前台环境
服务端渲染
服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。
服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
另外,使用服务器端渲染,我们可以获得更快的内容到达时间(time-to-content),无需等待所有的JavaScript 都完成下载并执行,产生更好的用户体验,对于那些「内容到达时间(time-to-content)与转化率直接相关」的应用程序而言,服务器端渲染(SSR)至关重要。
什么是NUXT
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
NUXT目录结构
整合项目首页面
固定路由:路径是固定的
动态路由:
创建方式:
如果我们需要根据id查询一条记录,就需要使用动态路由,NUXT的动态路由是以下划线开头的vue文件,参数名为下划线后边的文件名
首页数据banner接口
@Service
public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService {
//查询所有的banner
@Override
public List<CrmBanner> selectAllBanner() {
//根据id进行降序排列,只显示前2条记录
QueryWrapper<CrmBanner> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
//last方法,拼接sql语句
wrapper.last("limit 2");
List<CrmBanner> list = baseMapper.selectList(null);
return list;
}
}
整合Redis
Redis特点:
1、基于key-value进行存储的
2、支持多种数据结构:string、list、hash、set、zset
3、支持持久化,通过内存进行存储的,也可以存到硬盘里面
4、支持过期时间,支持事务
一般来说,把经常进行查询,不经常修改的,不是特别重要的数据放到redis作为缓存
整合步骤:
1、引入相关依赖
<!-- 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、配置类
@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))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
3、在查询所有Banner的方法上面添加缓存注释 @Cacheable
第一次查询:首先查询数据库,把数据库查询的数据返回,并且返回数据放到缓存中
第二次查询:查询缓存,发现缓存有数据,直接返回
4、启动redis服务
使用docker安装的redis,配置文件容器里没有,需要添加映射
- 创建docker统一的外部配置文件
mkdir -p docker/redis/{conf,data}
- 在conf目录创建redis.conf的配置文件
touch /docker/redis/conf/redis.conf
- 更改配置文件redis.conf,将其中的内容更改
#bind
#127.0.0.1
deemonize no #daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes
- 创建启动容器,加载配置文件并持久化数据
docker run -d --privileged=true -p 6379:6379 -v /docker/redis/conf/redis.conf:/etc/redis/redis.conf -v /docker/redis/data:/data --name redis-test redis redis-server /etc/redis/redis.conf --appendonly yes
- 使用redis-cli命令启动
- 启动前端,使用相关命令可以得到
登录实现
单点登录
单点登录三种常见方式:
1、session广播机制实现 session复制到每个模块中
2、使用cookie + redis实现
-
在项目中任何一个模块进行登录,登录之后,把数据放到两个地方
-
redis:在key中生成唯一随机值(ip,用户id等) 在value生成用户数据
-
cookie:把redis里面生成key值放到cookie里面
-
-
访问项目中其他模块,发送请求带着cookie进行发送、获取cookie值,拿着cookie做事情,把cookie获取值,到redis进行查询,根据key进行查询,如果可以获取到数据就是登录。
3、使用token实现
token是按照一定规则生成的字符串,字符串可以包含用户信息
- 在项目某个模块进行登录,登录之后,按照规则生成字符串,把登录之后用户包含到生成字符串里面,把字符串返回
- 可以把字符串通过cookie返回
- 把字符串通过地址栏返回
- 再去访问项目其他模块,每次返回在地址栏带着生成字符串,在访问模块里面获取地址栏字符串,根据字符串获取用户信息。如果可以获取到就是登录
JWT:
JWT就是给我们规定好了规则,使用jwt规则可以生成字符串,包含用户信息
JWT生成字符串包含三部分:
第一部分:jwt头信息
第二部分:有效载荷 包含主题信息(用户信息)
第三部分:签名哈希 防伪标志
邮箱验证
因为现在阿里云的短信服务不能使用,所以改为邮箱验证
所需要的依赖:
<dependencies>
<dependency>
<groupId >com.sun.mail</groupId >
<artifactId >javax.mail</artifactId >
<version >1.5.4</version >
</dependency>
<dependency >
<groupId >javax.mail</groupId >
<artifactId >mail</artifactId >
<version >1.4.5</version >
</dependency>
</dependencies>
待完工。
Oauth2
分布式登录:
1、登录成功后,按照一定的规则生成字符串,字符串包含用户信息
2、把生成字符串通过路径传递,或者cookie
3、后面再发送请求时长,每次带着字符串进行发送,获取字符串,从字符串获取用户信息登录
Oauth2解决方案:
令牌机制,按照一定规则生成字符串,字符串包含用户信息