项目的再复习
@RequestBody的用法
对@RequestBody的用法讲解得很详细,通俗易懂。前端传送json数据到后端,请求数据都放到请求体,不需要指定参数名,后端用@RequestBody接收请求体数据封装到实体类中
前后端分离的crud
就是vue使用MVVM
Model view viewmodel
数据进行双向绑定,所以vue向后端发送请求的时候就直接,使用data中的双向绑定的数据,
后端使用**@requestbody注解**(对@RequestBody的用法讲解得很详细,通俗易懂。前端传送json数据到后端,请求数据都放到请求体,不需要指定参数名,后端用@RequestBody接收请求体数据封装到实体类中)
后端拿到这个实体类,如果和自己的实体一样,就进行直接进行数据库操作,如果和自己的不一样使用BeanUtils.copyProperties(eduVideo, video);进行赋值,既然再操作数据库去
easyExcel
课程分类的导入
使用easy excel,一行一行进行添加,首先,判断Excel表中有没有数据?有数据的话进行读取每一行数据
Excel中一行有两列数据,第一列是一级标题,第二列是二级标题
查询是否存在一级标题,返回一个EduSubject对象,如果有就获取一下ID作为二级标题的父ID, 如果没有的话,就进行添加一级标题,并把父ID设为零,并把一级标题进行存储
判断是否存在二级标题,如果存在就不添加,如果不存在就进行添加,并拿上面获取到的一级标题自动生成的ID作为自己的父ID,并把二级标题进行存储
// 在数据库中,我们的一级标题和二级标题 都是一行数据
public void invoke(ExcelSubjectData user, AnalysisContext analysisContext) {
// 首先从excel中读取一级标题和二级标题,标题不可以重复
// 开始根据excel中的数据开始写入数据库
// 1:如果表中没有数据结束
if (user == null) {
throw new GuliException(20001, "excel中没有数据,添加失败");
}
// 添加一级分类,判断是否存在一级标题
EduSubject existOneSubject = this.existOneTitle(subjectService, user.getOneSubjectName());
// 没有这个一级标题,所以直接进行保存就可以
if (existOneSubject == null) {
existOneSubject = new EduSubject();
existOneSubject.setTitle(user.getOneSubjectName());
existOneSubject.setParentId("0");
subjectService.save(existOneSubject);
}
// 获取一级标题的id,判断是否存在二级标题
String parentId = existOneSubject.getId();
// 添加二级分类
EduSubject existTwoSubject = this.existTwoTitle(subjectService, user.getTwoSubjectName(), parentId);
if (existTwoSubject == null) {
existTwoSubject = new EduSubject();
existTwoSubject.setTitle(user.getTwoSubjectName());
existTwoSubject.setParentId(parentId);
subjectService.save(existTwoSubject);
}
}
课程分类的标题的显示
查出一级标题,查出二级标题,根据父ID是否为零区分这两个标题
数据库中查到,这两个一级标题和二级标题,首先创造一个大的数组来存放所有一级标题,因为二级标题都放在一级标题实体类的属性list数组中
开始两个for循环遍历把一级标题和二级标题都进行存储,返回最后大数组
第一个for循环进行,存储一级标题,在每一个一级标题中,我们根据此次ID来遍历所有二级标题,如果二级标题的服ID等于此次标题,ID
把这个放到一个数组中
店里完所有二级标题之后,把这个数组,放到这个一级标题ID的属性list中
最后,返回大数组
// 把数据库的数据渲染到页面中
@Override
public List<SubjectNestedVo> nestedList() {
// 查出一级目录
QueryWrapper<EduSubject> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("parent_id","0");
List<EduSubject> oneSubjects = baseMapper.selectList(queryWrapper1);
// 查出二级目录
QueryWrapper<EduSubject> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.ne("parent_id","0");
List<EduSubject> twoSubjects = baseMapper.selectList(queryWrapper2);
// 有了一级目录和二级目录,进行返回ui中需要格式的数据
// 就是我们把这(EduSubject),转化成真正的:一级目录一级目录
ArrayList<SubjectNestedVo> totalData = new ArrayList<>();
for (int i = 0; i < oneSubjects.size(); i++) {
// 数据库中的EduSubject,提取id和title给vo赋值
SubjectNestedVo subjectNestedVo = new SubjectNestedVo();
EduSubject oneSubject = oneSubjects.get(i);
// 一级目录赋值给自己的实体类
BeanUtils.copyProperties(oneSubject,subjectNestedVo);
// 开始二级目录的赋值
ArrayList<SubjectVo> subjectVos = new ArrayList<>();
for (int m = 0; m < twoSubjects.size(); m++) {
EduSubject twoSubject = twoSubjects.get(m);
// 判断二级标题的parent_id是否是一级标题的id
if (oneSubject.getId().equals(twoSubject.getParentId())){
// 匹配成功的时候再创建对象,进行赋值
SubjectVo subjectVo = new SubjectVo();
BeanUtils.copyProperties(twoSubject,subjectVo);
// 存储到一个集合中,形成一个孩子
subjectVos.add(subjectVo);
}
}
// 如果是对应的,就添加到一级标题中
subjectNestedVo.setChildren(subjectVos);
totalData.add(subjectNestedVo);
}
return totalData;
}
章节和小节(同上课程类型)
就像章节中有小杰,这种表是一对多的关系,因为数据库字段装不会有这个概念,所以我们创建一个自己的vo实体类,让这个实体类中包含小结list集合,
然后从数据库中查出,根据该课程courseId的所有章节和小节,
然后用一个大的数组来存储这个章节信息
外面for循环遍历章节,里面缝循环遍历小结
外层缝循环遍历出来的章节信息存到大数组中,然后获取for循环中第i个章节的ID,用这个ID和所有小节进行匹配
符合条件的小节存入到一个list集合中
最后吧这个list保存到章节的list属性中
两个for循环遍历结束,返回大数组
//要根据课程id查询所有小节,所以把小节service注入进来
@Autowired
EduVideoService eduVideoService;
public List<ChapterVo> nestedList(String courseId) {
// 存放返回的信息
ArrayList<ChapterVo> totalData = new ArrayList<>();
// 查询章节
QueryWrapper<EduChapter> chapterQueryWrapper = new QueryWrapper<>();
chapterQueryWrapper.eq("course_id", courseId);
// this.list是mybatis-plus自带的方法,查询返回一个列表
List<EduChapter> eduChapters = this.list(chapterQueryWrapper);
// 查询小节
QueryWrapper<EduVideo> eduVideoQueryWrapper = new QueryWrapper<>();
eduVideoQueryWrapper.eq("course_id", courseId);
List<EduVideo> eduVideos = eduVideoService.list(eduVideoQueryWrapper);
for (int i = 0; i < eduChapters.size(); i++) {
// 把数据库中的信息,转化成我们页面想要的信息
ChapterVo chapterVo = new ChapterVo();
EduChapter eduChapter = eduChapters.get(i);
BeanUtils.copyProperties(eduChapter, chapterVo);
// 添加到总数组中
totalData.add(chapterVo);
String pId = eduChapter.getId();
ArrayList<VideoVo> videoVos = new ArrayList<>();
for (int m = 0; m < eduVideos.size(); m++) {
EduVideo eduVideo = eduVideos.get(m);
if (eduVideo.getChapterId().equals(pId)) {
VideoVo videoVo = new VideoVo();
BeanUtils.copyProperties(eduVideo, videoVo);
videoVos.add(videoVo);
}
}
chapterVo.setChildren(videoVos);
}
return totalData;
}
项目中一对多的应用
每一课程章节和小节
课程分类中的一级标题和二级标题
项目核心-课程
- 课程相关使用到的表
课程中包括讲师,一级标题,二级标题
根据课程ID我们又可以,获取每一个章节和小节
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0OBm22nB-1656112893429)(C:\Users\小盖\AppData\Roaming\Typora\typora-user-images\image-20220624214447690.png)]
-
课程和课程描述我们是分开两个表来写的,就是在对课程增删改的时候,都添加上这个课程描述表的操作
-
课程中手写sql
课程模块自己手写SQL
课程发布的时候显示信息需要多个表,像老师,课程分类,需要不同表的信息,我们使用,自己手写的sql进行显示
显示课程详情信息的时候,我们这里也使用到了手写SQL
订单模块
在生成订单这个模块,我们使用feignclient来调用其他模块(openfeign)
调用用户信息和,课程信息因为生成订单的时候需要用户和相关课程的信息
VOD 模块是
一个是视频点播
一个是视频的增删改查
第一面
==和equals
list集合都有哪些
- ArrayList,查询遍历
- linklist,插入删除
- stack,先进先出
mybati和mybatis-plus使用感受和异同
线程和进程了解吗
spring-boot和spring-cloud使用感受
spring-cloud中用的组件
vue和bootstrap的使用感受
使用js
前端向后端发请求的话用的什么技术
mysql索引
redis的优点
第二面
- 基本数据类型,8种各占多少字节,要求精度用哪个,是否使用过bigdecimal
一字节是8位
一般整型取值范围是分为有符号取值和无符号取值两种,有符号取值就把第一位取为符号位,无符号取值默认为大于等于0的整数。
例如:int 占4字节,一字节是8位,总共就是32位,它的有符号取值范围就是-2^31^ ~ 2^31^-1 无符号取值为0 ~ 2^32^-1
整型:byte(字节型,占1字节)、short(短整型,占2字节)、int(整型,占4字节)、long(长整型,占8字节)
浮点型:float(单精度浮点数,占4字节)、double(双精度浮点数,占8字节)
注:Java浮点数默认类型是double,float浮点数后缀为F(或f)
布尔型:boolean(布尔型),只有true 和false两个取值
字符型:char(字符型,占2个字节)
注:因字符类型表示Unicode字符,所以一个字符占2字节
-
接口和抽象类的区别
-
redis,功能及应用场景
-
nginx功能:反向代理、负载均衡、动静分离。
正向代理和反向代理
A找C买房,即A——>C这个方向是正向,那么C——>A就是反向。
如果A是不固定的,C是固定的,即房源只有一套。B是为卖房者代理,这里的B就是反向代理。
如果A是固定的,即只有一个顾客,C是不固定的,有若干套房源。B为买房者代理,这里的B就是正向代理。
- sql语句,having group查询实际案例
//秋季学期有2门以上课程获90分以上成绩的学生名
select distinct sname from student,sc,course
where student.sno=sc.sno and course.cno=sc.cno
and grade>=90 and semester='秋'
group by student.sno having count(*)>=2
- Linux下,在很多文件中查出有特殊字符串的文件的指令
- Linux下查询进程
- Nosql优点
- 你的登录亮点,项目式如何登录的?
- 项目的前端是用什么启动的?node.js
- 注册中心是干什么用的?
- 线程池的好处
- Spring mvc执行流程
- mybatis使用
- Static,关键字
- 冒泡排序和递归怎么写?
- 单例模式怎么写?
- 使用过Bigdecimal吗?
- 一个的类加载顺序,累的各个变量创建顺序
- 如何创建线程?
- 面向对象五大原则
- 谈谈你对Ioc,aop的理解
- 谈谈你对堆栈的理解
- Static,在修饰方法或者累的时候或者变量的时候都有什么效果?
- final和finally的区别
- 你常用的linux指令
- 你项目中-前端向后端发送请求的时候是发送的什么请求
asiox
axios是ajax的封装
a.从浏览器中创建 XMLHttpRequest
b.从 node.js 发出 http 请求
c.支持 Promise API
e.拦截请求和响应
f.转换请求和响应数据
g.取消请求
h.自动转换JSON数据
- 常见的set和常见的map和常见的list