1. 苍穹外卖的模块
苍穹外卖大方向上主要分为管理端和用户端
管理端使用vue开发,主要是商家来使用,提供餐品的管理功能,主要有下面几个模块:
- 员工模块,提供员工账号的登录功能和管理功能
- 分类、菜品、套餐模块,分别对分类、菜品和套餐进行增删改查和启用禁用
- 订单模块,可以搜索和查看订单,变更订单状态
- 统计模块,统计营业额、用户、订单和销量排名,还有Excel报表导出功能
- 工作台模块,提供今日运营数据数据以及订单、菜品、套餐的总览
用户端使用微信小程序开发,主要是给用户提供点餐功能
-
登录模块,调用微信小程序登录接口实现登录功能
-
菜品、套餐模块,用于查询菜品、套餐的信息
-
购物车模块,在购物车中添加或删除套餐菜品
-
订单模块,提供下单、微信支付、查询订单、取消订单、再来一单、催单功能。
2. 管理端账号密码的登录流程
登录的本质就是对员工表进行查询操作
- 首先要接收前端发送的账号和密码
- 然后根据账号在数据库员工表进行查询,如果没有查到,说明此账号不存在,可以直接给前端返回一个提示,如果查询到了说明这个账号存在
- 接下来就要进行前端传入密码和数据库查询到的密码比对,由于数据库的密码是加密保存的,所以在比对之前,还需要对前端传入的秘密进行加密;如果比对失败,说明用户提供的密码不对,可以直接给前端返回一个提示;如果比对没有问题,说明用户提供的账户和密码是正确的,此时登录成功
- 登录成功之后,需要生成一个标识用户身份的token,返回给前端,前端会将token保存起来
- 用户后面访问系统的时候,需要携带着这个token,而我们后端需要编写一个拦截器,用于拦截请求,校验token
- 校验通过,则放行请求,正常访问;校验失败,则禁止通行,返回提示
3. 前端小程序的微信登录流程
微信登录的核心是通过微信小程序提供的临时凭证code换取永久凭证openid的过程
- 首先微信小程序会向微信官方申请一个临时登录code
- 然后,小程序带着code向后台服务发送请求
- 后台接收到code后,会调用微信官方接口验证code是否合法,如果合法,官方会返回一个openid;这个openid就是此用户在我们系统中的唯一标识,同时也代表用户身份合法
- 后台服务接收到来着微信的openid之后,会去数据库查询一下是否存在此账户;如果存在,代表这是一个老用户,如果不存在,则代表这是一个新用户首次使用我们的系统,我们需要将其信息保存到用户表中
- 登录成功之后,需要生成一个标识用户身份的token,返回给前端,前端会将token保存起来
- 用户后面访问系统的时候,需要携带着这个token,而我们后端需要编写一个拦截器,用于拦截请求,校验token
- 校验通过,则放行请求,正常访问;校验失败,则禁止通行,返回提示
4. ThreadLocal 在项目中的应用
-
ThreadLocal 称为线程局部变量,可以为每个线程单独提供一份存储空间,它的特点是:线程之内,数据共享;线程之间,数据隔离。
-
在我们的项目中经常使用ThreadLocal来存储用户的登录信息,具体的做法是:
每次用户访问后台都需要经过拦截器鉴权,如果鉴权通过,我们就将登录用户的信息保存到ThreadLocal中
接下来,在项目的各个代码中就可以轻松的从ThreadLocal中获取用户信息了
最后,当请求访问完服务离开的时候,还会再次经过拦截器,这个时候就可以清理掉ThreadLocal中的内容了
5. 项目是如何进行异常处理的
在我们的项目中,异常处理都是通过spring的全局异常处理器来实现的,核心是两个注解:
- 一个是@RestControllerAdvice,标注在类上,可以定义全局异常处理类对异常进行拦截
- 一个是@ExceptionHandler,标注在异常处理类中的方法上,可以声明每个方法能够处理的异常类型
在我们的项目中,将异常分为了三大类:
在苍穹外卖项目的全局异常处理器中一般定义三种异常:
- 第一类是指定异常,指定异常指的是用户操作产生的与程序设计相关的异常,比如说字段重复异常、Validation校验异常等等,这类异常捕获之后,我们会根据异常的消息提示,给前端一个确定的返回结果
- 第二类是业务异常处理,业务异常是由于用户不正当操作产生的与业务相关的的异常,这种异常往往需要我们自定义,然后在程序的相关位置手动抛出,在抛出的时候还会指定异常提示信息。然后异常处理器捕获之后,直接将异常提示消息返回给前端
- 第三种异常时兜底异常,此处主要捕获的是不属于上面两种异常的异常,一般是一些程序员代码不够严谨引发的运行时异常,对于这些异常,我们处理方案是首先要把错误记录到日志系统中,然后给前端一个类似于服务器开小差了之类的统一提示
6. 项目是如何存储文件的
在我使用过的文件存储中,主要有三类存储方式
- 直接将文件保存到服务到硬盘,这种方式操作方便,但是扩容困难,而且安全保障不高,现在基本不再使用
- 使用一些付费的第三方存储服务,比如阿里云或者七牛云,这种方式无需自己公司提供服务器和相关软件,并且安全性和扩展性都不需要自己再进行考虑,但是不适合存储一些敏感文件
- 将文件保存在公司自己搭建的一些分布式系统中,比如我们公司用过MinIO和FastDFS,它需要我们自己准备服务器,安装维护软件,好处是文件都存放在自己的服务器上,隐私性比较好
至于如何选择服务器,我认为目前主要考虑的就是分布式文件存储系统和第三方服务
- 如果文件是隐私性比较高,建议使用自己搭建的分布式文件存储系统
- 如果文件隐私性不高,可以考虑使用第三方服务
我们项目中主要存储的文件是一些菜品或者套餐的图片,不涉及什么隐私问题,所以选择了阿里云服务
7. 项目是如何进行参数校验的
-
我们项目中的校验是使用validation技术实现的,它的核心是一些具有特定意义的注解
-
这些注解主要标注在请求参数或者是参数对象对应类的属性上,每个注解都有自己的校验规则。
-
如果我们输入的请求参数不符合对应的校验规则,系统就会抛出异常,此时我们只需要在全局异常处理器中捕获异常,然后给前端提示即可。
-
我们常用的注解有下面这些:
@Null 可以标注在任意类型元素上,被标注的元素必须为null
@NotEmpty 可以标注 在字符串,集合,数组,map上,被标注的元素必须不能为 null ,也不能是空串
@Range 标注在字符串和数值的大小必须在指定的范围内,对于null无效
@Digits(integer(数值的位数) =3 , fraction(小数的位数)=2)
@size(min=,max=) 可以标注在字符串,数组,集合,map用于控制长度
@Email 邮箱
@URL 合法的地址
8. 如何理解分组校验
- 很多情况下,我们会将校验规则写到实体类中的属性上,而这个实体类有可能作为不同功能方法的参数使用,而不同的功能对象参数对象中属性的要求是不一样的。比如我们在新增和修改一个用户对象时,都会接收User对象作为请求参数,但是新增要求对象的id为空,而修改则要求id字段不能为空。这个时候就需要使用到分组校验了
- 分组校验其实就是定义多套校验规则,对于指定的功能,我们按照要求指定它使用哪套规则即可