苍穹外卖上半部分总结

苍穹外卖一个很经典的项目 虽然已经烂大街,但项目依旧是很优秀,并且代码十分规范,很值得学习。

前置介绍

niginx反向代理

前端和后端的url请求不一致的原因:前端是请求到nginx服务器,再由nginx服务器转发到后端

nginx的好处

1.提高访问速度,当这条数据相同,不必要到后端去处理了,之间有nginx服务器返回数据,nginx就相当于一个缓存,redis

2.进行负载均衡 ,后端可能有多个服务器,访问一个服务器,会导致服务器压力大,就由nginx把请求均匀分配给多个服务器

3.保证后端服务安全,直接把后端url暴露,是不安全的行为。让前端访问nginx服务器,不暴露后端

niginx配置

负债均衡配置

负债均衡策略

配置文件

接口文档

apifox

APIFOX是设计阶段使用的工具,管理和维护接口

创建项目-项目设置-导入数据-Yapi-导入数据

接口测试文档

Swagger是在开发阶段使用的框架,用在后端测试接口测试

Swagger常用注解

@Api用在类上,描述这个类中接口的作用

@ApiOperation用在方法上,描述此接口的功能

@ApiModel描述自定义返回类型

@ApiModelProperty描述参数的作用

用Swagger测试功能记得添加jwt令牌全局参数

添加全局参数 校验过令牌

1.正常获取令牌

2.添加全局参数

项目目录

项目分为三个包

sky-common、sky-pojo、sky-server

sky-common包主要存放的都是静态常量

sky-common包目录

如信息异常常量类:

sky-pojo包主要存放的是各种O 统称POJO和数据库对应的类

包目录

DTO是专门接收前端传来的数据,整合成一个类 统称DTO

VO是后端整合的数据传给前端,统称VO

sky-server包存放控制类、接口类、数据库Mapper和.XML以及配置类

接口实现

员工登录相关接口

前端穿的是JSON数据时,应加上@RequestBody注解 接收JSON文件

调用服务类接口

接口调用实现类

实现类

成功后生成jwt令牌

将数据整合为VO 返回

添加员工接口

这里就不再接收控制类 都是一样的 调用服务类 直接讲解服务类实现即可

数据初始化后,添加到数据库

分页查询

返回的类型是pageResut

使用的是PageHelper插件 简化分页查询

pageHelper是一个帮我们自动计算页数的插件

pom.xml

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>

使用方法:

传入当前页数,和每页多少条数据

//使用pageHelper 简化分页查询         参数1 当前查询的页数 参数2 每页多少条数据
PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

然后以Page<你数据库返回的对应的类>

Page<Employee> page=employeeMapper.getPage(employeePageQueryDTO);

SQL内 他会自动添加limit 不需要手动计算

//共有多少条数据
long total = page.getTotal();
//查询出来每页的数据
List<Employee> result = page.getResult();

之后从数据内取出对应的数据即可

使用PageHelper的startPage方法 传入当前页码,和每页多少条数据。

传入DTO 返回类型为Page<数据库返回的封装数据(Employee)>

取出共有多少条数据 每页的总数据

返回PageResult 数据为刚出的多少条数据 每页的总数据

page插件会自动把计算,并把limit加上

启用禁用用户状态接口

前端一个传的是url参数

需要加@PathVariable注解

将数据拷贝到完整数据类内

动态SQL 避免代码冗余

当某个字段不为空时,就加上对应的SQL语句

根据ID查询员工信息

查询后,密码即使加密过,也不暴露显示,统一改为

修改员工信息接口

因为前端传的是JSON数据 所以要加@RequestBody注解 接收JSON数据

将DTO数据拷贝到完整类内

SQL直接复用动态sql即可。

分类接口

分类接口大部分与员工接口逻辑相似

新增分类

将DTO数据拷贝到完整类内

分类分页查询

使用PageHelper插件帮忙计算limit

