浅尝苍穹外卖-后端篇
Intro
只是浅尝,
对于这门课而言,有点像搭积木了,
Java拼好码么?
那很有生活了。
但是一些工程化的思想却流入了我的大脑,
让我在余下的时间思考工程化的意义。
课程准备
环境配置
前端环境配置
整个课程已经提供了Windows环境下的Nginx-1.20.2软件包,且其中已经包含了前端文件,
所以直接启动Nginx服务就行。
Nginx涉及配置也已经提供以及涉及到的负载均衡等高级问题,这个这段还无需关心。
后端环境配置
IDEA直接从官网下了最新版,反正我的账号已经学生认证,不用白不用。
配置项目的时候犯了点傻,下了最新版JDK,导致后面尝试启动项目的时候发生错误。
课程好像没讲用的什么JDK,不过研究了一下确定了应该使用JDK 8。
技术栈
Web框架:SpringBoot
SpringBoot 人如其名,就是“快速启动”的Spring
SpringBoot 按照 “约定大于配置” 的原则,直接为开发者设置好了配置。
Spring 是什么?
Spring主要做的就是两件事情:
- 生成Bean(扫描有什么Bean,并在需要的时候生成)
- 管理Bean(管理Bean生命周期)
当然,这些底层如何实现就要涉及到 反射等 高级特性了,这里不关心。
DB:MySQL
课程使用的是MySQL,但是没有具体提到版本。我用的是5.7。
因为事先接触过Docker技术,所以果断选择了wsl环境下拉了个mysql5.7的镜像,并挂载conf和课程提供的sql文件生成镜像。
后面调试的时候发现中文发生了乱码,因为以前遇见过类似错误,所以很快锁定到,是编码集的问题。
一查果然是,遂重新以utf-8的格式进行编码数据库。
这里偷了个懒,直接删了镜像重新创建了。
- 发生这等错误的缘故好像是因为MySQL5.7默认编码集不是utf-8的问题
缓存:Redis
Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件。
主要特点:
- 基于内存存储,读写性能高
- 适合存储热点数据(热点商品、资讯、新闻)
- 企业应用广泛
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。它存储的value类型比较丰富,也被称为结构化的NoSql数据库。
NoSql(Not Only SQL),不仅仅是SQL,泛指非关系型数据库。NoSql数据库并不是要取代关系型数据库,而是关系型数据库的补充。
微信小程序
小程序是一种新的开放能力,开发者可以快速地开发一个小程序。可以在微信内被便捷地获取和传播,同时具有出色的使用体验。
首先,在进行小程序开发时,需要先去注册一个小程序,在注册的时候,它实际上又分成了不同的注册的主体。我们可以以个人的身份来注册一个小程序,当然,也可以以企业政府、媒体或者其他组织的方式来注册小程序。那么,不同的主体注册小程序,最终开放的权限也是不一样的。比如以个人身份来注册小程序,是无法开通支付权限的。若要提供支付功能,必须是企业、政府或者其它组织等。所以,不同的主体注册小程序后,可开发的功能是不一样的。
然后,微信小程序我们提供的一些开发的支持,实际上微信的官方是提供了一系列的工具来帮助开发者快速的接入
并且完成小程序的开发,提供了完善的开发文档,并且专门提供了一个开发者工具,还提供了相应的设计指南,同时也提供了一些小程序体验DEMO,可以快速的体验小程序实现的功能。
最后,开发完一个小程序要上线,也给我们提供了详细地接入流程。
微信登录流程
步骤分析:
- 小程序端,调用wx.login()获取code,就是授权码。
- 小程序端,调用wx.request()发送请求并携带code,请求开发者服务器(自己编写的后端服务)。
- 开发者服务端,通过HttpClient向微信接口服务发送请求,并携带appId+appsecret+code三个参数。
- 开发者服务端,接收微信接口服务返回的数据,session_key+opendId等。opendId是微信用户的唯一标识。
- 开发者服务端,自定义登录态,生成令牌(token)和openid等数据返回给小程序端,方便后绪请求身份校验。
- 小程序端,收到自定义登录态,存储storage。
- 小程序端,后绪通过wx.request()发起业务请求时,携带token。
- 开发者服务端,收到请求后,通过携带的token,解析当前登录用户的id。
- 开发者服务端,身份校验通过后,继续相关的业务逻辑处理,最终返回业务数据。
微信支付
前面的课程已经实现了用户下单,那接下来就是订单支付,就是完成付款功能。支付大家应该都不陌生了,在现实生活中经常购买商品并且使用支付功能来付款,在付款的时候可能使用比较多的就是微信支付和支付宝支付了。在苍穹外卖项目中,选择的就是微信支付这种支付方式。
要实现微信支付就需要注册微信支付的一个商户号,这个商户号是必须要有一家企业并且有正规的营业执照。只有具备了这些资质之后,才可以去注册商户号,才能开通支付权限。
个人不具备这种资质,所以我们在学习微信支付时,最重要的是了解微信支付的流程,并且能够阅读微信官方提供的接口文档,能够和第三方支付平台对接起来就可以了。
参考:https://pay.weixin.qq.com/static/product/product_index.shtml
完成微信支付有两个关键的步骤:
第一个就是需要在商户系统当中调用微信后台的一个下单接口,就是生成预支付交易单。
第二个就是支付成功之后微信后台会给推送消息。
这两个接口数据的安全性,要求其实是非常高的。
解决: 微信提供的方式就是对数据进行加密、解密、签名多种方式。要完成数据加密解密,需要提前准备相应的一些文件,其实就是一些证书。
在后绪程序开发过程中,就会使用到这两个文件,需要提前把这两个文件准备好。
工具库
MyBatis
用于处理数据库映射的工具,在 XML 下编写SQL。
本质上也是个参数化查询的工具罢了。
Swagger
一个WebGUI文档管理界面。
依赖 knife4j 框架自动扫描API端点,以及附着的注释,
从而生成对应的API文档。
并提供强大的API端点测试功能。
HttpClient
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
HttpClient的核心API:
- HttpClient:Http客户端对象类型,使用该类型对象可发起Http请求。
- HttpClients:可认为是构建器,可创建HttpClient对象。
- CloseableHttpClient:实现类,实现了HttpClient接口。
- HttpGet:Get方式请求类型。
- HttpPost:Post方式请求类型。
HttpClient发送请求步骤:
- 创建HttpClient对象
- 创建Http请求对象
- 调用HttpClient的execute方法发送请求
Spring Data Redis
我们在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。
Redis 的 Java 客户端很多,常用的几种:
- Jedis
- Lettuce
- Spring Data Redis
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。
Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。
Spring Cache
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:
- EHCache
- Caffeine
- Redis(常用)
在spring boot项目中,使用缓存技术只需在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持即可。
例如,使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可。
Spring Task
Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。
定位: 定时任务框架
作用: 定时自动执行某段Java代码
应用场景:
1). 信用卡每月还款提醒
2). 银行贷款每月还款提醒
3). 火车票售票系统处理未支付订单
4). 入职纪念日为用户发送通知
只要是需要定时处理的场景都可以使用Spring Task
WebSocket
WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。
HTTP协议和WebSocket协议对比:
- HTTP是短连接
- WebSocket是长连接
- HTTP通信是单向的,基于请求响应模式
- WebSocket支持双向通信
- HTTP和WebSocket底层都是TCP连接
思考: 既然WebSocket支持双向通信,功能看似比HTTP强大,那么我们是不是可以基于WebSocket开发所有的业务功能?
WebSocket缺点:
服务器长期维护长连接需要一定的成本
各个浏览器支持程度不一
WebSocket 是长连接,受网络限制比较大,需要处理好重连
结论: WebSocket并不能完全取代HTTP,它只适合在特定的场景下使用
WebSocket应用场景:
1). 视频弹幕
2). 网页聊天
3). 体育实况更新
4). 股票基金报价实时更新
Apache POI
Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。
一般情况下,POI 都是用于操作 Excel 文件。
Apache POI 的应用场景:
- 银行网银系统导出交易明细
- 各种业务系统导出Excel报表
- 批量导入业务数据
Apache POI既可以将数据写入Excel文件,也可以读取Excel文件中的数据。
学习
基本业务流程设计
数据是如何在不同层级间流动的
图示
案例
从源码入手:
参考 Employee 相关业务流程
- ->
public class EmployeeController
1
2
3
4
5
6
7
public Result update({ EmployeeDTO employeeDTO)
log.info("编辑员工信息:{}", employeeDTO);
employeeService.update(employeeDTO);
return Result.success();
}
可以看到,当前数据来到了 Controller层 的 update方法。
update方法 从 请求体 中 提取出数据并包装为 EmployeeDTO,
然后派发给 Service 层 进行业务逻辑处理。
- ->
public class EmployeeServiceImpl implements EmployeeService
1
2
3
4
5
6
7public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee);
employeeMapper.update(employee);
}
在 Service层 中, 数据被提取并映射为相应实体,
并交由 Mapper 层进行持久化处理,这里不再演示。
类似查询之类的逻辑也是一样的,
只不过变成了:
Controller -> Service -> Mapper -> Service -> Controller
缓存设计
图示
案例
public class ShopController
1 |
|
可以看到,直接在 Controller层 操作 redis连接对象 进行查询,
为了避免异常,对可能发生的错误提前包裹一下判断。
改动
图片改为本地存储
不想使用 阿里云OSS 所以改成本地存储了
一、 设置静态资源映射
1 | /** |
二、 修改文件上传接口实现
1 |
|
三、 实现辅助工具
1 |
|