guli_edu

文章目录

总述

项目包结构

一个项目中清晰明了的项目包结构,可以反映出开发人员的基本开发素质,以及是否对项目有一个清晰明确的开发思路。
从这个项目中,我们可以学到以下几点:

具体结构说明

在这里插入图片描述

可以看到包的层次非常的清晰明了,各个部分的作用非常的清晰,毫不含糊,方便后续人员的开发和维护。
当然这个项目设计到的技术栈还是很简单,因此项目结构还不是很复杂。

DTO:Data Transfer Object数据传输对象

可以将PO中的部分属性抽取出来,就形成了DTO。

比如一张表中有100个字段,那么对应的PO就会有100个属性。但是界面上只会显示10个字段,客户端用WEB service来获取数据,没有必要把整个PO对象传递到客户端,这样也不会服务端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO(View Object)。

在这里插入图片描述

//OneSubjectDto
//用于表示一级分类
@Data
public class OneSubjectDto {

    private String id;//一级分类id
    private String title;//一级分类名称
    //一级分类所有的二级分类
    private List<TwoSubjectDto> children = new ArrayList<>();
}
//TwoSubjectDto
//用于表示二级分类
@Data
public class TwoSubjectDto {

    private String id;//二级分类id
    private String title;//二级分类名称
}

MyBatis-Plus的用法

这里涉及到的主要是封装查询条件,然后使用baseMapper中的方法进行增删改查,不得不说这样很方便,避免了很多重复性的劳动。大大减少了工作量。

BaseMapper

Insert
//插入一条记录
int insert(T entity);

参数说明

Tentity实体对象
Delete
// 根据entity条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID批量删除)
int deleteBatchIds(@Param(Constants.CPLLECTION)Collection<? extends Serializable> idList);
// 根据
selectPage
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

根据entity条件,查询全部记录(并翻页)

@Param:page,分页查询条件
@Param:queryWrapper 实体对象封装操作类(可以为null)
selectList
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

根据entity条件,查询全部记录

@param:queryWrapper 实体对象封装操作类(可以为null)
selectCount
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

根据wrapper条件,查询记录总数

@param:queryWrapper 实体对象
selectOne
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

根据entity条件,查询一条记录

@param queryWrapper 实体对象
selectById
T selectById(Serializable id);

根据 ID查询

@param id 主键ID
deleteById
int deleteById(Serializable id);

根据ID删除

@param id 主键ID
delete
int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

根据entity条件,删除记录

@param queryWrapper实体对象封装操作类
insert
int insert(T entity);

插入一条记录

@param entity 实体对象

IService

Save
//插入一条记录(选择字段,策略插入)
boolean save(T entity);
//插入(批量)
boolean saveBatch(Collection<T> entityList);
//插入(批量)
boolean saveBatch(Collection<T> entityList, int bathcSize);

参数说明

类型参数名描述
Tentity实体对象
CollectionentityList实体对象集合
intbatchSize插入批次数量
SaveOrUpdate
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Coolection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Coolection<T> entityList, int batchSize);

参数说明

Tentity实体对象
WrapperupdateWrapper实体对象封装操作类UpdateWrapper
CollectionentityList实体对象集合
intbatchSize插入批次数量
Remove
// 根据entity条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据ID删除
boolean removeById(Serializable id);
// 根据columnMap条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean remvoeByIds(Coolection<? extends Serializable> idList);
类型参数名描述
WrapperqueryWrapper实体包装类QueryWrapper
Serializableid主键ID
Map<String,Object>columnMap表字段map对象
Collection<? extends Serializable>idList主键ID列表
Update
//根据 UpdateWrapper条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据whereEntity条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据ID选择修改
boolean updateById(T entity);
// 根据ID批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

参数说明

