谷粒学院16万字笔记+1600张配图(十)——课程管理
项目源码与所需资料
链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59
提取码:8z59
文章目录
- demo10-课程管理
- 1.课程信息确认后端
- 1.1分析
- 1.2多表连接查询
- 1.2.1多表查询的三种方式
- 1.2.2我们应该用哪种方式
- 1.3创建vo类
- 1.4持久层
- 1.4.1在mapper中定义方法
- 1.4.2在idea中连接数据库
- 1.4.3编写映射
- 1.5控制层
- 1.6业务层接口
- 1.7业务层实现类
- 1.8测试
- 1.9加载问题
- 1.9.1分析问题
- 1.9.2解决问题
- 1.9.3再次测试
- 2.课程信息确认前端
- 2.1在api中定义方法
- 2.2获取路径中的课程id
- 2.3调用api中的方法
- 2.4初始化页面
- 2.5将内容显示到页面上
- 2.6测试
- 3.课程最终发布后端
- 3.1分析
- 3.2控制层
- 4.课程最终发布前端
- 4.1在api中定义方法
- 4.2调用api中的方法
- 4.3测试
- 5.课程列表后端
- 5.1分析
- 5.2控制层
- 6.课程列表前端
- 6.1在api中定义方法
- 6.2编写list.vue页面
- 6.3测试
- 7.课程删除后端
- 7.1分析
- 7.2控制层
- 7.3业务层接口
- 7.4业务层实现类
- 7.5编写removeVideoByCourseId方法
- 7.6编写removeChapterByCourseId方法
- 7.7疑问
- 7.8测试
- 8.课程删除前端
- 8.1在api中定义方法
- 8.2绑定事件
- 8.3调用api中的方法
- 8.4测试
demo10-课程管理
1.课程信息确认后端
1.1分析
1.课程信息确认页面会显示课程名称、课程价格、课程简介、课程所属分类、课程所属讲师等等…我们要从数据表中查询这些信息,其中从edu_course表查询课程名称、课程价格;从edu_course_description表查询课程简介;从edu_subject表查询课程所属分类;从edu_teacher表查询课程所属讲师。这些数据并没有在一张数据表中,我们应该怎么解决呢?在"demo09-课程管理"的"3.1.3业务层实现类"中我们的做法是:分别查询这两张表,然后将查询到的数据封装到一个VO实体类中。此时我们也可以通过分别查询这几张数据表并封装数据来实现需求,但是在"demo09-课程管理"的"3.1.3业务层实现类"中只涉及到两张数据表,而我们此时涉及到的数据表太多了,所以不建议这样做
2.建议通过手写sql语句来实现
1.2多表连接查询
1.2.1多表查询的三种方式
假如左边的数据表是课程一级分类表,右边的数据表是课程二级分类表,且右边的表的第三列存放的是课程一级分类的id
- 内连接
- 查询的两张表有关联的数据就叫做内连接
- 那么查询上图中的两张表,就会查询出来四条数据:前端、后端、Java、vue
- 左外连接
- 查询时将查询左边表的所有数据,查询右边表时只查询和左边表有关联的数据
- 那么查询上图中的两张表,就会查询出来五条数据:前端、后端、运维、Java、vue
- 右外连接
- 查询时将查询右边表的所有数据,查询左边表时只查询和右边表有关联的数据,实际上就是左外连接反过来呗
- 那么查询上图中的两张表,就会查询出来五条数据:前端、后端、Java、vue、mysql
1.2.2我们应该用哪种方式
1.实际开发中我们经常用内连接和左外连接,右外连接用的不多。我们此时用内连接可以吗?当然可以,但是我们某一门课可能会没有简介,所以用内连接不太合适,所以我们这里使用左外连接查询
2.在数据库编写如下sql命令
SELECT ec.id,ec.title,ec.price,ec.lesson_num,ecd.description,et.name,es1.title AS oneSubject,es2.title AS twoSubject
FROM edu_course ec LEFT OUTER JOIN edu_course_description ecd ON ec.id=ecd.idLEFT OUTER JOIN edu_teacher et ON ec.teacher_id=et.idLEFT OUTER JOIN edu_subject es1 ON ec.subject_parent_id=es1.idLEFT OUTER JOIN edu_subject es2 ON ec.subject_id=es2.id
WHERE ec.id='1562267576652808193'
- 我们将课程一级分类和课程二级分类都存到了edu_subject这张表中,此时应该怎么做:如果一张表中有多个字段同时关联一张表,我们就需要查询多次
- 1562267576652808193是我的edu_course数据表中的id,你们写自己数据表中的
1.3创建vo类
在entity–>vo包下创建vo类CoursePublishVo来封装数据
@Data
public class CoursePublishVo {private String id;private String title;private String cover;private Integer lessonNum;private String subjectLevelOne;private String subjectLevelTwo;private String teacherName;private String price;//只用于显示
}
1.4持久层
我们在前面的代码编写中有时只需处理控制层,有时只需处理控制层和业务层,还从来没有处理过持久层。但我们此时手写sql语句,所以需要处理持久层
1.4.1在mapper中定义方法
在EduCourseMapper中定义"根据课程id查询课程具体信息"的抽象方法
public interface EduCourseMapper extends BaseMapper<EduCourse> {//根据课程id查询课程具体信息public CoursePublishVo getPublishCourseInfo(String courseId);
}
1.4.2在idea中连接数据库
1.点击"DataBase"
2.点击加号(“+”),然后点击Data Source下的MySQL
3.输入我们的mysql密码和数据库名字,然后点击"Ok"
4.填写mysql的账号密码,然后点击"Ok"
5.此时我们就可以看到数据库guli中的数据表了,说明此时连接成功
1.4.3编写映射
在EduCourseMapper.xml中编写刚刚定义的抽象方法的映射
<!--sql语句:根据课程id查询课程具体信息-->
<select id="getPublishCourseInfo" resultType="com.atguigu.eduservice.entity.vo.CoursePublishVo">SELECT ec.id,ec.title,ec.cover,ec.lesson_num AS lessonNum,ec.price,es1.title AS subjectLevelOne,es2.title AS subjectLevelTwo,et.name AS teacherNameFROM edu_course ec LEFT OUTER JOIN edu_subject es1 ON ec.subject_parent_id=es1.idLEFT OUTER JOIN edu_subject es2 ON ec.subject_id=es2.idLEFT OUTER JOIN edu_teacher et ON ec.teacher_id=et.idWHERE ec.id=#{courseId}
</select>
为什么截图中的第6行、第7行、第8行、第9行要分别用
AS lessonNum
、AS subjectLevelOne
、subjectLevelTwo
、teacherName
来起别名?- 因为我们vo类CoursePublishVo中定义的属性名是lessonNum、subjectLevelOne、subjectLevelTwo、teacher Name。所以我们需要起别名,并且起的别名一定要和CoursePublishVo中的属性名对应上
我们在"1.4.1在mapper中定义方法"定义的抽象方法只有一个参数,所以截图中第13行的
WHERE ec.id=#{courseId}
中的courseId可以随便写(不过别写成中文啊!!!)<select>标签中的id属性值就填写我们在"1.4.1在mapper中定义方法"定义的抽象方法的名字
<select>标签中的resultType属性是方法返回值的类型,这里我们需要填写CoursePublishVo类的全路径:
com.atguigu.eduservice.entity.vo
,末尾再加上.CoursePublishVo
1.5控制层
在控制器EduCourseController中定义方法
//根据课程id查询课程具体信息
@GetMapping("getPublishCourseInfo/{id}")
public R getPublishCourseInfo(@PathVariable String id) {CoursePublishVo coursePublishVo= courseService.publishCourseInfo(id);return R.ok().data("publishCourse", coursePublishVo);
}
1.6业务层接口
在业务层接口EduCourseService定义抽象方法
//根据课程id查询课程具体信息
CoursePublishVo publishCourseInfo(String id);
1.7业务层实现类
在业务层实现类EduCourseServiceImpl中实现上一步定义的抽象方法
//根据课程id查询课程具体信息
@Override
public CoursePublishVo publishCourseInfo(String id) {//调用mapper中的方法CoursePublishVo publishCourseInfo = baseMapper.getPublishCourseInfo(id);return publishCourseInfo;
}
我们在"demo07-课程分类管理"的"7.4.2业务层实现类"的第1步说过,在业务层调用mapper中的方法我们有两种方式:使用baseMapper.xxx或使用this.xxx。但是因为我们此时是调用mapper中我们自己定义的方法,所以我们只能用BaseMapper.xxx
1.8测试
1.重启EduApplication服务,使用swagger进行测试
2.在输入框输入课程id后点击"Try it out!"
3.执行了异常,说明我们接口是有问题的,解决方法在后面的"1.9加载问题"
1.9加载问题
1.9.1分析问题
1.接口报错如下
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.atguigu.eduservice.mapper.EduCourseMapper.getPublishCourseInfo
2.出现这种报错我们首先查看EduCourseMapper.xml的<select>标签中id属性值和我们在EduCourseMapper中定义的方法名字是否对应上,检查过后发现我们这里是对应上的
3.其实这个错误是maven默认加载机制造成的
①我们先看下面这张图,此时是有xml文件的
②然后再看下图,发现编译后没有xml文件了,也就是说编译时并没有编译xml文件
③这是maven默认加载机制造成的:加载时只会加载java文件夹下的.java类型文件,而不会加载java文件夹下的xml类型的文件
1.9.2解决问题
解决方法有很多种:
1.方法一:
将这些xml文件复制粘贴到编译后的mapper文件夹下(我没有用这种方法,所以我把具体操作截图后又将编译后的mapper文件夹下的这些xml文件删掉了)
这种方法不建议用,因为每次修改xml文件后都需要手动再将修改后的xml文件复制到编译后的mapper文件夹下,很麻烦
2.方法二:
将这些xml文件剪切粘贴到resources目录下(我没有用这种方法,所以我把具体操作截图后又将resources目录下的这些xml文件剪切粘贴到了mapper文件夹下,即归位)
这种方法不建议用,因为我们的代码都是用代码生成器生成的,人家给的结构就是xml在mapper文件夹下。这种方法可行,但以后每次再新生成xml文件就又需要我们将该xml文件剪切粘贴到resources文件夹下,挺麻烦的
3.方法三(推荐使用):
①在pom.xml中进行配置(我们可以在service_edu的pom.xml中进行配置,但我们后期别的项目中可能也需要这样的配置,所以我们选择在service的pom.xml中进行配置)
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources>
</build>
第123行的<include>**/*.xml</include>
中的**(两个星号)
表示多层目录,如果是*(一个星号)
则表示java目录下的一层目录,一样加载不到我们的xml文件(因为我们的xml文件是在java目录下的很多层目录下的)
②点击"Load Maven Changes"刷新pom文件
③在application.properties中进行配置
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/eduservice/mapper/xml/*.xml
1.9.3再次测试
1.重启EduApplication服务,可以看到编译后mapper文件夹下就有xml文件了
2.在输入框输入课程id后点击"Try it out!"
3.可以看到成功返回了数据,测试成功
2.课程信息确认前端
2.1在api中定义方法
在src–>api–>edu–>course.js页面中编写方法调用后端接口
//5.根据课程id查询课程具体信息
getPublishCourseInfo(courseId) {return request({url: `/eduservice/course/getPublishCourseInfo/${courseId}`,method: 'get'})
}
2.2获取路径中的课程id
在publish.vue页面得到路由中的课程id
//获取路由中的课程id
if(this.$route.params && this.$route.params.id) {this.courseId = this.$route.params.id
}
截图中第32行用到了数据模型courseId,现在我们去定义这个数据模型
2.3调用api中的方法
1.我们接下来需要调用在"2.1在api中定义方法"定义的方法getPublishCourseInfo,所以需要在publish.vue页面中引入course.js文件
import course from '@/api/edu/course'
2.在publish.vue页面中定义方法来调用api中的方法
//根据课程id查询课程具体信息
getCoursePublishId() {//调用api中的方法course.getPublishCourseInfo(this.courseId).then(response => {this.publishCourse = response.data.publishCourse})
},
截图的第43行用到了数据模型coursePublish。现在我们去定义这个数据模型
2.4初始化页面
我们在created方法中调用在"2.3调用api中的方法"的第2步定义的getCoursePublishId方法以初始化页面得到该门课程的信息
//调用方法:根据课程id查询课程具体信息
this.getCoursePublishId()
2.5将内容显示到页面上
1.将方框圈起来的部分删掉
2.将老师给的代码复制过来
<div class="ccInfo"><img :src="coursePublish.cover"><div class="main"><h2>{{ coursePublish.title }}</h2><p class="gray"><span>共{{ coursePublish.lessonNum }}课时</span></p><p><span>所属分类:{{ coursePublish.subjectLevelOne }} — {{ coursePublish.subjectLevelTwo }}</span></p><p>课程讲师:{{ coursePublish.teacherName }}</p><h3 class="red">¥{{ coursePublish.price }}</h3></div>
</div>
<div><el-button @click="previous">返回修改</el-button><el-button :disabled="saveBtnDisabled" type="primary" @click="publish">发布课程</el-button>
</div>
3.将老师给的css样式复制过来
<style scoped>
.ccInfo {background: #f5f5f5;padding: 20px;overflow: hidden;border: 1px dashed #DDD;margin-bottom: 40px;position: relative;
}
.ccInfo img {background: #d6d6d6;width: 500px;height: 278px;display: block;float: left;border: none;
}
.ccInfo .main {margin-left: 520px;
}.ccInfo .main h2 {font-size: 28px;margin-bottom: 30px;line-height: 1;font-weight: normal;
}
.ccInfo .main p {margin-bottom: 10px;word-wrap: break-word;line-height: 24px;max-height: 48px;overflow: hidden;
}.ccInfo .main p {margin-bottom: 10px;word-wrap: break-word;line-height: 24px;max-height: 48px;overflow: hidden;
}
.ccInfo .main h3 {left: 540px;bottom: 20px;line-height: 1;font-size: 28px;color: #d32f24;font-weight: normal;position: absolute;
}
</style>
2.6测试
在地址栏输入http://localhost:9528/#/course/publish/1562267576652808193进行测试,可以看到成功显示数据
3.课程最终发布后端
3.1分析
1.虽然此时数据库中有课程信息,但是我们还没有最终发布课程,只有当我们最终发布课程了,前台用户才可以看到这个课程
2.先看一下我们创建的edu_course表中status字段的含义
可以知道我们是通过status字段的值来判断该门课程是否发布:值为Draft时课程未发布;值为Normal时课程已发布
3.由下图可知当我们新的课程数据插入数据库中时,status字段默认是Draft,也就是说默认是未发布状态
3.2控制层
在控制器EduCourseController中编写方法用于将课程的发布状态改为"已发布"
//课程最终发布(修改edu_course表中status字段的值)
@PostMapping("publishCourse/{id}")
public R publishCourse(@PathVariable String id) {EduCourse eduCourse = new EduCourse();eduCourse.setId(id);eduCourse.setStatus("Normal"); //设置课程发布状态为"已发布"courseService.updateById(eduCourse);return R.ok();
}
4.课程最终发布前端
4.1在api中定义方法
在course.js中定义方法来调用上一步编写的后端接口
//6.课程最终发布(将课程的发布状态改为"已发布")
publishCourse(courseId) {return request({url: `/eduservice/course/publishCourse/${courseId}`,method: 'post'})
}
4.2调用api中的方法
1.可以看到,"发布课程"按钮我们给它绑定的方法是publish方法
2.publish方法我们曾经编写过
3.完整的publish方法如下
//课程最终发布
publish() {course.publishCourse(this.courseId).then(response => {//提示发布成功this.$message({type: 'success',message: '发布成功!'});//跳转到list.vue页面this.$router.push({path: '/course/list'})})
}
4.3测试
1.在地址栏输入http://localhost:9528/#/course/publish/1562267576652808193,然后点击"发布课程"
2.提示发布成功
3.去数据库查看,可以看到这条数据的status字段的值确实被修改为了Normal
5.课程列表后端
5.1分析
其实和讲师列表是一样的,老师这里只做了最基本的实现,后期的条件查询带分页由我们自己完善,那我暂时也只做最基本的实现吧
5.2控制层
在控制器EduCourseController中编写方法
//课程列表最基本实现(条件查询带分页后期再完善)
@GetMapping
public R getCourseList() {List<EduCourse> list = courseService.list(null);return R.ok().data("list", list);
}
6.课程列表前端
6.1在api中定义方法
在course.js中编写方法用于调用上一步编写的后端接口
//7.课程列表
getListCourse() {return request({url: `/eduservice/course`,method: 'get'})
}
6.2编写list.vue页面
此时list.vue(是course目录下的list.vue)中没有任何代码,我们说过了课程列表页面和讲师列表页面很相似,所以我们直接将讲师列表页面的代码全部复制粘贴到课程列表页面,并根据需求进行修改,修改后的课程列表页面如下
<template><div class="app-container"><!-- 表格 --><el-table:data="list"borderfithighlight-current-row><el-table-columnlabel="序号"width="70"align="center"><template slot-scope="scope">{{ scope.$index + 1 }}</template></el-table-column><el-table-column prop="title" label="课程名称" width="80" /><el-table-column label="课程状态" width="80"><template slot-scope="scope">{{ scope.row.status==='Normal'?'已发布':'未发布' }}</template></el-table-column><el-table-column prop="lessonNum" label="课时数"/><el-table-column prop="gmtCreate" label="添加时间" width="160"/><el-table-column prop="viewCount" label="浏览数量" width="80" /><el-table-column label="操作" width="450" align="center"><template slot-scope="scope"><router-link :to="'/course/info/'+scope.row.id"><el-button type="primary" size="mini" icon="el-icon-edit">编辑课程基本信息</el-button></router-link><router-link :to="'/course/chapter/'+scope.row.id"><el-button type="primary" size="mini" icon="el-icon-edit">编辑课程大纲</el-button></router-link><el-button type="danger" size="mini" icon="el-icon-delete">删除课程信息</el-button></template></el-table-column></el-table></div>
</template><script>
//引入course.js文件
import course from '@/api/edu/course'export default {data() { //定义变量和初始值return {list: null //查询之后接口返回的数据赋值给list}},created() { //页面渲染之前执行,一般用来调用methods中定义的方法//调用this.getList()},methods: { //创建具体的方法,调用course.js中定义的方法//课程列表的方法getList() {//调用方法,使用axios发送ajax请求course.getListCourse().then(response => {this.list = response.data.list})}}
}
</script>
- 截图中第41行的
:to="'/course/chapter/'+scope.row.id"
是为了实现:点击"编辑课程大纲 "按钮时走/course/chapter/+课程id
路由从而在浏览器展现chapter.vue页面。截图中第37行的:to="'/course/info/'+scope.row.id"
同理 - 删除按钮的后端和前端代码我们接下来就会说
6.3测试
自行测试
7.课程删除后端
7.1分析
1.课程里面有课程描述、章节,章节里面又有小节,小节里面又有视频,所以我们删除课程时需要将视频、小节、章节、课程描述还有课程本身都给删除掉
2.外键约束
两张表一对多关联时,在多的那一方创建字段,指向一的那一方的主键,这个字段就叫做外键
拿课程表和章节表举例:
3.去章节表看一下:
这里的course_id字段就是外键。但是我们发现我们并没有给这个字段添加foreign key将这个外键声明出来,我们只是自己心里知道它是一个外键,这种方式我们称之为物理外键。
为什么不给外键字段添加foreign key呢?有一个原因是:如果添加了foreign key那么删除数据时就必须先删除视频,然后删除小节,然后删除章节,再删除课程描述,最后才能删除课程本身,否则就会报错(其中删除课程描述不一定非要在删除章节之后,因为课程描述只和课程本身有关联,所以只要是在删除课程本身之前删除课程描述就可以了)
如果不添加foreign key那么我们删除数据时就没有先后之别了,不过还是建议使用刚刚说的顺序进行删除
7.2控制层
在控制器EduCourseController中编写代码
//删除课程
@DeleteMapping("{courseId}")
public R deleteCourse(@PathVariable String courseId) {courseService.removeCourse(courseId);return R.ok();
}
7.3业务层接口
在业务层接口EduCourseService中定义抽象方法
//删除课程
void removeCourse(String courseId);
7.4业务层实现类
在业务层实现类EduCourseServiceImpl中实现上一步定义的抽象方法:
1.我们会在抽象方法中删除小节表、章节表、课程描述表中的数据,其中课程描述表我们曾经已经注入过了,现在我们来注入小节表和章节表
//注入小节和章节service
@Autowired
private EduVideoServiceImpl eduVideoService;
@Autowired
private EduChapterService chapterService;
2.在EduCourseServiceImpl中编写代码
//删除课程
@Override
public void removeCourse(String courseId) {//1.根据课程id删除小节eduVideoService.removeVideoByCourseId(courseId);//2.根据课程id删除章节chapterService.removeChapterByCourseId(courseId);//3.根据课程id删除课程描述courseDescriptionService.removeDescriptionByCourseId(courseId);//4.根据课程id删除课程本身int result = baseMapper.deleteById(courseId);if (result == 0) { //删除失败throw new GuliException(20001, "删除失败");}
}
7.5编写removeVideoByCourseId方法
1.在业务层接口EduVideoService中定义抽象方法
//根据课程id删除小节
void removeVideoByCourseId(String courseId);
2.在业务层实现类EduVideoServiceImpl中实现上一步定义的抽象方法
//根据课程id删除小节
@Override
public void removeVideoByCourseId(String courseId) {//TODO 删除小节前需要先删除小节下的视频文件QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();wrapper.eq("course_id", courseId);baseMapper.delete(wrapper);
}
删除小节时需要先删除小节中的视频,这个业务我们后面实现
7.6编写removeChapterByCourseId方法
1.在业务层接口EduChapterService中定义抽象方法
//根据课程id删除章节
void removeChapterByCourseId(String courseId);
2.在业务层实现类EduChapterServiceImpl中实现上一步定义的抽象方法
7.7疑问
有没有朋友疑惑为什么不将removeVideoByCourseId方法和removeChapterByCourseId方法的逻辑编写在业务层实现类EduCourseServiceImpl的removeCourse方法中呢?我们这样做是为了解耦
7.8测试
重启后端项目后使用swagger自行测试吧
8.课程删除前端
8.1在api中定义方法
//8.根据课程id删除课程
deleteCourseById(courseId) {return request({url: `/eduservice/course/${courseId}`,method: 'delete'})
}
8.2绑定事件
给list.vue页面的"删除课程信息"按钮绑定事件
8.3调用api中的方法
//根据课程id删除课程
deleteCourse(courseId) {this.$confirm('此操作将永久删除课程记录, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {course.deleteCourseById(courseId).then(response => {//1.提示删除成功this.$message({type: 'success',message: '删除成功!'});//2.回到列表页面this.getList()}).catch(error => {}) //删除失败})
},
8.4测试
自行测试
谷粒学院16万字笔记+1600张配图(十)——课程管理相关推荐
- 谷粒学院16万字笔记+1600张配图(八)——课程管理
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo08-课程管理 1.课程 ...
- 谷粒学院16万字笔记+1600张配图(九)——课程管理
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo09-课程管理 1.课程 ...
- 谷粒学院16万字笔记+1600张配图(十一)——课程管理
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo11-课程管理 1.阿里 ...
- 谷粒学院16万字笔记+1600张配图(十六)——讲师显示、课程显示
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo16-讲师显示.课程显示 ...
- 谷粒学院16万字笔记+1600张配图(十八)——统计分析
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo18-统计分析 1.需求 ...
- 谷粒学院16万字笔记+1600张配图(十二)——课程管理
项目源码与所需资料 链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59 提取码:8z59 文章目录 demo12-课程管理 1.微服 ...
- 谷粒学院填坑笔记(事故多发是不熟悉前端)
1.p233生成订单时courseId是Underfined, 拿到的 courseId为未定义,排错前后端从sql语句到@pathvrible.最后是在前端的_id.vue发现缺少course,之前 ...
- 计算机数学学院,16级软件学院《计算机数学》课程标准
开封大学计算机应用.网络.软件专业 职业必修课程<计算机数学> 课程标准 开封大学数学教研部 二零一六年九月 <计算机数学>课程标准 一.课程定位 本课程是软件职业技术学院各专 ...
- 尚硅谷谷粒学院学习笔记(防坑点的总结部分勘误)
谷粒学院学习笔记 部分勘误 数据库设计规约 模块说明 环境搭建 创建一个Spring Boot 的父工程,版本使用:2.2.1.RELEASE 父工程pom.xml里面添加 在pom.xml中添加依赖 ...
最新文章
- linux命令 iperf-网络性能测试工具
- 干掉ArrayList:HikariCP为什么自己造了一个FastList?
- NUMECA FINE Turbo 14中文版
- 解决jenkins 使用ssh插件执行脚本,导致一直处于构建中无法停止
- Makefile选项CFLAGS,LDFLAGS,LIBS
- linux 让暂停的进程恢复,Linux 下进程的挂起和恢复命令
- [译]R语言——Shiny框架之入门(三):如何启动一个Shiny应用
- 根据文件路径打开文件所在文件夹,并且默认选中该文件
- 系统学习NLP(十三)--词向量(word2vec原理)
- ros 三线负载均衡
- Citrix 桌面云 XenApp_XenDesktop_7.15 部署系列(六)配置虚拟桌面控制器
- 南方cass字体样式设置_cass改变字体格式 cass字体样式管理器
- DOM操作简易年历案例
- Matlba实现傅里叶变换及其逆变换
- Hadoop-day01_(java代码模拟hadoop存储数据)
- 我们应该如何做外链?
- Google Authenticator(谷歌身份验证器)在苹果手机上IOS系统中 输入密钥时提示密钥无效的解决方案
- Win10 网络连接处空白什么都没有,电脑无法上网
- a到z的ascii码值是多少_c语言 ASCLL码中 A~Z和a~z是多少
- kafka多线程消费