软件开发流程
- 需求分析(需求规格说明书、产品原型)
- 设计阶段(UI、数据库、接口)
- 编码(代码开发、测试)
- 测试(测试用例、测试报告)
- 运维(软件环境安装、配置)
基础代码解析
- 登录功能
- 启动nginx服务器,访问localhost进入登录页面,输入用户名和密码,后端通过dto接收,通过服务层的login方法校验,判断是否可以通过用户名查找到用户,如果未找到,抛出异常,该异常是自定义异常,并通过全局异常捕获,结果统一用result接收,并将错误结果返回给前端,校验通过,判断密码是否正确、用户是否被禁用,如果都通过,返回用户信息,控制层接收到之后,生成jwt令牌,该令牌需要引入依赖,由一个工具类生成jwt令牌,其中key和过期时间以及tokenname在配置文件中,需要配置类读取配置文件并注入获取值,在jwt中存入的是用户的id,通过框架生成jwt;再通过vo对象将结果返回给前端
- 请求路径不一致,因为前端访问的是nginx反向代理服务器,nginx接收到之后再转发给真正的服务器,之所以这么做有以下3点原因
- 提高访问效率,查询的时候如果有相同的访问路径,会将结果进行缓存,如果下次再次访问该路径,就会直接将该结果返回
- 负载均衡
- 保证后端服务安全,前端访问会先访问nginx服务器,再由nginx访问局域网内部服务,所以后端服务不会对外部开放,从而增加了安全性
员工功能
- 新增员工
- 通过页面原型确定基础字段,通过数据库查询需要补全的字段,中间需要做dto和entity的字段映射,使用spring提供的BeanUtils的方法即可;还需要设置状态、创建时间、人等信息,创建人需要通过jwt拦截器拦截之后,从token中获取id,因为在登录的时候以及在token中设置了id,所以可以直接获取,获取到之后,通过ThreadLocal存入到线程内部,在获取的时候直接从ThreadLocal中获取即可,再次处将ThreadLocal封装成立一个类;因为用户账号是唯一的,所以重复的名字会抛出sql异常,需要通过全局异常获取该异常,判断是否抛出的是sql异常,如果是,给出相应提示并返回给前端,如果不是就是未知异常,也给信息到前端
- 员工分页查询
- 前端需要传递name(非必须),当前页码、每页展示个数,并通过pageDto接收,传递给服务层,服务层通过mybatis插件pagehelper进行分页查询,调用startpage方法设置页码和记录数,调用mapper层的查询方法返回page对象(pagehelper规定的),从这个对象可以获取总记录数,以及查询的结果;mybatis如何实现的,实际上利用的是ThreadLocal记录页码和记录数,在调用sql语句时动态拼接limit语句并自动计算出对应的页码;
- 代码优化:日期时间类型格式有问题,可以通过JsonFormat注解解决比较繁琐;第二种,在拦截器中统一修改,利用到了springmvc消息转化器机制,重写方法extendMessageConverters,先获取消息转化器,设置对象转化器,可以自定义一个对象转化器,需要继承ObjectMapper,需要添加到springboot的消息转化器中,默认排在最后,肯能无法利用到自定义的消息转化器,需要添加到前面,所以可以设置索引为0,就可以启用自定义的转化器了
- 员工启用禁用
- 将status和员工id传入,根据id修改值,为了提高代码复用,通过动态sql根据修改变量修改
- 修改员工信息
- 通过id先获取员工信息,返回员工信息即可,并修改值,执行更新操作,在更新时需要将更新时间和更新人修改(通过ThreadLocal获取)
菜品功能
公共字段赋值:通过aop实现,首先自定义注解,创建切面类,设置切入点,条件是mapper层以及有相应注解的才会拦截;创建前置通知类,获得被拦截方法上的数据库操作类型,获得实体对象(需要遵守一个约定:实体类型在第一个位置),准备要放入的数据,根据不同类型,放入不同数据
- 菜品分类:与员工功能代码类似,比较简单
- 菜品添加
- 查询分类(已经有了)
- 文件上传:通过阿里云的oss服务实现,首先通过配置类已经配置文件获取阿里云的参数,通过工具类实现图片上传,并在上传之前设置图片路径
- 菜品添加,将菜品添加,上传图片,添加口味,直接插入数据
- 分页查询:业务功能比较简单,返回值类型是dishvo,需要联表查询,将分类名称查询出来
- 删除菜品:可以批量查询、要把对应的口味删除、起售中的菜品不能删、和套餐关联的不能删;实现批量删除可以通过字符串接收,然后自己解析id;另一种方法,通过mvc框架解析,添加requestparam注解即可;
- 修改菜品:先查询出来菜品信息,联表查询出口味,修改时对于口味的修改,可以先删除口味信息,然后重新添加即可
店铺状态修改
此处由于只涉及一个字段,单独设立一张表优点浪费,所以采用redis存储该状态
小程序端开发
-
HttpClient
-
支持http协议的客户端编程工具包
-
首先获取HttpClient对象(HttpClients.createDefault)、获取请求对象(HttpGet|HttpPost...)、发送请求获取响应状态码(clients.execute(get)-->response,response.getStatusLine().getStatusCode()),响应体并且通过EntityUtils解析(reponse.getEntity()-->EntityUtils.toString(entity))、关闭资源(reponse.close,client.close)
-
-
微信小程序登录
-
小程序调用wx.login()获取code(只能使用一次),通过wx.request()发送code到后端,后端获取appid、密钥、code这三个参数请求微信接口服务获取到用户的oppenid和session_key等信息,后端接收到之后可以自定义客户登录状态即token,并返回给小程序,小程序可以存入到storage中,并在每次发送请求时携带token,后端即可通过校验token做其他业务
-
执行登录操作,获取到用户信息,生成jwt令牌并返回信息(openid、token、userId),服务层先请求微信官方登录接口,配置数据(通过配置文件配置类获取所需数据),返回一个json格式的数据,通过json工具调用parseObject方法获取openid;判断是否为空,是抛出登录异常,不是,判断是否是新用户,是,将openid、创建时间设值,insert进user表,并将id填入user对象中,可通过mybatis的两个属性,useGeneratedKeys、keyProperty,返回user对象;
-
用户登录之后,若有其他请求还需校验用户登录状态,可以使用拦截器进行校验;
-
-
缓存菜品
-
客户端查询菜品,先查询缓存,如果有就直接返回,如果没有,就先查询数据库,将返回的结果放入redis,并返回数据;redis中的key使用分类id,value用list包装的dish
-
清除缓存:新增、修改、批量删除、起售停售都应该清除缓存
-
-
SpringCache
-
是一个框架,实现了基于注解的缓存功能,只需加一个注解就能实现缓存功能
-
可以使用不同的缓存框架进行缓存,首先引入springche依赖,对于使用不同的缓存框架,只需要引入不同的缓存框架的依赖即可,例如使用redis作为底层缓存数据,只需引入redis的依赖即可;而且更换底层缓存技术,并不会影响注解的使用;
-
常用注解
-
@EnableCaching:开启缓存功能,通常加载启动类上
-
@Cacheable:在方法执行前查询缓存,如果有数据直接返回,没有调用方法并将返回值放入缓存
-
@CachePut:将方法返回值放入缓存值
-
@CacheEvict:将一条或多条数据从缓存中删除
-
-
使用规则
-
首先在启动类添加@EnableCaching,表示启动缓存
-
在方法上使用注解,例如在保存用户方法上添加注解@CachePut
,其中()中使用的是spEL(spring EL)表达式,.是对象导航
-
@Cacheable:当请求到达后端时,springboot生成一个controller代理对象,会先进入这个代理对象,从redis中查询数据,没有通过反射执行controller中的方法,将返回结果放入缓存
-
-
-
添加购物车
-
首先判断购物车中是否有套餐、菜品以及菜品对应的口味,有,数量+1执行更新操作,没有则新增菜品,先判断是否是套餐还是菜品,通过对应id即可查询
-
-
地址信息的增删改查,实现比较简单
-
订单功能
-
下单功能
-
通过购物车去结算,到达订单详情页面,在详情页面中有地址信息、派送状态、购物车中的数据、总金额、备注等信息,点击去支付,到达支付页面,在支付页面中有支付剩余时间,总金额、订单编号等信息;当用户点击去结算的时候,需要给订单表以及订单详情表添加数据,在添加之前需要对业务错误进行捕获,例如:地址为空、购物车为空;向订单表添加数据,部分数据可以直接拷贝,其余数据需手动添加;再向订单详情表添加数据,遍历购物车,添加相应数据;添加完成之后需要清空购物车数据,封装返回的结果;
-
-
支付功能
-
订单状态定时处理
-
使用的是springTask框架,利用cron表达式设置定时时间;
-
使用规则:在启动类添加@EnableScheduling,自定义任务类并添加@Component添加到Bean管理器中,在类中自定义方法,并添加@Scheduled(cron表达式),在方法内添加代码
-
实现:手机端客户可能一直未支付,此时需要每隔1分种执行一次,查看是否支付成功,未成功则取消订单;管理端订单可能一直处于派送中,此时可以在凌晨的时候查看是否有订单处于派送中,有则修改订单状态为已完成
-
-
-