# est **Repository Path**: pimee/est ## Basic Information - **Project Name**: est - **Description**: 前后端分离的在线预约维修平台 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-10-27 - **Last Updated**: 2023-10-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # est #### 介绍 前后端分离的在线预约维修平台 #### 软件架构 springboot后端 # day01 ## 项目框架搭建 父项目: ​ 通过父项目统一管理子模块到编译,构建 ​ 通过父项目统一管理依赖到版本号: 在父项目到`pom.xml`通过 ``来管理 子模块: ​ 继承父项目,可以减少版本号到管理 父项目: est 子模块: ​ est-common ​ est-model ​ est-dao ​ est-service ​ est-web 模块的依赖关系 dao -> model service -> dao,model,common web -> service,common ## 配置maven的阿里云镜像 默认情况下在`电脑的个人目录\.m2\settings.xml`文件中通过 `mirrors` 来配置 ```xml aliyun http://maven.aliyun.com/nexus/content/groups/public * ``` ## 使用 `Free Mybatis pulgin` 用来生成基础的实体类代码和Mapper接口文件 主要是根据数据库的信息来自动生成 1. 准备好数据库 2. 在idea工具中创建一个数据库连接 3. 打开数据库连接 4. 生成代码 > 查看maven依赖信息的地址: https://mvnrepository.com/ ## 在est-web项目中写一个控制器测试一下 est-web是一个`springboot` 的项目 `springboot`项目提供了统一的版本管理,为了使用这个版本管理,可以采用两种方式: 1. 父项目继承 `spring-boot-starter-parent`,est-web 子模块引入 `spring-boot-starter-web` 一类 ## 整合`mybatis`的配置 http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/ 通过 `mybatis-spring-boot-starter` 依赖来完成整合,在 `est-dao` 中引入 # day02 ## 全局异常处理类 抛出异常 ```java public Users login(Stirng username,String password){ // 根据用户名查询用户信息 Users user = userService.findByUsername(username); if(user == null){ // throw new BusinessException("1004","账号不存在"); ResultEnum resultEnum = ResultEnum.FAIL_ACCOUNT_NOT_EXIST; throw new BusinessException(resultEnum.getCode(),resultEnum.getMsg()); } // 判断密码是否正确 if(!user.getPassword().equals(password)){ //throw new BusinessException("1005","密码不正确"); throw new BusinessException(ResultEnum.FAIL_ACCOUNT_NOT_EXIST); } // 判断用户是否已经被锁定 if(user.isLocked()){ throw new BusinessException("1006","账号已经被锁定"); } // 返回登录的用户信息 return user; } ``` 异常处理 ```java package cn.gdrj.est.controller; import cn.gdrj.est.dto.CommonResult; import cn.gdrj.est.exception.BusinessException; import cn.gdrj.est.util.ResultUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class GlobalExceptionAdvice { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionAdvice.class); /** * 项目中系统异常的统一处理 * @param e * @return */ @ExceptionHandler(Exception.class) public CommonResult handleException(Exception e){ log.error("系统异常",e); return ResultUtil.fail("-1",e.getMessage()); } /** * 项目中业务异常的统一处理 * @param e * @return */ @ExceptionHandler(BusinessException.class) public CommonResult handleException(BusinessException e){ log.error("系统异常",e); return ResultUtil.fail(e.getCode(),e.getMessage()); } } ``` ## redis 在windows中运行redis: 1、修改配置文件:`redis.windows.conf` ```text # 绑定指定ip bind 0.0.0.0 # 指定密码 requirepass 123456 ``` 2、编写一个配置文件`start-redis.bat` ```shell start E:\redis-x64-5.0.14\redis-server.exe E:\redis-x64-5.0.14\redis.windows.conf ``` 3、双击运行bat文件 在项目中使用redis spring-boot 提供了一个starter `spring-boot-starter-data-redis` 1、引入依赖 在est-service中引入 2、配置连接信息 est-web中编写 3、使用:RedisTemplate和StringRedisTemplate # swagger 通过swagger可以生成接口文档 1、引入依赖,在model模块中引入 2、配置:在est-web中 3、启动项目:访问:http://localhost:8080/swagger-ui # knife4j 1、引入依赖,在model模块中引入 2、配置:在est-web中 3、启动项目:访问:http://localhost:8080/doc.html # 微信登录 https://open.weixin.qq.com/cgi-bin/frame?t=home/web_tmpl&lang=zh_CN 1、获取code ```text https://open.weixin.qq.com/connect/qrconnect?appid=wx9168f76f000a0d4c&redirect_uri=http://localhost:8080/api/login/wxchatlogin&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect http://localhost:8080/api/login/wxchatlogin?code=011ZKs100OFbJM1xoq200khszU2ZKs1O&state=STATE ``` 2、通过code获取access_token ```text https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx9168f76f000a0d4c&secret=8ba69d5639242c3bd3a69dffe84336c1&code=011ZKs100OFbJM1xoq200khszU2ZKs1O&grant_type=authorization_code { "access_token":"50_R-LXu7VUnetyOvKsW_s4JRST-sHfXsFpriv1ECv7h7GDN0hz2B_8FWb9F1PA1l4TmS2I9TlaAfikq4r3eHoYGkO19wltT-tXOYmkMzCT18Q", "expires_in":7200, "refresh_token":"50_xu30SC5lF8ADrgFJXLp_Iw_OpqXODxRfhVQuNJKCvruRl3AT_Heyj_u8nN5ts58s4ZVeJxHdAfyKnKjRGKXKfaFrJK212YWMloeioYuVj4A", "openid":"oPxiwwp7_81xzTF7I-lP2Lms6Yw0", "scope":"snsapi_login", "unionid":"otu3rt90xJsCxnevc6H5VjO6IonY"} ``` 3、通过access_token获取用户信息 ```text https://api.weixin.qq.com/sns/userinfo?access_token=50_R-LXu7VUnetyOvKsW_s4JRST-sHfXsFpriv1ECv7h7GDN0hz2B_8FWb9F1PA1l4TmS2I9TlaAfikq4r3eHoYGkO19wltT-tXOYmkMzCT18Q&openid=oPxiwwp7_81xzTF7I-lP2Lms6Yw0 { "openid":"oPxiwwp7_81xzTF7I-lP2Lms6Yw0", "nickname":"chaojun", "sex":0,"language":"", "city":"","province":"", "country":"", "headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/nU5zyEGOkfbSgjB5icdtcuibiazBnWz9UkibsknsVzbic613tPcJWuvgxYicRk6gO0cr09AN00QLGJ9oibUVEPEaf4pqw\/132", "privilege":[], "unionid":"otu3rt90xJsCxnevc6H5VjO6IonY" } ``` 登录的过程: 1、用户点击页面的微信登录按钮 2、让浏览器重定向微信扫码登录的界面 3、接受微信通过浏览器重定向过来的临时票据code 4、根据code和appid和secret从微信放获取access_token和openid 5、根据open_id到数据库查询用户信息 6、如果查询到,就表示用户正确,登录成功 7、没查询到、就是第一次登录、获取用户信息,注册用户信息,返回登录成功。 # day03 ## 通过java代码发送http请求 1、通过jdk中的URLConnection来发送请求 2、通过HttpComponent来发送请求 3、可以通过spring提供了RestTemplate类型发送Http请求 4、Hutool也封装了HttpUtil工具类来完成 # day04 前端项目需要更改main.js中的24行代码 将json字符串装换成一个对象,传给setUserData(obj obj)方法 # day05 ## 首页的商品分类接口 1、定义需要的dto 2、dao 1、商品分类查询、根据类别名称、上架状态、删除字段来查询 2、根据商品分类id查询品牌id:没有被删除的 3、根据品牌id查询具体的品牌信息:没有下架的品牌 4、根据分类和品牌查询商品信息,具有分页查询的功能 3、service 1、商品类别service,不建议直接使用其他实体的dao。 2、品牌 3、商品 4、controller 1、商品分类 # day06 修改前端项目的端口号为8080 ## 商品列表接口开发 定义一个通用的分页对象。 在dto中添加一个属性faceimg dao ​ 查询符合条件的记录数 ​ 分页查询当前页的数据 service ​ 要根据条件分页查询商品信息。 controller ## 商品详情接口开发 对应商品详情写一个单独的dto。 dao ​ 根据id查询 service ​ 调用dao controller ## 根据商品查询评估维度信息 写故障信息和故障选项dto dao ​ 根据modelId查询没有删除的故障信息 ​ 根据故障id查询没有删除的选项信息 service ​ 故障service,根据modelId查询没有删除的故障 ​ 故障选项service,根据故障id查询没有删除的选项信息 controller ## 维修估价 估价的算法:先搞清楚业务逻辑 ```text 故障1的维修最高价*具体故障选项的价格 屏幕异常 400 屏幕黑屏不显示:维修方式1 占比(50%) 400* 50% = 200 电池异常 300 耗电过快 维修方式2(更换) 占比100% 300 200 + 300 = 500 ``` dto ​ 基本的评估价格信息 dao ​ 根据选项id查询选项信息 ​ 根据选项所属的故障id查询故障信息 ​ 保存评估信息 ​ 保存评估详情信息 service ​ 故障 ​ 故障选项 ​ 评估信息 ​ 评估详情信息 controller ## 评估信息详情 dto ​ 评估信息dto好评估详情信息dto dao ​ 根据id查询评估信息 ​ 根据商品id查询商品信息 ​ 根据评估id查询评估详情列表 service # day07 ## 下单维修 输入部分, ​ 用一个对象接收信息,SubmitOrderRequest 输出部分, ​ SimpleOrderDTO dao, ​ AppointmentDao,添加预约信息(需要用户信息和预约信息) ​ MaintainOrderDao,添加维修订单,(根据id查询评估信息EvaluateDao) ​ MaintainOrderFLowDao,添加订单流水记录 service ​ MaintainOrderService ​ 提交维修订单(1、校验参数信息。2、保存预约信息。3、保存维修订单信息(订单编号yyyyMMddHHmmss+4位随机数+10位订单id信息)。4、保存维修订单流水信息。5、返回订单编号) controller # day08 参数校验 支付宝支付 1、浏览器提交支付宝的定金请求 2、项目后端向支付宝发起支付的请求 3、支付宝返回支付的页面信息(会自动提交的表单信息) 4、项目把支付宝返回的信息返回给浏览器 5、浏览器执行接受的页面内容,进行表单的自动提交 6、浏览器把请求提交支付宝 7、支付宝返回支付宝的收银台页面 8、浏览器显示支付宝支付的收银台页面 9、用户输入支付信息完成支付 10、支付信息提交到支付宝 11、支付显示支付成功的支付信息(会在一定时间后,让浏览器跳转到return_url的页面中) 12、向请求中指定的notify_url发起通知 13、项目中根据支付宝通知完成订单 支付交易 幂等性 幂等性其实是源于数学,后来延伸到计算机领域。 是指可以使用相同参数重复执行,并能获得相同结果的函数, 这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。 其实,幂等性指的就是*指一次和多次请求某一个资源应该具有同样的副作用*。 支付宝支付接口开发 ```text 1、用户提交预约请求并生成预约订单之后,前端会发起支付的请求 2、根据预约订单号获取预约订单信息 3、根据预约的订单信息创建支付订单 4、根据支付订单信息向支付宝发起支付的请求 ``` ```text 参数信息 预约订单号(必填,不能是已支付订金的情况) 返回值信息 把支付宝返回的有表单信息的html直接返回 dao MaintainOrder 根据预约订单号获取预约订单信息 PayOrderDao 根据预约订单信息创建支付订单 service MaintainOrderService 根据预约订单号获取预约订单信息 PayOrderService 根据预约订单信息创建支付订单 PayService 根据预约订单号完成定金支付 controller dao service controller ``` 支付宝的异步回调接口 ```text 1、接收支付宝传入的参数 2、验证签名 3、如果签名不正确,返回fail 4、如果正确(根据支付订单号查询支付订单如果是已支付,就直接返回success(幂等性),根据支付订单号修改支付订单的状态,修改维修的订单的状态为已支付定金,添加维修订单状态变化的流水记录) ``` 支付宝的同步回调接口 ```text 1、接收支付宝传入的参数 2、验证签名 3、如果签名不正确,返回fail 4、如果正确,让浏览器重定向到前端中显示预约成功的界面 ``` maven安装本地jar包 阿里支付 前端 vue : devServer{ "port" : 8081 } vue 配置allowhost 拓展 如果用户长时间没有付款怎么办? 设立付款截止时间,到点关闭订单。 可以使用定时任务或者消息队列实现。 Nginx技术介绍 定义:nginx是一个开源的高性能web服务器 应用场景 代理静态资源 反向代理 解决跨域问题 负载均衡 防火墙 多虚拟主机 一台服务器对应多个域名,每个域名要访问的内容是不一样的 多个域名:www.aaaa.com,www.bbbb.com 内容: /www/web-a /www/web-b