# miaosha_v1 **Repository Path**: giteehuan/miaosha_v1 ## Basic Information - **Project Name**: miaosha_v1 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-03-15 - **Last Updated**: 2021-05-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 项目结构 ![image-20210321204711727](pic/image-20210321204711727.png) # 项目环境 SpringBoot 2.0.5.RELEASE Java 8 ## redis 搭建的过程记录 配置选择 redis 数据库 ![image-20210322234434914](pic/image-20210322234434914.png) ### 问题记录 redis缓存的类没有实现学序列化接口,导致redis序列化失败。 ![image-20210322233114471](pic/image-20210322233114471.png) 解决 对应的 类 implements Serializable # 秒杀思考记录列表 ## 传输加密的密码——极度不专业 ![image-20210315172433176](pic/image-20210315172433176.png) 问题出现在哪里?不应该返回业务模型——前端需要什么,返回什么 ![image-20210315173732408](pic/image-20210315173732408.png) ## 返回的错误界面对前端不友好 ![image-20210315174932183](pic/image-20210315174932183.png) 解决方案:归一化 responseBody 返回的参数(Status +Data 格式) ![image-20210315182053233](pic/image-20210315182053233.png) ## 异常处理期待效果——和成功的格式类似,data 中的数据是——errCode 和 errMsg 实现方案—— @ExceptionHandler 注解 ![image-20210316095446737](pic/image-20210316095446737.png) # 用户信息管理 ## 用户获取 otp 短信接口 ### 跨域请求失败 ![image-20210316151828765](pic/image-20210316151828765.png) 解决方案 注解:@CrossOrigin ![image-20210316152038476](pic/image-20210316152038476.png) ![image-20210316152231677](pic/image-20210316152231677.png) ## 用户注册接口 ![image-20210316200050283](pic/image-20210316200050283.png) ![image-20210316200131207](pic/image-20210316200131207.png) ## 用户登录接口 从上到下思考(需求推动) 从下到上实现(保证可以交付) ## 参数校验优化 ![image-20210317170532192](pic/image-20210317170532192.png) 解决方案——引入 第三方工具 ![image-20210317170935051](pic/image-20210317170935051.png) 使用 hibernate ## 为什么在后端校验了,还要在前端校验? 因为校验最好是在离用户最近的地方——第一时间提醒,提升用户体验 为什么 ![image-20210316214736122](pic/image-20210316214736122.png) 解释 ![image-20210316214845240](pic/image-20210316214845240.png) # 商品信息管理 是先考虑 数据库的设计,还是先考虑领域模型的设计 参考:领域模型(Domain Model) https://www.jianshu.com/p/b6ec06d6b594 实现列表: 1. ItemModel ![image-20210317213517323](pic/image-20210317213517323.png) 2. 数据库的设计(价格用double) 3. 使用 mybatis generator 生成与数据库对应的实体及操作接口 +测试接口的正确性 参考:https://mybatis.org/mybatis-3/sqlmap-xml.html#Parameters ``` insert 语句补充 keyProperty="id" useGeneratedKeys="true" ``` 检查类型和数据的对应关系 价格——转化为 BigDecimal 测试 ```java @RunWith(SpringRunner.class) // Junit4 必须写 @SpringBootTest public class ItemDOMapperTest { @Test @Transactional public void selectByItemIdTest(){ ItemDO itemDO = itemDOMapper.selectByItemId(1); Integer sales = itemDO.getSales(); Assert.assertThat(sales, is(55)); } } ``` 4. ItemService 接口设计 1. 创建商品接口 2. 商品列表浏览接口 3. 商品详情浏览接口 ![image-20210317235200995](pic/image-20210317235200995.png) ## 创建商品接口(ItemService 的第一个方法实现)createITem 1. 校验createITem 的参数 ItemModel ,ItemModel 中写注解——使用 hibernate 的功能 注意:不要用有损精度的类型 double ,使用 BigDecimal 2. 若 ItemModel 合法,编写 xxxModel 转换为 xxxDO 的函数,进行数据转换(1对多) 1. ItemModel —> ItemDO 2. ItemModel —>StockDO 3. ItemDO 和 StockDO 分别写入数据库(保持事务的特性)——方法加 事务标签 1. ItemDOMapper.xml insert 映射文件修改 添加 useGeneratedKeys 和 keyProperty 2. ItemDO 先写到数据库,写完了之后将数据的自增字段 id 设置给 当前的 ItemModel 3. 将 加了 id 字段的 ItemModel转换为 StockDO,然后存入数据库 ![image-20210317231004161](pic/image-20210317231004161.png) 4. 调用 自己的 商品详情浏览 接口 ,返回 ItemModel ![image-20210318000250910](pic/image-20210318000250910.png) ## 商品详情查询接口 ——getItemById(Integer Id) 商品详情查询接口getItemById(Integer Id) 1. 先取出ItemDO,然后判断 是否为空——为空返回 null ![image-20210317232834692](pic/image-20210317232834692.png) 2. ItemDO 不为空,根据ItemDO id 查询 库存量 1. 实现 selectByItemId(Integer Id) 数据库操作层 ——StockDOMapper.xml 新增 selectByItemId ; 数据库操作层 ——StockDOMapper.java 新增方法 ![image-20210317232649363](pic/image-20210317232649363.png) ![image-20210317232719023](pic/image-20210317232719023.png) 3. 将两个从数据库查询出来的 DO,合并为一个业务模型 ItemModel,并返回给前端 StockDO—>StockModel 1. 编写转化方法,ItemDO+StockDO —> ItemModel (多合一) ![image-20210317233009478](pic/image-20210317233009478.png) ![image-20210317234439939](pic/image-20210317234439939.png) 至此,创建商品接口+ 商品查询接口设计完毕 ## 设计创建商品前端相关工作(接口请求 + 界面设计 ) 1. 前端相关——ItemModel 对应 的 ItemVO(仅给前端用户展示) 1. 复制 ItemModel 所有字段 2. 删掉无需返回给前端的字段 2. 前端相关—— Item 的 Controller 继承 BaseController,并且支持跨域请求 1. 处理创建商品的请求 1. 接受参数——命名与前端一致 2. 封装参数到 ItemModel 3. ItemModel 转换为 ItemVO 4. 将 ItemVO 转换为 通用返回类型 CommonReturnType 格式给前端 1. 编写转换方法(已经写好) 3. 实现前端 1. 复用之前的界面——注册界面(改label的 名字, 输入框的 name 和 id 属性 ) 2. 修改 jquery 的点击事件的对应submit 按钮的 id ![image-20210317224856369](pic/image-20210317224856369.png) 3. 从页面取值 ![image-20210317225004458](pic/image-20210317225004458.png) 4. 对取出的值进行前端校验 ![image-20210317225125994](pic/image-20210317225125994.png) 5. ajax 请求(url 请求,数据,跨域请求) ![image-20210317225415781](pic/image-20210317225415781.png) ## 商品详情页请求处理 localhost:8080/item/getItem?id=1 ![image-20210317235714649](pic/image-20210317235714649.png) ​ ## 商品页列表浏览接口——listItem(); // service 层 ![image-20210318001704576](pic/image-20210318001704576.png) // controller 层 Model —— VO —— CommonReturnType ![image-20210318001915703](pic/image-20210318001915703.png) // 这种 get 请求,直接写 url 测试就可以 ![image-20210318002123089](pic/image-20210318002123089.png) // 商品列表页面 UI 显示 ![image-20210318002350271](pic/image-20210318002350271.png) // 表格 ![image-20210318002607618](pic/image-20210318002607618.png) // ajax 删掉 ![image-20210318002748825](pic/image-20210318002748825.png) // ajax 修改 url ,data 不需要 ![image-20210318004611977](pic/image-20210318004611977.png) # TODO 反思——由上到下的设计不是健壮的 1. 对于开始自动写好的操作数据库的所有 接口以及 接口对应的 xml 映射文件,都应该经过严格的测试,才应该交付上层使用 2. 使用了maven 自动生成代码的插件,要注意以下几点工作 1. 提交当前工作良好的代码 2. 避免 插件的自动化工作覆盖已有的工作 TODO 3. Maven 执行 test 任务的时候,为什么插件也执行了,原理是什么? TODO # 跨域请求 ![image-20210317132708809](pic/image-20210317132708809.png) ## 左侧为前端配置,右侧为后端配置 ![image-20210317132808455](pic/image-20210317132808455.png) ## TODO 升级版本到 2.4.3 启动会报错 ![image-20210317143952544](pic/image-20210317143952544.png) # Spring Boot Test 编写 Spring Boot 默认使用的依赖 ![image-20210317141159543](pic/image-20210317141159543.png) ![image-20210317141640214](pic/image-20210317141640214.png) 注意 Junit 4 和 Junit 5 的在 SpringBoot 中配置的变化 > If you are using JUnit 4, don’t forget to also add `@RunWith(SpringRunner.class)` to your test, otherwise the annotations will be ignored. > >If you are using JUnit 5, there’s no need to add the equivalent `@ExtendWith(SpringExtension.class)` as `@SpringBootTest` and the other `@…Test` annotations are already annotated with it. 测试的事务回滚功能——测试的时候执行,测试之后恢复原来的状态 ![image-20210317142235111](pic/image-20210317142235111.png) # 思考 TODO 为什么要引入 VO 层?不直接使用 领域模型 Model VO 又是比 Model 大很多,用户的一次请求,可能会返回聚合很多信息到 VO,分层是必须的 # 关于命名 **select**ByItemId(Integer Id)——一看就是直接操作数据库的 **get**ItemById(Integer Id) ——业务层的 # 一些错误记录 ## SQL xml 配置文件 ![image-20210319134403747](pic/image-20210319134403747.png) ## logback 乱码 TODO 暂时的解决办法就是——能不用中文就不用中文 ![image-20210319202323244](pic/image-20210319202323244.png) # 附录 ## 分层设计 ![image-20210319235902698](pic/image-20210319235902698.png)