Wrapper<T>updateWrapper实体对象封装操作类UpdateWrapper
Tentity实体对象
Collection<T>entityList实体对象集合
intbatchSize更新批次数量
Get
// 根据ID查询
T getById(Serializable id);
// 根据Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据Wrapper,查询一条记录
T getOne(Wrapper<T> querWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
Serilizableid主键ID
Wrapper<T>querWrapper实体对象封装操作类QueryWrapper
booleanthrowEx有多个result是否抛出异常
Tentity实体对象
Function<? super Object,V>mapper转换函数
list
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询所有列表
List<Map<String,Object>> listMaps();
// 查询列表
List<Map<String,Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
//查询全部记录
<V> List<V> listObjs(Function<? super Object ,V> mapper);
// 根据Wrapper条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据Wrapper条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? ssuper Object, V> mapper);

参数说明

Wrapper<T>queryWrapper实体对象封装操作类QueryWrapper
Collection<? extends Serilizable>idList主键ID列表
Map<?String,object>columnMap表字段map对象
Function<? super Object,V>mapper转换函数
Page
//无条件分页查询
IPage<T> page(IPage<T> page);
//条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
//无条件分页查询
IPage<Map<String,Object>> pageMaps(IPage<T> page);
//条件分页查询
IPage<Map<String,Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

参数说明

IPage<T>page翻页对象
WrapperqueryWrapper实体对象封装操作类QueryWrapper
Count
//查询总记录数
int count();
//根据Wrapper条件,查询总记录数
int count(Wrapper<T> queryWrapper);

参数说明

Wrapper<T>queryWrapper实体对象封装操作类 QueryWrapper
Chain
query
//链式查询 普通
QueryChainMapper<T> query();
//链式查询 lambda式。注意:不支持Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();

//示例:
query().eq("column",value).one();
lambdaQuery().eq(Entity::getId,value).list();
update
//链式更改 普通
UpdateChainWrapper<T> update();
//链式更改 lambda式。注意:不支持Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();

//示例:
update().eq("column",value).remove();
lambdaUpdate().eq(Entity::getId,value).update(entity);

day02

测试查询所有讲师功能

    //1查询所有讲师功能
    @GetMapping
    public R getAllTeacherList(){
        //调用service的方法
        List<EduTeacher> list = eduTeacherService.list(null);
        //return list;
        return R.ok().data("items",list);
    }

逻辑删除讲师功能实现

entity包的EduTeacher类中的isDeleted字段上加上@TableLogic,表示逻辑删除,这是Mybatis-plus的注解。·

还需要在配置类EduServiceConfig中加上逻辑删除的插件

@EnableTransactionManagement
@Configuration
@MapperScan("com.online.edu.eduservice.mapper")
public class EduServiceConfig {
    /**
     * 逻辑删除插件
     * */
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }
}

