项目总结 -谷粒学院
项目总结-谷粒学院重点技术总结,不拖泥带水,不讲curd在线教育系统,分为前台网站系统和后台运营平台,B2C模式。前台用户系统包括课程、讲师、问答、文章几大大部分,使用了微服务技术架构,前后端分离开发。后端的主要技术架构是:SpringBoot + SpringCloud + MyBatis-Plus + HttpClient + MySQL + Maven+EasyExcel+ nginx前端的
谷粒学院
项目总结-谷粒学院(前后端分离)
1、项目描述
在线教育系统,分为前台网站系统和后台运营平台,B2C模式。
前台用户系统包括课程、讲师、问答、文章几大大部分,使用了微服务技术架构,前后端分离开发。
后端的主要技术架构是:
SpringBoot + SpringCloud + MyBatis-Plus + HttpClient + MySQL +
Maven+EasyExcel+ nginx
前端的架构是:
Node.js + Vue.js +element-ui+NUXT+ECharts
其他涉及到的中间件包括
Redis、阿里云OSS、阿里云视频点播
业务中使用了ECharts做图表展示,使用EasyExcel完成分类批量添加、注册分布式单点登录使用了JWT
项目前后端分离开发:
后端采用SpringCloud微服务架构,持久层用的是MyBatis-Plus,微服务分库设计,使用Swagger生成接口文档
接入了阿里云视频点播、阿里云OSS
系统分为前台用户系统和后台管理系统两部分:
前台用户系统包括:首页、课程、名师、问答、文章。
后台管理系统包括:讲师管理、课程分类管理、课程管理、统计分析、Banner管理、订单管理、权限管理等功能。
前端
我是用vue进行开发的
-
使用Element-UI快速搭建模板样式
-
使用了Nuxt轻量级框架
-
使用node成为js的一个运行环境,将前端部署在node上
为什么使用Nuxt呢?Nuxt有什么特点会让你使用?
答:Nuxt也就是服务器渲染技术也可以充当静态站点引擎,它可以很好的解决SEO问题,SEO简称(搜索引擎优化)
比如说我前端显示一张图片,是通过ajax异步请求得到数据的,抓取工具并不会等待异步完成后才对页面内容进行抓取。
而用服务器渲染技术,我们无需等待所有的js加载完后执行,而是在服务端中通过node.js将我们查询出来的数据全部封装,
然后一次性返回到前端获得更快的内容到达时间,这就是NUXT的简单操作流程,而且都是在服务端中实现的。
axios拦截器
axios的拦截器特性
1)request请求拦截
当我们请求的时候会检查cookie中是否有token如果有就将token设置进request的head当中,发送到服务端做单点登录的逻辑处理。
2)response响应拦截做一个全局异常处理
拦截每一个响应信息,判断状态码是否正常,如果返回报错状态码,用弹窗的形式给用户展现友好的信息,如果正常就将response返回给后面业务使用。
// 创建axios实例
const service = axios.create({
//baseURL: 'http://qy.free.idcfengye.com/api', // api 的 base_url
//baseURL: 'http://localhost:8210', // api 的 base_url
baseURL: 'http://192.168.56.133:9001',
timeout: 15000 // 请求超时时间
})
// http request 拦截器
service.interceptors.request.use(
config => {
//debugger
if (cookie.get('guli_token')) {
config.headers['token'] = cookie.get('guli_token');
}
return config
},
err => {
return Promise.reject(err);
})
// http response 拦截器
service.interceptors.response.use(
response => {
//debugger
if (response.data.code == 28004) {
console.log("response.data.resultCode是28004")
// 返回 错误代码-1 清除ticket信息并跳转到登录页面
//debugger
window.location.href="/login"
return
}else{
if (response.data.code !== 20000) {
//25000:订单支付中,不做任何提示
if(response.data.code != 25000) {
Message({
message: response.data.message || 'error',
type: 'error',
duration: 5 * 1000
})
}
return Promise.reject('error')//只要报错前直接抛出错误,就不会执行成功方法了
} else {
return response;
}
}
},
error => {
return Promise.reject(error)
});
- NPM
包管理工具,类似Maven
后端
-
使用spring boot来搭建项目的环境和部署(注解开发)。
-
持久层用的是MyBatis-Plus用到了自动填充 逻辑删除(未实现)和乐观锁(未实现)
自动填充创建时间和修改时间还有每当数据修改时,会将修改时间自动填充
其他的就是调用mp的api实现增删改查嘛。 -
使用Swagger生成接口文档
-
后端采用SpringCloud微服务架构
1)注册中心使用了nacos将每个微服务注册进去。
2)使用fegin来实现每个模块之间的远程调用。
3)使用 ribbon实现负载均衡,因为导入fegin-start的依赖会将ribbon也导入,因为fegin封装了ribbon。
4)后台使用gateway网关,解决跨越问题,还有使用gateway的过滤器检测用户是否登录,gateway过滤器通过拦截request请求看head中是否用token,如果没有就不放通过。 -
SpringSecurity实现登录和授权
后端重点功能实现
JWT令牌:(三部分)
请求头、有效载荷、签名哈希
单点登录(SSO):(token+cookie)
用户先进行登录,如果登录成功我们将用户名用JWT随机生成字符串也就是token,再将token放到cookie当中,当发送请求时通过axios拦截器来拦截我们的request请求,如果cookie中有token,我们会将他放到request的head当中再进行发送,后端通过request的head得到token然后用JWT解析得到用户名然后到数据库查找对应的用户信息,并且将用户信息返回给前端。
微信扫码登录:
- 第一步:先访问微信二维码的页面,在手机上确定登录后会调用我们的callback(回调方法) 得到一个code(相当于手机验证码)。
- 第二步:利用httpclient携带上这个code请求一个微信固定的地址
得到access_token(访问凭证)和open_id(微信号的唯一标识)。- 第三步:利用httpclient携带上access_token和open_id请求一个微信固定的地址,这时微信返回以json形式的用户信息再用json转换工具将其转换为用户对象,我们会先判断用户表的是否有重复的open_id如果有就说明注册了,如果没有就将当的用户信息加入到我们的用户表中,
- 第四步:当插入成功后mp会返回用户名给我们,我们将用户名使用JWT加密生成token放到url参数的位置,重定向到首页。
课程详细视频在线播放功能:
上传视频:
当我们在创建小节的时候向数据库保存的不是视频的地址,而是我们请求阿里云播放器提供的第三方接口的videoId。
播放视频:
通过小节id到数据库中查找对应的videoId,然后通过videoId再访问阿里云的第三方接口得到访问凭证通过videoId和访问凭证播放视频。
为什么通过videoId和访问凭证播放视频?
答:如果说通过视频地址访问视频,只能访问未加密视频,但是不能访问加密视频, 如果用videoId和访问凭证,就能访问加密视频。
@Autowired
private VODProperties vodProperties;
//通过vid拿到视频凭证
public R getVODvid( String vid) throws Exception{
DefaultAcsClient client = InitObject.initVodClient(vodProperties.getKeyid(),vodProperties.getKeysecret());
//请求
GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
request.setVideoId(vid);
//响应
GetVideoPlayAuthResponse response = null;
response = client.getAcsResponse(request);
//得到播放凭证
String playAuth = response.getPlayAuth();
//返回结果
return R.ok().message("获取凭证成功").data("playAuth", playAuth);
}
/**
* 流式上传接口
*
* @param accessKeyId
* @param accessKeySecret
* @param title
* @param fileName
* @param inputStream
*/
private static String testUploadStream(String accessKeyId, String accessKeySecret, String title, String fileName, InputStream inputStream) {
UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, inputStream);
UploadVideoImpl uploader = new UploadVideoImpl();
UploadStreamResponse response = uploader.uploadStream(request);
if (response.isSuccess()) {
return response.getVideoId();
} else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因
return response.getVideoId();
}
}
微信支付功能:(建议将订单加入到redis当中缓存,设置过期时间)
- 根据用户id到订单表查询是否有和当前课程对应的消费的记录,如果有说明已购买和立即观看
- 如果没有,会提醒支付观看我们会转跳到二维码支付页面,然后将订单信息加入到订单表
- 前端设置定时器每三秒访问我们的接口访问订单状态,如果支付成功将订单状态改为支付成功, 并且将支付信息保存的订单日志表中。
前台热点信息,使用redis缓存:
原理:
- 设置常量key比如说如果我们要存课程的热点信息,那我们就将key设置course,每次查询前使用key查询在redis中先查询是否存在信息,如果存在就直接从redis当中获取。
- 从redis中获取的是二进制字节,然后利用对象流反序列化返回对象。
如果redis中不存在,那么我们就向数据库中查询数据,先利用对象流将我们的对象序列化成 二进制字节,然后存入redis当中,这样下一次我们用就会直接从redis当中查询了。
先集成spring-boot-starter-data-redis然后在查询的方法上打上**@Cacheable(value = “teacher”,key = “‘teacherList’”)** value为redis的存放的key, key为存放的数据名。
@Cacheable(value = "teacher",key = "'teacherList'")
@Override
public List<Teacher> getTeacherData() {
QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
teacherQueryWrapper.orderByDesc("id");
teacherQueryWrapper.last("limit 4");
List<Teacher> teacherList = baseMapper.selectList(teacherQueryWrapper);
return teacherList;
}
通过gateway网关的过滤器来查看request的head当中是否有token,检查是否有登录。
使用springsecurity实现认证和授权:
1)认证(登录):
1、如果登录成功。
2、先利用用户名查出对应的用户权限列表加入redis当中,然后将用户名用JWT令牌加密为token。
3、通过登录过滤器然后将token设置到cookie当中每次请求再从cookie中拿到放到request的head当中。
2)用户授权
授权过滤器先从request的head中拿到token再用JWT解析得到用户名通过用户名做为key到redis找到用户权限列表,然后给当前用户添加权限。
Redis做缓存,什么样的数据适合使用Redis做缓存?
经常访问,但不经常修改的数据;如主页
项目遇到的问题
跨域问题:
vue不管路由跳转了几次 created()方法只会执行一次
解决方法:vue监听
watch:{
$route(to,from){
init()
}
}
mybatisPuls的xml问题:打包时不会将xml文件也打包
解决:
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
配置文件:mybatis-plus.mapper-locations=classpath:com/atguigu/edu/mapper/xml/*.xml
-
用@RequestBody接受数据必须用@PostMapping提交否则报miss
-
nginx也会限制文件上传大小 总结:服务器大多都会限制文件上传大小,上传前要设置文件上传大小
更多推荐
所有评论(0)