1.学习了MyBaits-plus的相关配置
2.对于Mysql8.0中配置文件时区的配置
3.关于SpringBoot中对于Mapper接口的扫描
1.可在SpringBoot主程序中添加 @MapperScan("包名") 注解
2.可在Mapper接口上添加 @Mapper 注解
4.在MyBaits-Plus中 通过继承 BaseMapper<>类来代替Mapper.xml
达成一些简单的CRUD
5.使用Lombok插件中的@DATA
注解 ,来对实体类生成get set方法
6.使用测试类来进行测试 可以使用SpringBoot的测试类来自动注入
组件 进行测试
7. 由于Mapper接口并不是实现类,所以IDEA可能在自动注入后会报错 可以忽略,不影响运行,也可以通过添加组件注解(@Component等)来解除错误
1.在配置文件中添加配置来显示详细MyBaits-Plus信息
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2.数据库主键生成策略
* 1) 自动增长 AUTO INCREMENT 分表时 需要获取上一张表的id值
* 2) UUID 每次生成随机唯一的值 排序不方便
* 3) Redis生成id
* 4) Mybatis-Plus 自带策略 ->雪花算法
3.MyBatis-Plus中使用 @TableId(type = IdType=xxx )
注解来标注使用哪种主键生成策略
- AUTO 自动增长
- INPUT 需要自行输入
- UUID 自动生成随机唯一值
- NONE 不使用任何策略 也属于是自行输入
- ID_WORKER Mybatis-Plus自带策略 自动生成19位置 数字类型主键使用这种策略 比如long
- ID_WORKER_STR Mybatis-Plus自带策略 自动生成19位置 字符类型主键使用这种策略 比如String
4.测试MyBatis-Plus的修改操作,在创建对象后,MyBatis-Plus只会对 对象属性赋过值的字段进行修改,其他不会改动
public void updateUser(){
User user =new User();
user.setId(5L);
user.setAge(120); //只会修改此属性对应的字段值
int result = userMapper.updateById(user);
System.out.println("update: "+result);
}
5.MyBatis-Plus自动填充
在表中添加字段 create_time , update_time 我们可以选择在插入修改时使用set方法来进行修改
在MyBatis-Plus中我们可以使用自动填充功能来自动为表中字段赋值
1.在想要自动填充的字段上使用注解 @TableFiled(fill=xxx) 来表示表中字段自动填充的时机
2.创建类来实现 MetaObjectObjectHandler 接口 并实现其方法
3.在对应时机的方法中为其属性进行赋值
注意 :此实现类会为所有表的同名字段进行赋值,并没有单独指定一张表的自动填充
=====对应实体类中的字段=====================
//自动填充
//使用@TableFiled 注解 在插入表中数据时 将此属性对应的自动填充对应数据
@TableField(fill = FieldFill.INSERT)
private Date createTime; //驼峰式写法
//使用@TableFiled 注解 在第一次插入和修改表中数据时 将此属性对应的自动填充对应数据
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
=== MetaObjectHandler 接口的实现类====================================
@Component //要想容器中注入该组件
public class MyMetaObjectHandler implements MetaObjectHandler {
//使用mp 实现添加操作,这个方法就会执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//使用mp 实现修改操作,这个方法就会执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
6.丢失更新:多人同时修改同一条记录,最后提交的会把之前已经提交过的数据覆盖
* 解决方法:
* 1 . 悲观锁:串行执行
* 2.乐观锁: 添加version 使用版本号进行控制 比较数据与数据库中的版本号,版本号不同,不能进行更改
乐观锁:与MySql中的MVCC(多版本并发控制) 和Redis中的乐观锁相似
7.乐观锁的具体实现
1.表中添加字段 作为乐观锁版本号
2.对应实体类添加版本号属性
3.在配置类中配置乐观锁插件
//乐观锁 版本号配置
@Version
@TableField(fill = FieldFill.INSERT)
private Integer version;
//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
8.MyBatis-Plus的简单查询 ,简单条件查询,以及分页查询
分页查询:
1.需要在配置类中添加分页插件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
分页查询的使用:
public void testPage(){
//1.创建page对象
//注入两个参数: 当前页 和 每页显示记录数
Page<User> page =new Page<>(1,3);
//调动mp分页查询的方法
//把分页的所有数据封装到page对象里面
userMapper.selectPage(page,null);
//通过page对象获取分页数据
System.out.println(page.getCurrent()); //获取当前页
System.out.println(page.getRecords()); //获取当前页数据组成的List
System.out.println(page.getSize()); //获取当前页中记录长度
System.out.println(page.getTotal()); //获取表中所有记录长度
System.out.println(page.getPages()); //获取分页总页数
System.out.println(page.hasNext()); //判断是否有下一页记录
System.out.println(page.hasPrevious()); //判断是否有上一页记录
}
9.MyBatis-Plus的删除操作:分为物理删除,逻辑删除
物理删除
:直接删除数据库中的记录
逻辑删除
:使用标识符 表示记录已被删除,但是还存在于表中,逻辑删除的数据不能被查询,需要使用xml写复杂sql查询
逻辑查询:
1.在配置类中添加逻辑删除插件
//逻辑删除插件
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
2.在实体类中添加 标识符属性 deleted
3.使用 @TableLogic 注解标识 属性 deleted
4.逻辑删除是将数据库中标识符的值默认为0 改为1 ,底层通过条件查询deleted=0来剔除被删除的数据
10.Mybatis-Plus性能分析插件
性能分析:
1.在配置类中配置性能分析插件
2.在配置文件中配置当前开发环境 spring.profiles.active=dev
/**
* SQL 执行性能分析插件
* 开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长
*
* 三种环境
* dev: 开发环境
* test: 测试环境
* prod:生产环境
*/
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);//ms,超过此处设置的ms则sql不执行
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
11.Mybatis-Plus构造器查询 --复杂条件查询
复杂条件查询,推荐使用 QueryWrapper 构建条件
public void testWrapper(){
//1.创建对象
QueryWrapper<User> wrapper =new QueryWrapper<>();
//2.通过QueryWarper设置条件
//ge gt le lt >= > <= <
//第一个参数 字段名 第二个参数 设置值
// wrapper.ge("age",20);
//eq ne 等于 不等于
// wrapper.eq("name","张三");
// wrapper.ne("name","张三");
//between 范围查询
// wrapper.between("age",20,30);
//like 模糊查询
// wrapper.like("name","张");
//orderByDesc 降序排序
// wrapper.orderByDesc("id");
//last 追加sql语句
// wrapper.last("limit 1");
//select 指定要查询的列
wrapper.select("age","name","age");
List<User> users = userMapper.selectList(wrapper);
System.out.println(users);
}
1.项目概要:此项目使用前后端分离
2.前后端分离开发:
前端:html、css、js、jq
主要作用:数据显示
后端:controller、service、mapper
主要作用:返回数据或者操作数据
开发接口:指的不是interface,而是开发controller service mapper过程
前端使用ajax 调用接口 后端接口返回数据
3.执行sql脚本 导入数据,了解数据库规范
4.创建项目结构
项目结构:
创建父工程(pom类型 管理依赖版本和放公共依赖) --springboot工程
创建子模块 --maven工程
子模块一
子模块一
子模块二
字模块二
使用多层结构方式
5.开发讲师模块
创建项目结构
gulli_parent(父工程)
service(子工程)
service_edu(子工程)
6.使用MyBatis_Plus提供的代码生成器,生成相关代码
在测试类中执行此单元测试方法,会自动生成关于edu_teacher 表的相关组件
public class CodeGenerator {
@Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir"); //项目目录
gc.setOutputDir("D:\\IDEA\\workSpace\\GuliCollege\\guli_parent\\service\\service_edu" + "/src/main/java"); //输出目录 项目目录尽量使用绝对路径
gc.setAuthor("testjava"); //作者
gc.setOpen(false); //生成后是否打开资源管理器(文件夹)
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
//包 com.wqf.eduservice
pc.setParent("com.wqf");
pc.setModuleName("eduservice"); //模块名
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
//逆向生成实体类策略
StrategyConfig strategy = new StrategyConfig();
//对应的表名
strategy.setInclude("edu_teacher");
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略 下划线对应大写
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
7.在配置文件中修改相关配置
8.测试查询所有记录:
1.在controller中注入service
2.创建方法,使用service获取所有数据信息并返回
3.创建配置类,添加注解@MapperScan() 扫描所有mapper接口
4.创建项目启动类 添加注解@SpringBootApplication,在main方法中调用SpringApplication.run(xx.class,args);
5.在配置文件中配置时区和返回时间格式
#返回json的全局时间格式和时区配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
9.测试逻辑删除讲师记录
1.在配置类中配置逻辑删除插件
2.在实体类中添加 标识符字段 并添加@TableLogic注解
3.在控制类中编写方法,使用rest风格获取要删除的讲师id(@PathVariable("id"))
10.使用swagger进行接口测试
1.创建与service同层子模块common,并在common中创建子模块
2.创建配置类 配置Swagger接口测试器
/**
* Swagger接口测试器
* 可以生成接口文档进行测试
* @author 昭浅
*/
@Configuration
@EnableSwagger2 //开启Swagger
public class SwaggerConfig {
@Bean
public Docket webApiConfig(){
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApi")
.apiInfo(webApiInfo())
.select()
.paths(Predicates.not(PathSelectors.regex("/admin/.*")))
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build();
}
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("网站-课程中心API文档")
.description("本文档描述了课程中心微服务接口定义")
.version("1.0")
.contact(new Contact("Helen", "http://atguigu.com", "[email protected]"))
.build();
}
}
3.在pom文件中添加Swagger子模块依赖
4.在启动类中添加@ComponentScan()注解 扫描Swargger组件所在的包
5.在浏览器中使用固定地址 http://localhost:8080/swagger-ui.html 访问Swagger
6.测试相关API
7.定义接口说明和参数说明
定义在类上:@Api
定义在方法上:@ApiOperation
定义在参数上:@ApiParam
8.统一结果返回
1.在conmon模块创建子模块common_untils
2.创建接口,创建两个静态变量 SUCCESS,ERROR表示两种状态码
3.创建统一结果返回类型,创建相关属性 succss(布尔),code(Integer),message(String),data(HashMap)
4.将返回值类型构造器私有化
5.创建静态方法 ok(),error(),分别代表成功操作,错误操作
6.创建属性相关方法,返回值为 return this; 使用这种方式来达到 链式编程
r.success().code.message()...
7.在service模块中引入common_untils依赖
8.将控制器方法的返回值类型改为 R, 并在方法结束时调用R.ok() 或 error() 来设置返回值内容并返回 R 类型 ,查看导入的包,不要导错
9.使用Swagger测试Api,查看返回值类型
9.讲师分页查询,在配置类中配置分页插件,在控制器中创建相关方法
//创建page对象
Page<EduTeacher> page=new Page<>(current,limit);
//调用方法实现分页
//调用方法时候,底层进行封装,把分页的所有数据封装到page对象里面
teacherService.page(page, null);
long total = page.getTotal(); //获取表中所有记录数
List<EduTeacher> records = page.getRecords(); //h获取当前页中所有记录组成的list集合
最后将取得的数据封装到Map集合中,由R.data()将其返回
10.多条件分页查询,在分页查询的基础上,增加条件查询
1.在实际查询中,,会有很多的条件查询,可以将所有的条件封装为条件类
2.创建条件类,将所有的查询条件封装进去
3.创建对应的控制器方法,在参数中添加对应的条件查询类对象,spring会自动将参数封装进去
4.获取所有的查询条件值,判断是否为空,如果不为空,则将其添加至QueryWarpper封装类中
5.正常进行分页查询,,将warpper条件添加
6.在日常开发中,我们一般将条件查询改为post请求,所以,我们可以在条件参数前添加注解 @RequestBody(只能接受post参数) 来接收请求体中json参数
因为查询条件可能不存在 所以需要修改注释中的属性 required = false
11.实现添加讲师功能,在实体类中将时间属性添加注释 @TableFiled(fill = xxx) 并创建MetaObjectHandler实现类 实现自动填充
12.添加根据id查询讲师功能,添加根据id修改讲师功能
13.配置异常处理
1.在代码运行中可能会出现异常,我们需要配置全局异常处理
2.创建异常处理类,使用@ControllerAdvice 注解
3.创建异常处理方法,将异常进行处理,使用@ExceptionHandler 注解标识
4.异常处理方法返回值类型为 R 统一类型返回,所以需要引入依赖,所以在service模块中 由于依赖的传递,就不需要再重复引用common_utils依赖
@ResponseBody
@ExceptionHandler(Exception.class)
public R error(Exception e){
e.printStackTrace();
return R.error().message("执行了全局异常处理。。。");
}
1.继day02的全局异常处理,添加特定异常处理,自定异常处理
特定异常处理
@ResponseBody
@ExceptionHandler(ArithmeticException.class)
public R error(ArithmeticException e){
e.printStackTrace();
return R.error().message("执行了ArithmeticException异常处理。。。");
}
自定异常处理:
1.我们需要自定义一个异常
2.在异常处理器中添加自定义异常处理方法
3.需要在可能出错的代码处进行捕获异常,catch中手动抛出自定义异常
@ExceptionHandler(GuliException.class)
@ResponseBody
public R error(GuliException e){
e.printStackTrace();
//返回自定义异常的状态码和错误信息
return R.error().code(e.getCode()).message(e.getMsg());
}
2.日志
1.日志的记录是分等级的:
OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
默认情况下从控制台打印出的日志级别只有INFO及以上,我们可以在配置文件中配置日志级别
#日志级别
logging.level.root=warn
2.目前的日志只能在控制台输出,不能输出到指定文件中,所以我们需要使用日志工具来将日志输出到文件中
3. logback日志工具的使用:
1)删除在配置文件中关于对日志的配置信息 ,防止对日志 工具冲突
2)在resource中配置logback-spring.xml文件,修改日志信息写出文件位置
3)配置输出异常信息到日志文件
1.在异常处理器的类上添加 @Slf4j 注解
2.使用log.error(); 将错误信息输出到日志文件中
3.安装VSCode,使用VSCode开发项目前端,安装相关插件,创建工作区
4.es6的简要概述于作用
5.对于es6
和普通js
中定义变量
的区别
6.es6中对象简写方式,以及函数简写方式 (箭头函数)
7.讲解Vue的基本使用
8.VSCode vue的代码片段抽取,调高开发速度
9.学习Vue的指令
1.v-bind 单向数据绑定 简写方式: :+属性
2.v-model 双向数据绑定
3.v-on 绑定事件操作 简写方式 @+事件
4.vue修饰符 prevent 在事件后应用,阻止当前事件原本操作,进行指定操作
<form action="save" v-on:submit.prevent="onSubmitForm()">
5.v-if 条件判断 效果与v-show 相同 一般建议使用 v-if
6.v-for 循环遍历操作 可用来循环 ,遍历数组列表
7.vue路由组件的使用
1.axios 异步请求的简单使用
// axios.提交方式().then(箭头函数).catch(箭头函数)
使用json文件模拟响应数据,使其返回并显示
```·
2.element-ui的简单了解
3.学习 nodejs 及其安装
```java
1.什么是nodejs
1)类似于java 运行java需要安装jdk环境,学习的nodejs 是JavaScript的代码环境,
不需要浏览器,直接使用nodejs运行JavaScript代码
2) 可以模拟服务器效果 类似tomcat
2.nodejs的安装,使用控制台通过node命令测试js文件
3.npm的使用 (包管理工具)
1.nmp类似于maven 用来管理前端js依赖,控制版本,联网下载js依赖,比如jquery
2.构建前端项目 nmp init -y 使用默认方式初始化项目 生成package.json文件
3.修改npm 下载镜像 使用taobao镜像 提高下载速度
#经过下面的配置,以后所有的 npm install 都会经过淘宝的镜像地址下载
npm config set registry https://registry.npm.taobao.org
4.使用 npm install 命令下载 前端依赖
举例: npm install jquery 下载 jquery.js 依赖
5.在npm install 命令中,如果不指定下载依赖的版本,则会默认下载最新版本的依赖
使用 npm install jquery@2.1.x 来下载指定版本依赖
6.根据 package.json文件 自动下载依赖文件
使用 npm install 会读取package.json 中的依赖 进行下载
4.babel转码器的使用
1.babel转码器的作用:
由于es5对于浏览器的兼容性更强,但是es6的开发更为方便,所以在实际开发中,我们使用es6进行开发,
使用 babel转换器 将es6语法转码为es5语法
2.babel转换器的安装
npm install --global babel-cli
使用 babel --version 查看是否安装成功
3.在前端项目中创建 .babelrc 配置文件(文件名称固定)
添加配置
{
// presets字段设定转码规则,将es2015规则加入 .babelrc:
"presets": ["es2015"],
"plugins": []
}
4.安装转码器
npm install --save-dev babel-preset-es2015
5.使用命令进行转码
根据文件转码: babel 01.js -o 02.js 01.js为将要转换的文件,02.js为转换后的文件
根据文件夹转码:babel es6 -d dist es6为将要转换的文件夹,dist为转换后的文件夹
6.模块化
1.模块化是什么:
1)开发后端接口(controller、service、mapper)时,类与类之间的调用成为后端模块化操作
2)前端模块化,在前端中,js与js之间调用成为前端模块化操作
2. js文件之间如何调用
es5实现模块化操作:
1)创建js文件,在其中声明成员方法
2)在其他js文件中使用 const m =require('./01.js') 导入需要调用的js文件
3)调用导入的文件对象m 使用m对象中的方法
4)在控制台中 使用 node命令 执行js文件 测试是否调用js文件成功
7.es6实现模块化的两种方法:
注意:如果使用es6来实现模块化操作,在nodejs环境中是不能直接运行的,
也就是说nodejs环境不支持es6的模块化操作,需要使用babel将es6代码转为es5代码,
才可以在nodejs中进行运行
方式一:
export function save(){ 表示该方法可以被其他js文件引入
console.log('save.....')
}
//引入01 js文件 中的方法
import { getList,save } from "./01.js";
//调用方法
getList()
方式二:
//指定可以被其他js文件所引入的方法
export default{
getList(){
console.log('getList....')
},
update(){
console.log('update.....')
}
}
//调用01.js的方法 引 入01.js文件进行调用
//引入01 js文件 中的方法
//es6 写法二
import m from './01.js'
//调用方法
m.getList()
8.了解 Webpack
* 前端资源加载、打包工具,
* 将多种静态资源 js,css,less转换成一个静态文件
9.Webpack的基本使用 --打包js
1.创建三个js文件 common.js ,utils.js ,main.js
2.在main.js中引入另外两个js文件
3.创建配置文件,配置打包信息
4.执行命令进行打包
webpack / webpack --mode=development(没有警告)
5.在html文件中引入打包好的文件 进行测试
配置文件
const path = require("path"); //Node.js内置模块
module.exports = {
entry: './src/main.js', //配置入口文件 程序打包入口
output:{
path: path.resolve(_dirname,'./dist'), // 输出路径: _dirname:当前文件所在路径
}
}
10.Webpack的基本使用 --打包css
1.创建css文件
2.在main.js文件中引入css文件
3.安装css加载工具
npm install --save-dev style-loader css-loader
4.在配置文件中添加配置
module:{
rules:[
{
test:/\.css$/, //打包规则应用到以css结尾的文件上
use: ['style-loader','css-loader']
}
]
}
5.重新打包,打开html文件进行测试
11.搭建项目前端页面环境
1.解压前端模板(框架)进行环境搭建
2.将框架文件复制到VScode工作区中
3.通过VSCode的终端打开解压文件夹,进行依赖的安装
4.启动项目
npm run dev
1.前端页面环境说明
1.前端框架入口(两个)
index.html / main.js
2.vue-admin-template模板主要基于两种技术实现
.vue-admin-template模板 = vue + element-ui
3.前端框架重要文件
- vue-admin-template-master
* build目录 (放项目构建的脚本文件)
* config目录
+ index.js (项目中的基本配置文件) 需要修改 userEslint=true 为 false 取消代码格式自动检查
+ dev.env.js (项目启动环境配置文件 可修改访问后端接口地址,我们使用的启动命令使用的环境为dev npm run dev)
* src目录
+ api目录 (定义调用方法)
+ assets (放置静态资源)
+ components (放一些组件,额外的插件)
+ icons (项目中使用的相关图标)
+ router (vue路由)
+ views (项目中一些具体的页面)
2.前端模板路径问题(默认路径会报错,需要更换路径,使用自己的路径),以及创建对应接口方法进行测试
3.了解跨域问题,以及怎样解决跨域问题
跨域问题:
通过一个地址去访问另一个地址,这个过程中如果有三个地方中的任何一个地方不一样,就会产生跨域问题
1.访问协议: http https
2.ip地址:192.168.1.1 172.12.1.1
3.端口号: 9528 8001
如何解决跨域问题:
1.在后端接口controller中添加注解 @CrossOrigin (常用)
2.使用网关(SpringCloud的网关)
4.前端框架使用过程
1.添加vue路由
2.点击某个路由,显示对应页面内容
3.在前端项目api目录中创建js文件,定义接口地址和参数
4.创建vue页面,引入js文件,调用方法实现功能
5.讲师列表的前端实现
1.添加路由
2.创建对应的vue页面并引用
3.在api文件夹中创建teacher.js 定义访问的接口地址
4.在讲师列表 list.vue页面调用定义的接口方法,得到接口返回的数据
5.把请求接口获取的数据在页面进行显示
使用组件 element-ui实现
6.使用element-ui的分页组件进行分页查询并显示
7.使用element-ui的条件查询组件进行条件查询,在表格上面添加条件查询点的表单,以及清空查询条件
6.讲师记录的删除
1.在每条记录后面添加 删除按钮
2.在按钮绑定事件
3.在绑定事件的方法传递删除讲师的id值
4.在api文件夹teacher.js中定义删除讲师的接口地址
5.设置删除按钮的提示信息,以及删除后跳转的页面
7.添加讲师功能
1..点击添加讲师按钮,点击进入表单页面,输入讲师信息
2.在teacher.js中定义接口方法的地址,将teacher对象转化为json
3.在页面中实现调用对应的方法
4.在后端程序中使用创建时间进行倒序排序
8.讲师修改功能
1.在每条记录后添加 修改按钮
2.点击修改按钮,进入表单页面,进行数据回显
3.通过路由跳转进入数据回显页面
4.在表单页面中实现数据回显,在页面调用接口实现数据回显
5.因为添加修改都是用的是save页面,区别添加还是修改,只有修改时查询数据回显
判断路径中是否有id参数值
6.创建修改方法,判断当前操作执行的是添加还是修改
9.路由问题
1.点击修改按钮后,再点击添加按钮会页面表达中的数据不会被清空
2.使用vue的监听来解决,监听路由的变化
1.对象存储OSS, 开通对象存储OSS服务
2.创建service_oss模块, 测试文件上传
1.引入相关oss依赖
2.创建配置文件,配置相关配置项
3.创建启动类,解决启动时可能发生的错误(没有配置数据源)
* 1)添加数据库相关配置项
* 2)启动类上添加属性 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
4.创建controller service 实现对应的方法,返回上传文件的地址
根据阿里云文档 实现service中上传文档的具体操作,最后返回文件的地址
5.使用UUID拼接文件名,使用日期将文件进行文件管理
3.大概了解 Nginx 反向代理服务器,请求转发,负载均衡,动静分离
4.Windows 版的 Nginx
安装,修改相关配置
1.在conf文件中打开ngxin.conf
2.在http项目-》server 中修改 listen 为9001 修改默认端口号,避免端口冲突
server {
listen 9001; // 避免端口冲突
server_name localhost;
3.在server中添加nginx地址配置,根据请求地址映射到不同的服务器 (不同的端口号)
location ~ /eduservice/ { // ~ 表示模糊匹配
proxy_pass http://localhost:8001
}
4.在前端项目中,更改前端请求地址,改为Nginx地址
4.添加上传头像功能
1.在添加讲师页面,创建上传组件,实现上传
在vue-element-admin-master 中寻找文件上传组件并导入
2.在添加讲师页面添加相关组件代码,在显示出文件上传的组件
3.使用组件,在data中定义变量及初始值
4.引入组件并声明
5.修改上传接口地址,编写close方法和上传成功方法
5.了解Easy Execl的读取和写入
Easy Excel是对 poi 的封装,是用来对execl进行操作的框架
6.实现课程分类添加功能
1.引入easyexcel依赖,以及poi等相关依赖
2.使用代码生成器生成课程分类的代码
3.创建与excel表格数据对应的实体类
4.在service层创建对应方法读取excel文件,创建监听器
5.解决一级分类和二级分类的添加问题
1.添加课程分类模块
1.创建页面路由,修改路由对应的页面路径
2.实现课程添加模块,添加上传文件组件,连接上传文件接口,读取文件写入数据库中
3.实现课程分类模块,通过接口获取课程信息,在页面进行分类显示
1)根据返回类型创建一级分类,二级分类的实体类,实现一对多的关系
2)创建接口返回list集合数据,对一级分类,二级分类进行封装
3)测试接口返回数据
4.添加课程列表页面,将接口返回数据显示在页面中
2.了解课程管理模块需求分析,分步确认,最后提交
3.课程管理-添加课程基本信息
1.使用代码生成器,生成课程相关代码
2.创建vo类,用于封装表单提交的数据
3.编写Controller和service,实现数据保存
1) 在service层中,将vo类中的信息分别存储到两张数据表中
2)修改课程描述表的id生成策略,使课程信息与课程描述有一对一的关系
4.课程添加前端实现
1.添加页面路由,再添加相关隐藏路由,实现页面步骤跳转
2.实现三步各个页面,点击按钮实现跳转
3.编写表单页面,实现接口调用,返回课程id
4.调用接口返回讲师列表数据,实现下拉讲师列表,存储讲师id
5.实现讲师下拉列表,显示不同分类级别讲师
6.添加封面组件,实现自动上传封面图片到oss服务器中
7.至此,完成第一页课程信息添加功能
1.在课程添加页面中,添加富文本编辑器组件,并使用
2.在后端实现接口,根据课程id 返回该项课程中的所有章节以及他的小结信息
3.在前端项目中创建对应的 js 文件,映射对应的接口,在页面中通过接口获取章节信息以及小节信息
4.通过路由路径中的id获取章节信息和小节信息后在页面上遍历输出
5.修改课程基本信息,进行课程基本信息的回显,在数据回显页面点击保存会修改此课程
1.在api中定义两个接口方法
2.修改chapter页面的跳转路径
3.获取路由路径中的课程id 在info页面实现数据回显
4.解决回显数据时,二级分类没有被初始化的问题,讲师列表没有被初始化的问题
5.实现数据回显后进行更改,提交后对表中数据进行修改,通过判断是否存在courseId来进行增加还是修改记录
6.在创建课程大纲页面中,创建按钮,实现添加章节功能
1.在后端实现对于章节的增加,修改,查询接口
2.对于章节的删除
1)方式一:可以直接删除章节以及章节下的所有小节
2)方式二:可以先判断此章节下是否存在小节,如果没有就直接删除,否则不能删除
3.实现前端接口,完成章节的添加功能
7.章节的修改功能
1.在前端实现接口,创建添加按钮,完成操作,注意使用@RequestBody 注解 才可接受请求体中的参数
8.章节的删除功能
1.章节的删除,实现接口,添加删除按钮,删除章节后刷新页面
9.添加 添加小节按钮 实现点击按钮提示弹窗,实现前端后端接口
10.实现小节中的编辑按钮和删除按扭,实现其功能
11.在后端Mapper中创建方法来获取课程中所有的相关信息
1.在Mapper接口中创建方法,在mapper.xml文件中实现sql语句,始终左外连接的方式查询课程的所有信息
2.mapper.xml文件在mapper包中 ,在Maven打包的机制下不是。java文件不会被打包
Maven默认加载机制:只会把src-main-java文件夹中的java类型文件进行加载,其他类型文件不会加载
解决方法:
1) 复制xml到target目录中
2)把xml文件复制到rescources目录中
3)通过配置文件进行配置,让maven默认加载xml文件
* 在pom.xml文件中进行配置 配置扫描文件目录中的xml文件
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/ *.xml</include> 去掉空格!!!!
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
* 在项目的application.properties中配置
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/wqf/eduservice/mapper/xml/*.xml
1.实现前端接口,根据课程id获取到所有课程相关信息,并显示在页面
2.实现课程最终发布,更改课程发布状态
3.创建前端课程列表页面,显示所有课程信息列表
4.自行完成关于课程列表中课程信息的编辑功能
5.实现后端接口方法,完成删除课程信息操作,并在前端页面中实现接口,完成删除操作
1.采用外键的方式,来达成删除课程相关所有表中信息的操作
* 只使用外键点的逻辑知识,不真正使用外键
2.按照 小节-章节-课程的顺序 依次删除课程信息
3.在前端页面调用接口,完成删除
6.了解阿里云视频点播服务
1.服务端:后端接口
客户端:浏览器、安卓、ios
2.API:阿里云提供固定的地址,只需要调用这个固定的地址,向地址中传递擦书,实现功能
SDK:sdk对api进行封装,跟方便使用,类似之前使用过的EasyExcel直接调用类或方法,调用阿里云提供的类或接口中的方法实现视频功能
7.测试实现阿里云的视频上传点播功能
1.在后端创建视频点播模块,引入相关依赖
2.进行初始化操作,创建DefaultAssClient对象
3.根据视频id获取视频播放地址 GetPlayInfoRequest
4.根据视频id获取视频凭证 GetVideoPlayAuthRequest
8.测试阿里云视频上传功能
1.阿里云视频上传依赖不是开源的,需要自行下载并安装到Maven仓库
在jar包所在的目录中打开cmd窗口,输入以下指令
mvn install:install-file -DgroupId=com.aliyun -DartifactId=aliyun-sdk-vod-upload -Dversion=1.4.11 -Dpackaging=jar
-Dfile=aliyun-java-vod-upload-1.4.11.jar
2.通过阿里云文档测试视频文件上传功能
9.在项目中整合视频上传功能,创建vod模块,实现视频上传接口
1.创建vod模块,引入依赖
2.填写配置文件
3.创建启动类
4.实现对象接口方法,实现视频上传功能,在配置文件中修改文件上传大小限制,注意文件上传文件大小限制
5.使用swagger-ui进行测试
10.前端添加视频上传组件完成视频上传功能
1.在前端添加组件,完成视频上传功能
2.实现视频上传接口
3.添加nginx对应代理的后端端口请求地址
location ~ /eduvod/{
proxy_pass http://localhost:8003;
}
4.更改nginx默认的请求体大小限制
#配置nginx上传请求体内容大小限制
client_max_body_size 1024m;
1.实现后端接口,根据视频id删除阿里云中的视频
2.实现前端接口,完成点击按钮删除阿里云中的视频,解决一些小bug
3.了解什么是微服务
微服务:
1.一种架构风格
2.有多个服务,每个服务运行在自己独立的进程中,互不打扰,独立运行
把一个项目拆分成独立的多个服务,多个服务是独立运行,,每个服务占用独立进程,
微服务与单体架构的区别
1)单体架构所有模块全都耦合在一起,代码量大,维护困难
微服务每个模块就像一个单独的项目,代码量明显减少,遇到问题也好解决
2) 单体架构都是共用一个数据库,存储方式单一
微服务每个模块都可以使用不同的存储方式,比如mysql,redis等,数据库也是单个模块对应自己的数据库
3)单体架构开发所使用的技术都是一样的
微服务每个模块都可以使用不同的开发技术(比如有的模块使用java,有的使用python),开发模式更灵活
4.了解SpringCloud
1.SpringCloud并不是一种技术,是很多技术的总称,很多技术的集合
2.SpringCloud里面有很多框架(技术),使用SpringCloud里面这些框架来实现微服务的操作
3.使用SpringCloud,需要依赖SpringBoot
SpringBoot是spring快速配置的脚手架,SpringCloud是一个基于SpringBoot实现的开发工具
4.SpringCloud与SpringBoot有版本对应关系
5.SpringCloud中相关基础服务组件
5.了解SpringCloud中的组件Nacos(注册中心)
不同模块互相调用方法,独立运行,不进行引用
Nacos:注册中心
类似于 房产中介-租户和房东之间的桥梁
实现不同微服务模块之间的调用,把这些模块在注册中心进行注册,注册之后,实现互相调用
Nacos 代替了SpringCloud原生的注册中心 Eureka
模块与模块之间的关系:
生产者:提供方法的模块
消费之:调用方法的模块
Nacos执行流程:
6.Nacos的安装与使用,进行服务注册
1.安装Naocs
2.使用默认地址打开管理页面
默认地址:http://localhost:8848/nacos
账号密码:nacos/nacos
3.注册service-edu服务到Nacos中
4.在pom文件中引入服务注册依赖
5.在配置文件中添加nacos地址
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
6.在想要注册的服务模块的启动类上天添加注释
@EnableDiscoveryClient //Nacos注册 注解
7.启动服务,在nacos管理地址中查看注册的服务
8.注意 引入nacos依赖后,如果不对模块进行配置,不添加注解等,会报错 no server available !!!但是不影响运行
7.服务调用
服务调用的代码是写在服务调用端
1.引入服务调用依赖
2.在调用服务端的启动类上添加 服务调用注解 @EnableFeignClients //服务调用 注解
3.在调用端 创建interface,使用 @FeignClient(name="service-vod")注解指定调用服务的名称,
定义调用的方法路径,要写调用方法的完全路径
@DeleteMapping("/eduvod/video/reomveALiYunVideo/{id}")
public R removeAliYunVideoById(@PathVariable("id") String id); //@PathVariable注解一定要指定名称,否则会报错
4.在controller中注入接口,调用方法删除视频
8.创建接口,实现批量删除阿里云视频
1.创建接口,传入List类型参数id集合,在方法中使用字符工具类将集合转换为逗号相隔的字符串
2,传入字符串参数,调用方法,批量删除视频
3.在使用服务调用时。必须完全补充参数或是路径等
List为参数类型时,要明确指出他的泛型,restful参数使用@PathVariable注解时要指定他的参数名称,
引入其他服务中的方法时,要补全路径等,否则会报错
9.了解SpringCloud调用接口的过程
Spring Cloud 在接口调用上,大致会经过如下几个组件配合:
Feign ----->Hystrix —>Ribbon —>Http Client(apache http components 或者 Okhttp)
提高容错和延迟
1.在调用的服务宕机时,会执行其他操作
2.在调用的服务延迟较高,返回数据较慢时,可以设置最大等待时间
添加熔断器机制
1.添加熔断器依赖Hystrix,添加负载均衡依赖ribbonn
2.在配置文件中开启熔断器,设置超时时间
#开启熔断机制
feign.hystrix.enabled=true
# 设置hystrix超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
3.实现调用服务的接口,并实现方法
4.在调用服务接口的注释中添加 fallback属性
//name 表示调用的服务的名称,fallback表示调用服务失败后,调用哪个类中的方法
@FeignClient(name="service-vod",fallback = VodFileDegradeFeignClient.class) //指定将要调用的服务的名称
5.关闭调用的服务,测试熔断机制
1.了解NUXT框架,搭建前台环境
1.ajax是异步刷新,可能存在数据还未返回完,搜索引擎已经将数据返回了,不利于SEO
SEO: 根据搜索的匹配度等策略按顺序返回数据
2.NUXT:对node.js进行封装的框架,服务端渲染技术,将数据一次性直接返回给客户端,解决SEO问题
2.配置NUXT前端项目
1.将模板文件复制到工作区
2.修改package.json 文件
3.使用npm install 命令下载配置文件中的相关依赖
4.使用 npm run dev 命令启动项目进行测试
3.NUXT目录结构
-- .nuxt (编译好的文件)
-- asset (存放项目中使用的静态资源 css js img)
-- components (放项目中使用的相关组件)
-- layouts (定义网页布局方式 布局页面,将pages中的页面引入)
-- pages (项目中的页面,layouts布局页面中的中间部分)
-- nuxt.config.js (nuxt框架核心配置文件)
项目页面: (default.vue设置布局方式)
头信息
nuxt标签-----> <ifream>标签 -> index.vue
尾信息
4.整合前端项目页面
1.安装幻灯片插件(轮播图) --指定版本
npm install vue-awesome-swiper@3.1.3
2.配置插件 引入Vue和轮播图插件,并在nuxt.config.js配置文件中配置相关属性
3.将布局代码和页面代码分别复制到vue页面
4.运行项目 测试页面效果
5.了解Nuxt路由
1.固定路由 (路径是固定地址,不发生变化)
在pages里创建文件夹 course 在其中创建index.vue文件 使用固定路由 /course 会自动访问course下的index.vue页面
2.动态路由 (路径是动态生成的,比如使用每个课程id)
Nuxt的动态路由是一下划线开头的vue文件,参数名为下划线后边的文件名
6.实现数据banner显示(轮播图)
1.在service中创建service_cms子模块
2.创建application.properties配置文件,填写相关配置
3.实现相关接口方法,对Banner增删改查
4.创建接口,实现查询返回名师和课程功能
7.前端页面准备工作,安装axios依赖,封装axios
1.使用命为Nuxt框架安装axios插件
npm install axios
2.创建utils/request.js文件,编写代码,封装axios
8.前端实现接口,显示轮播图
1.创建api文件夹,创建js文件,定义调用接口路径
2.在主类中使用 @MapperScan注解时,要注意扫描到具体的mapper包,否则 该注解会将所有的interface接口都注册到ioc容器中,会存在多个service的类型
3.配置nginx中的映射地址
4.调用接口获取数据,在页面中显示数据
9.回顾Redis
1.基于key-value存储
2.支持多种数据结构:string(字符串),list(列表),hash(哈希),set(集合),zset(有序集合)
3.支持持久化,通过内存进行存储,也可以存储到硬盘中
4.支持key过期时间,支持事务
5.一般来讲,把经常进行查询,不经常修改,不是特别重要的数据放到redis作为缓存
10.SpringBoot整合Redis
1.在common包中创建配置类,使用@EnableCaching注解开启缓存功能
2. 配置类继承 CachingConfigurerSupport
3. 实现Redis具体方法 RedisTemplate
4. 在查询所有banner的方法上面添加缓存注解 @Cacheable
@Cacheable(value:"banner",key="indexList") 先在缓存中查看是否有数据,有数据就返回,没数据就到数据库中查询数据
value属性:表示缓存名
key属性:表示缓存的数据的key名字
在redis中 会以 value::key 的形式作为查询到数据的key进行存储(banner::indexList)
5.修改redis配置文件,保证可以外部服务访问,关闭虚拟机防火墙
6.在service_cms中配置redis相关配置
7.启动服务测试效果
1.了解单点登入
1.对于一个项目来说,有很多不同的服务(模块),在登入时,只需要登入一个服务,在其他服务中就会自动登入,不需要在此登入
2.单一服务器模式 单点登入
使用session对象实现 session.setAttribute("user",user)/session.getAttribute("user")
登入成功后,将用户数据存放到session域中
在其他服务中判断是否登入,只需要从session域中获取数据,就可以获取到登入
3.集群部署 分布式
采用微服务,分布式,将项目分成不同的小服务(模块),之间互不打扰,并运行在不同的服务器上
在登入其中的一个模块后,其他服务器上的模块就不需要再登入,
2.单点登入的实现(SSO(single sign on)模式)
单点登录的三种常见方式
一.session广播机制实现
session数据的复制,浪费资源,已弃用
二.使用cookie+redis实现
1.在项目中的任何一个模块进行登录,登录后,将数据放到两个地方
1)redis 生成唯一随机值作为key 将用户数据作为value 进行存储
2) cookie 把redis中生成的key值放到cookie里面
2.访问项目中其他模块,发送请求时都会带着cookie进行发送获取到cookie值,使用cookie值做事
1) 使用cookie获取的值,到redis中进行查询,根据key进行查询,如果查询到数据就是登录
三.使用token(令牌机制)实现 (自包含令牌)
token:按照一定规则生成字符串,字符串包含用户信息
1.在项目某个模块进行登录,登录之后,按照规则生成字符串,把登录之后用户数据包含到生成字符串里面,把字符串返回
1)可以把字符串通过cookie返回
2) 把字符串通过地址栏返回
2.再去访问项目其他模块时,每次访问在地址栏带着生成的字符串,在访问模块里获取地址栏字符串,根据字符串获取用户信息,如何可以获取到就是登录了
3.了解JWT令牌
1.token是按照一定规则生成字符串,包含用户信息,规则是多样的
一般采用通用的规则,官方规则 JWT
2.JWT就是给我们规定好的规则,使用JWT规则可以生成字符串,包含用户信息
3.JWT结构 JWT生成字符串包含三部分
第一部分 JWT头信息
第二部分 有效载荷 包含主体信息(用户信息)
第三部分 签名哈希 防伪标志
4.了解学习JWTUtil类 及方法
4.了解阿里云短信服务
需要备案才能使用,所以目前使用测试版
5.创建service-msm模块实现相关功能
1.创建service_msm模块,引入相关依赖
2.实现对应接口,完成功能
3.引入RandomUtil类生成随机验证码
4.实现send方法设置对应参数,调用阿里云方法实现发送验证码
5.创建接口,实现用户登入功能
1.创建service-ucenter模块,创建数据表
2.使用代码生成器生成相关代码
3.实现接口完成登录功能,返回token字符串
4.注意可能会出现的bug:在使用@RequestBody注解时,请求方式只能是Post,否则会接收不到请求参数值
6.创建接口,实现注册功能
1.创建Vo类,接受注册信息
2.创建接口,实现注册功能
3.获取service_msm服务中的redis缓存验证码,与输入验证码进行比对
4.创建接口实现从token获取用户信息
7.创建前端页面,显示登入注册页面
1.在pages中创建登入注册页面
2.修改default.vue中路径,映射到登入注册页面
3.安装element-ui等插件,修改nuxt-cinfig.js配置文件
8.前端创建接口,实现具体登录注册具体功能
1.创建register.js,login.js映射对应接口方法,在页面中引入具体方法
2.了解js定时器的使用 每隔一段时间执行一次js方法,实现倒计时效果
3.实现发送验证码方法
4.测试注册功能
1.前端项目实现接口,完成登录功能
1.创建js文件映射到后端接口,完成前端登入方法
2.了解使用token+cookie实现单点登入的流程
1.调用接口登录返回token字符串
2.将返回token字符串存放到cookie中
3.创建前端拦截器,判断cookie中是否有token字符串你,如果有,把token字符串放到Header(请求头)中
4.根据token值,调用接口,根据token获取用户信息,为了首页面显示,将根据token字符查询到的用户信息存放到cookie中
5.在首页显示用户信息,从cookie中获取用户信息
3.实现获取token 完成登录用户数据回显
1.创建方法实现登录功能
2.request.js添加拦截器获取cookie中值并设置到header中
3.根据token值获取登录用户信息,跳转至主页面
4.读取cookie信息 回显用户信息
5.实现退出功能,清空cookie值 实现退出
4.了解OAuth2
1.OAuth2针对特定问题的一种解决方案
2.OAuth2主要可以解决两个问题
1)开发系统间的授权
2)分布式访问问题(单点登录)
5.了解使用微信扫码登录
1.在配置文件中配置微信对应地址信息等,生成微信二维码
2.请求微信固定地址,生成二维码(目前使用地址是老师的地址,个人微信地址需要认证)
3.将redirect_uri的地址改为localhost:8160
4.返回字符串 重定向至 二维码的地址 输出图片测试
6.扫描微信二维码,修改地址
1.学习中的微信地址是老师写的程序重定向了其他地址 所以需要修改对应端口号和地址相同
http://localhost:8160/api/ucenter/wx/callback
2.修改服务端口为8160 扫码完成后要自动跳转请求8160端口
3.扫码后会返回两个参数 code(类似于微信的随机验证码),state(原样传递)
4.拿着code值请求固定微信地址,返回两个值(使用HttpClient)
access_token:访问凭证
openid:每个微信的唯一标识
5.拿着上面获取的两个值,再去请求微信固定地址获取登录人信息
使用gson将获取到的字符串转换为map,获取到上面两个变量的值,然后请求其他地址去获取用户信息
6.获取扫码人的信息,判断数据库中是否存在信息 没有则添加
7.解决cookie跨域问题
1.根据微信信息,使用JWT生成token字符串,把token字符串通过路径传递到首页面
8.通过微信返回的token进行登录
1.获取首页页面路径中的token字符串
this.$router.query.token
2.将获取到的字符串放到cookie里面,前端拦截器会判断cookie中是否有token 如果有,把cookie中token获取除开,放到header中
3.调用后端接口,根据token值获取用户信息
1.实现接口,返回分页数据,实现分页功能
2.实现接口 点击教师通过接口获取教师id 完成显示教师详情页面
2.实现条件查询课程分页功能
1.创建VO对象,用来接收条件查
2.实现接口方法,返回课程分页数据
3.在前端实现接口接收数据并显示
4.获取一级分类,并显示
3.实现级联显示 点击一级分类会显示二级分类,点击二级分类查询功能
1.创建js文件,引入接口地址,在页面进行调用
2.显示一级分类,一级分类显示二级分类
3.实现接口,获取二级分类id 将分类信息赋值给条件查询对象
4.调用方法进行查询
4.实现显示课程详情功能
1.点击课程返回课程id
2.后端实现接口返回课程相关信息
3.编写sql语句,查询课程详细信息,返回课程小节信息
4.将返回的课程信息以及课程的小节信息一起显示在页面上
5.前端使用阿里视频点播测试
1.根据视频id获取视频凭证,根据视频凭证播放视频
2.点击小节获取小节视频id,通过id获取凭证
3.前端添加 _vid.vue页面。通过视频id和凭证播放视频,设置视频格式参数
1.独立完成课程评论功能
1.评论时先判断用户是否登入,未登录跳转登录页面
1)远程调用service-ucenter模块中的方法(远程调用会默认将请求方式转换为 POST 请求)
2)远程调用不能使用 HttpServletRquest 作为请求参数类型
2.获取登录用户相关信息以及课程信息,存储到数据库中,刷新页面
2.实现课程购买和订单功能
1.分析需要实现的接口
生成订单接口,根据订单id查询订单信息接口,生成微信支付二维码接口,查询订单支付状态接口
2.远程调用service_edu模块,service_ucenter 查询课程信息和用户信息生成订单
3.添加相关注解开启服务注册和远程调用
4.根据订单号查询订单信息
5.整合前端页面,创建js文件,生成订单信息,返回订单编号,显示页面,要先登录才能获取用户信息
3.实现微信支付功能
1.创建接口生成微信支付二维码,设置相关参数,使用map集合返回相关数据
2.实现接口查询订单状态,支付成功修改订单状态,添加购买记录
3.前端创建接口获取二维码数据,显示支付二维码
4.前端创建计时器,每三秒查询支付状态,定义响应拦截器,判断响应码是否是25000 根据响应码判断支付是否成功
5.返回成功,取消定时器查询
1.查询用户是否购买课程,远程调用查询购买状态,决定显示购买还是观看
2.通过查询返回统计信息,在后台页面显示出来
1.使用Date()时间函数查询时间,而不用like模糊查询
2.将查询到的数据返回给统计服务,统计服务进行存储
3.增加前端后台管理路由
1.创建js,实现接口映射后端得到返回数据
2.调用方法,成功返回数据并跳转到图标显示页面
4.了解定时任务,固定时间自动执行程序
1.在启动类上添加注解
@EnableScheduling //开启定时任务注解
2.创建定时任务类,创建方法,在方法上使用@Scheduled(cron = "0/5 * * * * ?") 使用表达式设置什么时候执行
1)@Scheduled注解 指定多长时间执行一次方法
2) cron表达式[七子(/域)表达式],设置执行规则
3) 设置定时任务,每天凌晨一点对注册数据今天添加
5.了解ECharts 官网:echarts.apache.org
6.编写后端接口,根据查询类型返回对应的数据,时间和数量,前端调用接口返回数据,使用echarts插件将数据显示出来
1.了解 Canal
数据同步工具,将远程调用服务的数据库同步到本地库中,当远程库中表数据发生变化,本地库中数据也会发生变化
2.数据同步环境准备
1.canal会将不同服务器中的两个相同结构的数据库进行同步,使用linux和windowss不同的mysql,创建相同的库和表进行测试
2.需要创建一个可以远程连接的mysql用户
3.安装Canal工具
4.创建服务 canal_clientedu 引入相关依赖,配置相关配置文件,复制好相关的类并运行
5.在linux系统mysql中进行增删改操作,测试windows表中会不会同步数据
3.了解 gateway网关
1.什么是网关
客户端和服务端的一面'墙',可以做到请求转发,负载均衡,权限控制等
2.将服务在nacos中进行注册,使用gateway网关进行调用
4.配置gateway网关服务
1.创建新模块,引入gateway相关依赖等,创建启动类,开启nacos服务注册
2.创建启动类,配置相关注解,开启nacos服务注册,在配置文件中开启服务发现,配置各个服务的路由
3.启动测试网关
4.了解负载均衡:轮询,权重,最小请求时间
5.添加配置类,解决跨域问题,解决权限控制问题
1.使用配置类解决跨域问题后不能再向controller中添加@CrossOrigin注解
6.了解权限管理需求,了解各种表之间的关系
7.创建新模块,查询所有菜单,呈属性结构显示所有菜单
1.实现接口创建方法,使用递归查询级联菜单
2.使用递归进行删除
3.使用递归将角色和路由添加到数据库
1.了解Spring Security框架,用户认证与用户授权功能
1.用户认证:
用户登录时,对用户名和密码进行校验,如果输入正确,则认证成功
2.用户授权:
登录系统后,登录的用户可能是不同的角色,比如登录的用户可能是管理员,也可能是普通用户,管理员的操作肯定比普通用户多很多
3.Spring Security本质上就是过滤器Filter,对请求进行过滤
2.Spring Security的底层原理
使用基于token的形式进行授权与认证,用户根据用户名和密码进行登录并认证成功,
获取当前登录用户的一系列权限值等,并以用户名为key,权限列表为value的形式存入redis缓存中,
根据用户名相关信息生成token值并返回,浏览器将token值存入cookie中,每次api调用接口都默认将token携带到header请求头中
,Spring Security解析header头获取token值,解析token值获取当前用户名,
根据用户名就可以从redis中获取权限列表,这样Spring Security就能判断当前请求是否有权限访问