在这里插入图片描述

    //2逻辑删除讲师
    @DeleteMapping("{id}")
    public boolean deleteTeacherById(@PathVariable("id") String id){
        boolean b = eduTeacherService.removeById(id);
        return b;

统一返回数据结果

{
    "success": 布尔,//响应是否成功
    "code": 数字,//响应码
    "message": 字符串,//返回消息
    "data": HashMap //返回数据,放在键值对中
}

简单分页查询功能

还需要配置分页插件,具体来说,在EduServiceConfig.java中添加分页插件

    /**
     * 分页插件
     * */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
    //3 分页查询讲师列表的方法
    @GetMapping("pageList/{page}/{limit}")
    public R getPageTeacherList(@PathVariable("page") Long page, @PathVariable("limit") Long limit){
        //创建page对象,传递两个参数
        Page<EduTeacher> pageTeacher = new Page<>(page,limit);
        //调用方法实现分页查询
        eduTeacherService.page(pageTeacher, null);
        //从pageTeacher对象里面获取分页数据
        Long total = pageTeacher.getTotal();
        List<EduTeacher> records = pageTeacher.getRecords();
        return R.ok().data("total",total).data("items",records);
    }

day03

统一异常处理

统一日志处理

在这里插入图片描述

day04

讲师管理前端开发(添加路由)

找到模板的router文件夹下的index.js文件,添加新的路由即可。
例如,仿照example示例,添加讲师管理路由

  {
    path: '/teacher',
    component: Layout,
    redirect: '/teacher/list',
    name: '讲师管理',
    meta: { title: '讲师管理', icon: 'example' },
    children: [
      {
        path: 'list',
        name: '讲师列表',
        component: () => import('@/views/table/index'),
        meta: { title: '讲师列表', icon: 'table' }
      },
      {
        path: 'save',
        name: '添加讲师',
        component: () => import('@/views/tree/index'),
        meta: { title: '添加讲师', icon: 'tree' }
      }
    ]
  },
    {
    path: '/example1',
    component: Layout,
    redirect: '/example/table',
    name: 'Example1',
    meta: { title: 'Example1', icon: 'example' },
    children: [
      {
        path: 'table1',
        name: 'Table1',
        component: () => import('@/views/table/index'),
        meta: { title: 'Table1', icon: 'table' }
      },
      {
        path: 'tree1',
        name: 'Tree1',
        component: () => import('@/views/tree/index'),
        meta: { title: 'Tree', icon: 'tree' }
      }
    ]
  },

1、把讲师管理前后端整合
(1)讲师列表
第一步:添加路由,到src--router--index.js添加路由
第二步:创建路由配置页面views/edu/teacher/index
第三步:在src--api文件夹里面创建teacher.js文件,定义列表请求后端路径
第四步:在views/edu/teacher/index页面中编写核心代码

  • 列表页面
  • 分页部分
  • 条件查询部分

使用element-ui组件实现的

(2)讲师删除
第一步:页面 views/edu/teacher/index,添加每条记录有删除按钮
第二步:点击删除按钮,触发事件,传递讲师id,@click="removeDataById(scope.row.id)"
第三步:编写删除的方法,添加确认框,调用具体的方法实现删除

2、跨域问题
(1)如果访问协议、ip地址、端口号,有一个是不一样的,就是跨域
(2)解决:nginx、httpclient、添加到controller注解@CrossOrigin

3、把登录改造到本地
(1)看easymock返回的数据,自己写方法也返回相同的数据
(2)在自己controller里面编写两个方法,login和info
(3)在前端修改api里面的login.js修改为自己路径

因为请求本地路径,把config里面dev.env.js修改为本地ip和端口号

讲师管理前端开发(修改讲师功能实现1)


在这里插入图片描述

讲师管理前端开发(路由变化bug解决)

前端首先写函数观测路由变化

    watch: {
        $route(to, from) {
            console.log('watch $route')
            this.init()
        }
    },
    created () {
        this.init()
    },
    methods: {
        init() {
            //在页面加载之前,判断路由里面是否有id值
            //如果有id值,调用方法根据id查询
            //从路由里面获取值
            if(this.$route.params && this.$route.params.id) {//修改数据回显
                const id = this.$route.params.id
                //调用方法根据id查询
                this.getTeacherById(id)
            } else {//添加
                //表单数据清空
                this.teacher = { ...defaultForm }
            }
        },

day05

阿里云oss介绍和测试

(1)上传功能

  • 原始写法

    • 上传表单要求:post提交、表单有文件上传项目并且name属性<input type="file name="file"/>
    • 设置form表单属性 enctype="multipart/form-data"
    • 使用fileupload组件实现上传
  • springmvc写法

    • 在controller中使用对象获取上传文件MultipartFile

后端代码开发(nginx基本配置)

在这里插入图片描述

讲师头像上传(前端上传组件整合和测试)

<!-- 讲师头像:TODO -->
      <!-- 讲师头像 -->
      <el-form-item label="讲师头像">

            <!-- 头衔缩略图 -->
            <pan-thumb :image="teacher.avatar"/>
            <!-- 文件上传按钮 -->
            <el-button type="primary" icon="el-icon-upload" @click="imagecropperShow=true">更换头像
            </el-button>

            <!--
        v-show:是否显示上传组件
        :key:类似于id,如果一个页面多个图片上传控件,可以做区分
        :url:后台上传的url地址
        @close:关闭上传组件
        @crop-upload-success:上传成功后的回调 -->
            <image-cropper
                        v-show="imagecropperShow"
                        :width="300"
                        :height="300"
                        :key="imagecropperKey"
                        :url="BASE_API+'/eduservice/oss/upload'"
                        field="file"
                        @close="close"
                        @crop-upload-success="cropSuccess"/>

        </el-form-item>
//声明使用的额外组件
    components: {ImageCropper,PanThumb},
    data() {
        return {//设置teacher对象初始值
            BASE_API: process.env.BASE_API, // 接口API地址
            imagecropperShow:false,
            imagecropperKey:0,
            teacher: defaultForm
        }
    },
    //cropSuccess函数
            cropSuccess(data) {
            console.log(data)
            this.imagecropperShow = false
            //获取后台返回图片地址,显示到页面中
            this.teacher.avatar = data.imgurl
            //重新加载上传组件
            this.imagecropperKey = this.imagecropperKey + 1
        },

课程相关表结构的分析

在这里插入图片描述

day06

poi导入分类信息(添加分类)

  • 实现后端
    • 使用代码生成器生成分类相关代码
  • 在项目中引入poi依赖
  • 在controller创建方法实现功能
  • 在controller调用service方法
    (1)获取文件输入流
    (2)创建workbook,传入输入流
    (3)根据workbook获取sheet
    (4)获取最后一行数据索引 int lastRowNum = sheet.getLastRowNum();
    (5)遍历每一行数据,从第二行开始遍历,得到每一行数据
    (6)获取每一行数据的第一列
    (7)获取每一行第一列中的值
    (8)判断获取第一列中的值(一级分类名称)在数据表是否存在相同的一级分类名称
    • 根据一级分类名称和parent_id值0进行判断
      (9)如果数据库表不存在相同的一级分类,进行添加,如果已经存在不添加
    • 把一级分类id获取到,为了后面二级分类做准备
      (10)获取每一行第二列中的值
      (11)判断第二列中的值(二级分类)在数据库表是否存在相同的二级分类名称
    • 根据二级分类名称和parent_id进行判断
      (12)如果数据库表不存在相同的二级分类,进行添加,如果已经存在不添加。

poi导入分类信息(初步实现添加一级分类)

在这里插入图片描述

day07

发布课程流程

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

发布课程(添加课程信息分类下拉列表)

在这里插入图片描述

day08

  • 分类删除
  • 分类添加
  • 发布课程
  • 添加课程基本信息

添加课程基本信息完善

(1)课程分类二级联动

// 获取选择一级分类的id值
//根据一级分类id值,获取下面的所有二级分类

//1 遍历所有一级分类集合
//2 获取每个一级分类
//3 判断value值和遍历出来的每个一级分类id值是否一样,
//如果一样,获取下面二级分类,是child

(2)整合文本编辑器

  • 为了课程简介显示更丰富的内容,比如图片,文字有颜色
  • 按照笔记过程整合出来就可以了
  • 文本编辑器图片存储没有使用服务器,而是对图片使用base64编码

(3)课程封面上传

  • 把课程封面上传到阿里云oss里面

课程基本信息修改

(1)课程基本信息数据回显

  • 实现课程大纲页面上一步效果
  • 根据课程id查询课程信息,做数据回显
  • 后端代码:根据课程id查询课程详细信息

(2)修改课程基本信息

前端分类数据回显底层分析

在这里插入图片描述

day09

1、删除课程功能(删除课程、删除章节、删除小节)
(1)第一步 根据课程id删除章节
(2)第二步 根据课程id删除小节
(3)第三步 根据课程id删除描述

删除章节、小节和描述,不需要返回值判断,可以没有数据

(4)第四步 根据课程id删除课程本身

2、编写课程大纲
(1)查询课程大纲列表

大纲包干课程里面章节和课程里面小节
章节和小节信息可以根据课程id查询

第一步:创建两个dto实体类,用于数据封装
(1)课程章节
(2)课程小节

发布课程

在这里插入图片描述

根据课程id查询信息sql语句编写

/*
    根据课程id查询课程信息
    课程名称、课程价格、课程封面
    课程描述
    课程所属讲师名称
    课程一级分类和二级分类
*/

select c.title,c.price,c.cover,cd.description,et.name,s1.title as onelevel,s2.title as twolevel
from edu_course c LEFT outer join edu_course_description cd on c.id = cd.id
                  LEFT outer join edu_teacher et on c.teacher_id= et.id
                  LEFT outer join edu_subject s1 on c.subject_parent_id=s1.id
                  LEFT outer join edu_subject s2 on c.subject_id=s2.id
where c.id='18'

day10

nacos注册

在这里插入图片描述

今日内容:
1、实现课程最终发布功能
(1)在第二步点击下一步,跳转到课程最终发布页面,在最终发布页面中,显示课程的详细信息

根据课程id查询课程详细信息
因为显示课程详细信息包含很多内容,所以查询的时候包含很多张表数据
编写一条sql语句,使用sql语句查询出课程详细信息

如何解决?
第一种做法:把xml配置文件放到resources里面,不建议这样做
第二种做法:推荐做法,进行配置实现,通过配置实现,通过配置让maven加载xml配置文件
第一个地方,在项目pom.xml文件中进行配置
第二个地方,在项目springboot的配置文件中进行相应的配置
mybatis-plus.mapper-locations=classpath:com/online/edu/eduservice/mapper/xml/*.xml

(2)点击最终发布,修改课程状态是已经发布状态
修改课程状态,字段status值修改为Normal

发布课程过程总结(问题和细节)

(1)填写课程基本信息的时候

课程所属类型做二级联动
二级联动实现过程:显示所有的一级分类,二级分类默认没有数据,点击某个一级分类的时候,才显示对应的二级分类。
点击某个一级分类的时候,下拉列表触发的事件是change事件

整合文本编辑器
上传功能如何实现的:没有上传服务器,不是真正上传,把文件进行base64编码,编码数据进行存储
这种上传方式优点:如果文件比较小,使用这种方式效率高

(2)添加课程大纲信息的时候

dto封装思想

(3)课程最终发布

查询多张表,自己写sql语句
maven默认不会加载java文件夹下面的配置文件,通过配置可以让maven加载配置文件

day11

今天内容
1、添加小节(视频操作)
(1)上传视频到阿里云服务器
使用阿里云实现上传视频到阿里云服务器中,需要引入依赖

这个依赖从maven仓库下载不到,需要手动把依赖安装到本地仓库中

第一种方式:使用命令(推荐)

  • 打开cmd窗口,进入依赖所在文件夹下
  • 输入命令

mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.7 -Dpackaging=jar -Dfile=aliyun-java-vod-upload-1.4.7.jar

第二种方式:直接在仓库创建文件夹

*** 写测试类,测试上传视频到阿里云服务器操作

(2)删除视频(删除阿里云里面视频)

(3)整合阿里云视频播放器

配置nginx

server {

		listen 9001;
		server_name localhost;

		location ~ /eduservice/ {           
			 proxy_pass http://localhost:8001;
		}

		location ~ /vidservice/ {           
			 proxy_pass http://localhost:8002;
		}

	}
  • 在前端页面中,添加小节时候,上传视频
  • 413 nginx上传大小限制问题。client_max_body_size 1024m;
  • 上传之后,在文件后面有×,点击×实现删除阿里云云端视频文件

2、统计分析功能需求分析
(1)springcloud里面服务注册和服务发现

(2)图表工具echarts(柱状图,饼状图等)

(3)统计每一天有多少注册人数

在这里插入图片描述

day12

内容介绍

在这里插入图片描述

在这里插入图片描述

JWT令牌

在这里插入图片描述

整合阿里云短信服务

申请模板

申请签名

在这里插入图片描述

1、springcloud组件服务注册和服务发现

可以让不同的服务之间实现通信,每间隔30秒实现周期性的轮询

2、删除小节,同时删除对应的阿里云视频
第一节 搭建注册中心
第二节 把eduservice和vidservice注册到注册中心里面
第三节 在eduservice中调用vidservice的删除视频方法

在调用端eduservice,引入依赖,启动类上添加注解
创建接口,使用注解指定找哪个服务 @FeignClient(“xueyuan-vidservice”)
接口中定义调用的方法,写调用vidservice里面的路径
特别注意,@PathVariable后面必须加上变量的名称

    @DeleteMapping("/vidservice/vod/{videoId}")
    public R removeVideoAliyunId(@PathVariable("videoId") String videoId);

3、删除课程,不仅删除小节,还要把小节里面阿里云视频删除
(1)删除课程的时候,因为里面有很多的章节,每个章节有很多小节,每个小节中都会有视频。因此一个课程会有很多个视频

4、统计分析功能实现(一部分)

在这里插入图片描述

Redis缓存

由于首页数据变化不是很频繁,而且首页访问量相对较大,所以有必要把首页接口数据缓存到redis缓存中,减少数据库压力和提高访问速度。

Spring Boot缓存注解
缓存@Cacheable

根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存数据不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

属性/方法名解释
value缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames与value差不多,二选一即可
key可选属性,可以使用SpEL标签自定义缓存的key
缓存@CachePut

使用该注解的方法,每次都会执行,并将结果存入指定的缓存中。其它方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
查看源码,属性值如下:

属性/方法名解释
value缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames与value差不多,二选一即可
key可选属性,可以使用SpEL标签自定义缓存的key
缓存@CacheEvict

使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上。
查看源码,属性值如下:

属性/方法名解释
value缓存名,必填,它指定了你的缓存存放在哪块命名空间
cacheNames与value差不多,二选一即可
key可选属性,可以使用SpEL标签自定义缓存的key
allEntries是否情况所有缓存,默认为false。如果指定为true,则方法调用后将立即清空所有的缓存
beforeInvocation是否在方法执行前就清空,默认为false。如果指定为true,则再方法执行前就会清空

day14

  • 前台系统中讲师列表整合
  • 前台系统中讲师详情整合
  • 实现前台系统中课程列表
  • 实现前台系统中课程详情
  • 整合阿里云视频播放器课程播放
  • 在线教育优化

(1)首页面优化

在线教育首页面,包含幻灯片和课程列表和讲师列表
把首页这些信息放到缓存里面,放到redis里面

redis缺点
第一类重要的数据(财务类)
第二类经常修改的数据

如何把数据放到redis里面,实现过程?
首先获取数据肯定查询redis,看redis里面是否有数据
如果redis里面有数据,直接返回
如果redis没有数据,查询数据库,把数据库数据放到redis里面

在这里插入图片描述

(2)页面静态化
(3)消息队列应用场景(mq)activemq

  • 项目后台删除课程的同时,删除视频
  • 删除课程的时候,再删除阿里云视频,删除阿里云视频放到消息队列里面,直接返回删除成功
  • 删除速度快,让消息队列慢慢去删除阿里云视频

消息队列缺点:
要求操作实时性高

在这里插入图片描述

课程评论

在这里插入图片描述

day15

今天内容:

1、实现微信扫描登录
第一步 生成微信扫描登录的二维码

第二步 扫描生成二维码,回调操作,登录过程

2、jwt

3、OAuth2

微信登录流程
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

day16

定时任务

在这里插入图片描述

day17

数据同步

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

权限管理需求

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210106100510556.pn

day18

Spring Security

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值