使用PageHelper的startPage方法传入当前页码和查询数量

返回总数和数据列表

SQL语句

删除分类

若分类中有关联菜品 无法直接删除

修改分类

将DTO数据拷贝到完整类内

动态SQL 提高复用性

启用、禁用分类

数据舒适化后,复用动态SQL

根据类型查询分类

公共接口

上传文件接口

这里使用的是OSS 客户端把图片,音频等上传到服务器,服务器不本地保存,上传到阿里云OSS内

配置OSS

阿里创建OSS

网页端上传服务端 服务端不在本地存放图片、视频、音频 而是在云端存放,这样不会在服务器消耗内存,减少服务器消耗。

登录阿里云 购买OSS

之后创建AccessKey 会让你下载一个excel 里面存放的是AccessKeyID和AccessKey Secret 这个只能查看一次,所以excel务必保存好。

endpoint 是域名的外围的endpoint 具体参考:

access-key-id和access-key-secret就是下载的excel文件内存放的

bucket-name就是你创建Bucket的名字

帮助中心

pom.xml

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId>
</dependency>
​
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId>
</dependency>

这是上传文件的配置文件

package com.sky.utils;
​
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
​
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
​private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
​/*** 文件上传** @param bytes* @param objectName* @return*/public String upload(byte[] bytes, String objectName) {
​// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
​try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}
​//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);
​log.info("文件上传到:{}", stringBuilder.toString());
​return stringBuilder.toString();}
}
创建一个配置类 创建Util对象

