苍穹外卖上半部分总结

news2024/9/23 23:35:05

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

前置介绍

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/ObjectName
        StringBuilder 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
    @ConditionalOnMissingBean
    public 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];
​
        //准备当前时间和用户id
        LocalDateTime 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.coloradmin.cn/o/2158763.html

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

相关文章

个人防护装备检测系统源码分享

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

字母与符号检测系统源码分享

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

全国职业院校技能大赛(大数据赛项)-平台搭建Spark、Scala笔记

Spark作为一个开源的分布式计算框架拥有高效的数据处理能力、丰富的生态系统、多语言支持以及广泛的行业应用。Scala是一种静态类型的编程语言&#xff0c;它结合了面向对象编程和函数式编程的特性&#xff0c;被誉为通用的“大数据语言”。而二者的结合更能迸发出新奇的化学反…

深度学习之微积分预备知识点(2)

极限&#xff08;Limit&#xff09; 定义&#xff1a;表示某一点处函数趋近于某一特定值的过程&#xff0c;一般记为 极限是一种变化状态的描述&#xff0c;核心思想是无限靠近而永远不能到达 公式&#xff1a; 表示 x 趋向 a 时 f(x) 的极限。 知识点口诀解释极限的存在左…

itextsharp报错 PdfReader not opened with owner password

itextsharp报错 PdfReader not opened with owner password itextsharp读取PDF时报错&#xff1a; PdfReader not opened with owner password 报错原因(据说是)&#xff1a;pdf 文件设置了加密。 网上搜索了一下&#xff0c;查到大多数答案是&#xff1a; 在创建pdfReader…

JDK7u21 HashMap版

今天在搞ROME HotSwappableTargetSource链的时候突然发现&#xff0c;JDK7U21反序列化链不仅HashMap.put触发了key.equals putForCreate也调用了 而且HashMap.readObject直接调用了putForCreate来还原 what?直接向HashMap两个put不就完了&#xff0c;还搞什么HashSet 开弄&am…

闪回科技再冲刺上市:曾夸大融资规模,毛利率下滑,有股东退出

近日&#xff0c;闪回科技有限公司&#xff08;下称“闪回科技”&#xff09;递交招股书&#xff0c;准备在港交所主板上市。据贝多财经了解&#xff0c;该公司曾于2024年2月递表&#xff0c;此次是“失效”后的更新版本&#xff0c;清科资本为其独家保荐人。 闪回科技在招股书…

5款好用的电脑软件,个个良心实用

分享5款好用但冷门的windows软件&#xff0c;个个良心实用&#xff0c;而且大部分免费&#xff0c;值得统统装进电脑里&#xff01; 1、EagleGet——高速下载器 一款免费的高速下载软件&#xff0c;页面设计简洁&#xff0c;没有广告&#xff0c;支持 HTTP、HTTPS、FTP、MMS、…

​数据库: MyBatis-Plus

MyBatis-Plus MyBatis-Plus 是 MyBatis 的增强工具&#xff0c;核心作用是简化 CRUD 操作和提升开发效率。它提供基础的增删改查方法、分页插件、条件构造器以及代码生成器&#xff0c;帮助减少重复代码量。MyBatis-Plus 不支持自动建表&#xff0c;专注于简化数据库操作&…

QT中添加资源文件

什么是资源文件 项目中经常需要添加图片、‌音频、‌视频、翻译文件等文件&#xff0c;在QT中&#xff0c;这些文件会放在 .qrc 文件中来被使用。 .qrc 文件是一个XML格式的资源集合描述文件&#xff0c;是Qt中用于定义和管理资源的关键文件 如何使用 创建资源文件 在你的Qt项…

面试真题:谈一谈Mysql的分库分表

分表和分库是什么&#xff1f;有什么区别&#xff1f; 分库是一种水平扩展数据库的技术&#xff0c;将数据根据一定规则划分到多个独立的数据库中。每个数据库只负责存储部分数据&#xff0c;实现了数据的拆分和分布式存储。分库主要是为了解决并发连接过多&#xff0c;单机 my…

一行命令,一分钟轻松搞定SSL证书自动续期

httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;专为 Nginx 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。现在的网站SSL免费证书有效期只有3个月&#xff0c;所以就会有经常更快SSL证书的需求&#xff0c;如果手上需要更换的SSL证书比较多的情况下…

DoppelGanger++:面向数据库重放的快速依赖关系图生成

doi&#xff1a;DoppelGanger: Towards Fast Dependency Graph Generation for Database Replay&#xff0c;点击前往 文章目录 1 简介2 架构概述3 依赖关系图3.1 符号和问题定义3.2 无 IT(k) 图3.3 无 OT 图表3.4 无 OTIT 图表3.5 无 IT[OT] 图表3.6 输出确定性保证 4 重复向后…

win10 win11 设置文件权限以解决Onedrive不能同步问题

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

蓝牙AOA基站助力打造智慧医院管理系统

随着科技的飞速发展&#xff0c;智慧医院的概念逐渐深入人心。其中&#xff0c;蓝牙AOA&#xff08;到达角&#xff09;定位技术以其高精度、低功耗、低成本等优势&#xff0c;在智慧医院建设中扮演着重要角色。本文将深入探讨蓝牙AOA基站如何助力智慧医院的建设与发展。 一、蓝…

CVE-2024-4956实战

一、访问网页 二、公司信息域名收集 三、抓包读取敏感文件 Burpsuite抓包&#xff0c;修改GET请求即可&#xff08;GET /%2F%2F%2F%2F%2F%2F%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd HTTP/1.1 &#xff09;

点赞系统实现

点赞功能是社交、电商等几乎所有的互联网项目中都广泛使用。虽然看起来简单&#xff0c;不过蕴含的技术方案和手段还是比较多的。 下面将分享之前做的判题OJ系统的点赞系统的思路。 1.需求分析 点赞功能与其它功能不同&#xff0c;没有复杂的原型和需求&#xff0c;仅仅是一…

shardingjdbc介绍

文章目录 1、shardingjdbc介绍1.1、读写分离、数据分片&#xff08;分库分表&#xff09;中间件&#xff1a;1.1.1、shardingsphere1.1.2、mycat 2、shardingjdbc-demo搭建2.1、创建项目2.2、添加依赖2.3、application.yml2.4、创建实体类 User2.5、创建 UserMapper2.6、创建测…

筛子排序(SieveSort)

当你手头有了支持AVX-512&#xff08;SIMD&#xff09;的i9-11900K&#xff0c;你最想做什么&#xff1f; i9-11900K&#xff1f;现在都14代了&#xff0c;谁还用11代的&#xff1f; 但12代以上就没有AVX-512了&#xff01; AVX-512有什么特别之处&#xff1f;有了这个硬件支…

How do you send files to the OpenAI API?

题意&#xff1a;你如何向 OpenAI API 发送文件 问题背景&#xff1a; For fun I wanted to try to make a tool to ask chatgpt to document rust files. I found an issue, in that the maximum message length the API allows seems to be 2048 characters. 为了好玩&…