public class OssConfiguration {
​@Bean@ConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info("开始创建阿里上传文件对象{}",aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
​
}

创建一个公共接口

自定义注解

当插入数据或修改数据时,都需要手动更改创建人id 修改人id 创建时间,修改时间等,代码造成冗余,所以自定义一个注解,当执行此类操作时,统一完成操作即可,避免代码冗余

创建一个自定义注解接口

public class AutoFillAspect {
​/*** 指定切入点* 参数1 指定拦截的路径    参数2 注解存在的路径*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}
​/*** 前置通知,在通知中进行公共字段的赋值* 在方法执行前进行拦截 并且把对应属性赋值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint){log.info("开始进行公共字段自动填充...");
​//获取当前拦截方法中数据库上的操作类型MethodSignature signature=(MethodSignature) joinPoint.getSignature();AutoFill autoFill=signature.getMethod().getAnnotation(AutoFill.class);OperationType operationType=autoFill.value();
​//获取当前拦截方法的参数Object[] args=joinPoint.getArgs();if(args==null || args.length==0){return;}
​Object entity=args[0];
​//准备当前时间和用户idLocalDateTime now=LocalDateTime.now();Long currenId= BaseContext.getCurrentId();
​//根据数据库操作类型的不同,为对应的属性通过反射赋值if(operationType==OperationType.INSERT){//如果市插入数据 为四个属性赋值try {Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
​//通过反射为对象属性赋值setCreateTime.invoke(entity,now);setCreateUser.invoke(entity,currenId);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currenId);} catch (Exception e) {throw new RuntimeException(e);}}if(operationType==OperationType.UPDATE){//如果是修改 就为两个属性赋值try {Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
​//通过反射为对象属性赋值setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currenId);} catch (Exception e) {throw new RuntimeException(e);}}}

菜品管理接口

新增菜品接口

不仅仅要添加菜品 还要添加菜品的口味 菜品口味再另一个表

添加菜品口味 需要菜品的id 菜品id为自增 所以要返回菜品的id

插入菜品口味时,都需要设置菜品id

动态SQL 循环插入 第一个为形参参数 每个遍历出来的名字 用,分割

菜品分页接口

菜品停、启接口

复用SQL接口

根据ID查询菜品新接口

这个接口是当要修改菜品信息时 把菜品信息返回给前端

查询出菜品信息,还得查询菜品对应的口味数据

然后封装成VO返回给前端

批量删除菜品接口

前端穿的是String 1,2,3 这样的 使用@RequestParam转换成List<Long>类型

修改菜品接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149069.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

箭头与数字识别系统源码分享

箭头与数字识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…

《CUDA编程》1.GPU硬件与CUDA环境搭建

1 GPU 介绍 GPU&#xff08;graphics processing unit&#xff09;&#xff0c;意为图形处理器&#xff0c;也被称为显卡&#xff08;graphics card&#xff09;。GPU的浮点数运算峰值就比同时期的CPU高一个量级&#xff1b;GPU的内存带宽峰值也比同时期的CPU高一个量级。 CP…

数据结构 - 排序算法

一.直接插入排序 /*** description: 直接插入排序算法* param - a : 要进行排序的数组的指针* return : 无 */ void Seqsort(int *a) {/* i 用于表示无序部分的第一个元素的下标 &#xff0c; j 用于表示有序部分的最后一个元素的下标 &…

如何登录通义灵码,快速开启AI编码之旅?

通义灵码个人版开发者可以使用阿里云账号登录通义灵码 IDE 端插件&#xff0c;本文介绍个人版开发者登录 IDE 端插件的操作指南。 登录通义灵码 步骤 1&#xff1a;准备工作 已成功注册阿里云账号&#xff0c;具体操作可参考&#xff1a;账号注册&#xff08;PC端&#xff09;…

15.多线程概述(下篇)

目录 1.进程与线程 2.实现多线程方式一&#xff1a;继承Thread类【应用】 3.实现多线程方式二&#xff1a;实现Runnable接口【应用】 4.实现多线程方式三&#xff1a;实现Callable接口【应用】 5.三种实现方式的对比与套路 6.设置和获取线程名称/线程对象【应用】 7.线程优先级…

【编程底层原理】Java常用读写锁的使用和原理

一、引言 在Java的并发世界中&#xff0c;合理地管理对共享资源的访问是至关重要的。读写锁&#xff08;ReadWriteLock&#xff09;正是一种能让多个线程同时读取共享资源&#xff0c;而写入资源时需要独占访问的同步工具。本文将带你了解读写锁的使用方法、原理以及它如何提高…

【重磅】考虑火电机组储热改造的电力系统低碳经济调度

目录 1 主要内容 储热改造原理 约束条件 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序参考文献《考虑火电机组储热改造的电力系统低碳经济调度》&#xff0c;利用原文献火电机组储热改造方案建立模型&#xff0c;在传统火电机组的基础上加装热能存储系统&#xf…

【每天学个新注解】Day 3 Lombok注解简解(二)—@Log

Log 自动创建并初始化日志记录器 日志系列注解包括&#xff1a;CommonsLog、Flogger、JBossLog、Log、Log4j、Log4j2、Slf4j、XSlf4j、CustomLog&#xff0c;对应于不同的日志框架。每个注解都会在编译时生成一个名为 log 的静态字段&#xff0c;该字段被初始化为对应的日志框…

【小白向】怎么去除视频水印?HitPaw帮你轻松解决

序言 HitPaw是一款优秀的去除视频水印的工具。 特点&#xff1a;不仅仅能够去除图片、视频里的固定水印&#xff0c;还能去除移动水印。 尤其是它的AI去水印功能&#xff0c;效果非常好。 极简使用教程 下载安装 HitPaw需要在电脑上安装软件才能使用。 支持Windows系统和…

基于SpringBoot+Vue+MySQL的旅游推荐管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着社会的快速发展和人民生活水平的显著提高&#xff0c;旅游已成为人们休闲娱乐的重要方式。然而&#xff0c;面对海量的旅游信息和多样化的旅游需求&#xff0c;如何高效地管理和推荐旅游资源成为了一个亟待解决的问题。因此…

JavaSE--IO流总览03:复制照片案例,解决关闭流异常的方法

概述&#xff1a;本篇主要是讲述根据上一篇的知识完成一个小需求&#xff1a;图片的复制&#xff0c;以及关闭流的异常以及解决方法 一.照片的复制&#xff1a; 注意&#xff1a;字节流非常适合做一切文件的复制作 &#xff0c;任何文件的底层都是字节 字节流做复制 是一字不…

MODELS 2024:闪现奥地利,现场直击报道

周末出逃&#xff01;小编闪现至奥地利林茨&#xff0c;亲临第27届MODELS 2024国际会议&#xff0c;以第一视角引领你深入会议现场&#xff0c;领略其独特风采。利用午饭时间&#xff0c;小编紧急码字&#xff0c;只为第一时间将热点资讯呈现给你~ 会议介绍&#xff1a; MODEL…

Cilium + ebpf 系列文章-ebpf-map(二)

前言: 上一章节讲述了什么是:ebpf. Cilium + ebpf 系列文章-什么是ebpf?(一)-CSDN博客一、We Create a container be a Server.二、We Create a container be a Client.三、Them link at a Bridge.四、 Do test.一、Test-tools。3、当你执行l s操作时,会调用open的系统调…

线程对象的生命周期、线程等待和分离

线程对象的生命周期、线程等待和分离 #include <iostream> #include<thread> using namespace std;bool is_exit false;//用于判断主线程是否退出 void ThreadMain() {cout << "begin sub thread main ID: " << this_thread::get_id() &l…

难题妙解——前K个高频单词

1.题目解析 692.前K个高频单词 本题⽬我们利⽤map统计出次数以后&#xff0c;返回的答案应该按单词出现频率由⾼到低排序&#xff0c;有⼀个特殊要 求&#xff0c;如果不同的单词有相同出现频率&#xff0c;按字典顺序排序 2.算法原理 2.1思路一 ⽤排序找前k个单词&#xff0c…

栈的操作:进栈,出栈,读栈顶元素

代码&#xff1a; #include<iostream> using namespace std; template<class T> class sq_Stack {private:int mm;int top;T *s;public:sq_Stack(int);void prt_sq_Stack();int flag_sq_Stack();void ins_sq_Stack(T);T del_sq_Stack();T read_sq_Stack(); }; tem…

【自学笔记】支持向量机(3)——软间隔

引入 上一回解决了SVM在曲线边界的上的使用&#xff0c;使得非线性数据集也能得到正确的分类。然而&#xff0c;对于一个大数据集来说&#xff0c;极有可能大体呈线性分类趋势&#xff0c;但是边界处混杂&#xff0c;若仍采用原来的方式&#xff0c;会得到极其复杂的超平面边界…

Linux: filesystem:resize2fs: error: superblock checksum does not match

最近遇到一个resize2fs命令的错误:superblock checksum does not match superblock while trying to open。 而且问题的出现有随机性。 <qrms6-oam-b:root>/root: #rpm -qf /usr

通信工程学习:什么是VM虚拟机

VM&#xff1a;虚拟机 VM虚拟机&#xff08;Virtual Machine&#xff09;是一种通过软件模拟的计算机系统&#xff0c;它能够在物理计算机上模拟并运行多个独立的虚拟计算机系统。以下是关于VM虚拟机的详细解释&#xff1a; 一、VM虚拟机的定义与原理 定义&#xff1a; VM虚拟…

【ZYNQ 开发】填坑!双核数据采集系统LWIP TCP发送,运行一段时间不再发送且无法ping通的问题解决

问题描述 之所以说是填坑&#xff0c;是因为之前写了一篇关于这个双核数据采集系统的调试记录&#xff0c;问题的具体表现是系统会在运行一段时间后&#xff08;随机不定时&#xff0c;长了可能将近两小时&#xff0c;短则几分钟&#xff09;&#xff0c;突然间就不向电脑发送数…