苍穹外卖学习笔记(一)

news2025/1/9 1:19:47

文章目录

  • 开发环境搭建
    • 一. 前端环境搭建
    • 二. 后端环境搭建
      • 1.进入idea项目
      • 2.提交git仓库(+推送github远程仓库)
      • 3.数据库环境搭建
      • 4.前后端联调(在源代码中项目已经实现登录功能)
        • nginx反向代理好处:
    • 三. 完善登录功能(md5加密存储)
      • 1.首先打开pojo模块中实体类的employee,添加salt字段
      • 2.在数据库中employee表新建一个salt字段,注意得是字符串类型
      • 3.修改EmployeeServiceImpl类,添加加密处理
  • 接口文档的导入
  • 基于Swagger的Knife4j
    • Swagger常用注解​
      • @Tag
      • @Schema
      • @Content
      • @Hidden
      • @Operation
      • @Parameter
      • @Parameters
      • @RequestBody

开发环境搭建

首先把资料下载,网盘链接:黑马程序员苍穹外资料链接

鉴于很多Windows的朋友没有下载百度网盘客户端或者出现打不开、登录不上的问题,在这里推荐大家使用Tampermonkey+IDM 的脚本管理器方式下载

  1. 首先在浏览器中下载Tampermonkey拓展
    在其添加脚本中下载网盘直链下载助手

  2. 下载多线程下载器IDM(并且下载使用浏览器扩展)
    IDM 全称为 Internet Download Manager,仅支持 Windows 平台,Mac 平台可使用 NDM 代替。

    1. 打开 IDM 选项,将自己的浏览器加入 IDM 的捕获列表中。
    2. 把要支持 IDM 下载的后缀名添加到 IDM 选项 -> 文件类型里。
      后缀:
    3GP 7Z AAC ACE AI AIF ALZ APK APP APPX APPXBUNDLE ARC ARJ ASF AVI BH BIN BR BUNDLE BZ BZ2 CDA CSV DIF DLL DMG DOC DOCX EGG EPS EXE FLV GZ GZIP IMG IPA ISO ISZ JAR KEXT LHA LZ LZH LZMA M4A M4V MDB MID MKV MOV MP3 MP4 MPA MPE MPEG MPG MSI MSIX MSIXBUNDLE MSU MUI OGG OGV PDF PKG PPT PPTX PSD PST PUB QT R0* R1* RA RAR RM RMVB RTF SEA SIT SITX SLDM SLDX TAR TBZ TBZ2 TGZ TIF TIFF TLZ TXZ UDF VOB VSD VSDM VSDX VSS VSSM VST VSTM VSTX WAR WAV WBK WIM WKS WMA WMD WMS WMV WMZ WP5 WPD WPS XLS XLSX XPS XZ Z ZIP ZIPX ZPAQ ZSTD
    

    20240906210957

  3. 打开网页版百度网盘就可以下载了

一. 前端环境搭建

前端工程基于nginx部署
注意:必须将nginx相关代码存放到英文目录下,否则nginx不能启动

启动之后打开浏览器搜索locatehost即可

鉴于之后要经常使用它,我能可以使用edge浏览器的应用功能,将该网站作为应用安装,快速使用
20240906211803
如图:
20240906211822

二. 后端环境搭建

后端工程基于Maven分模块开发构建该spring项目

1.进入idea项目

用idea打开项目在pom.xml文件中引入依赖

20240906212410

直接clean然后install即可
20240906212527

该项目结构比较简单,就是一个父工程聚合三个子模块的单体架构,可以说是当前主流的前后端中的必过项目了

这里对具体项目结构不再详细阐述

2.提交git仓库(+推送github远程仓库)

具体配置idea的github远程仓库这里不再描述

20240906213621

3.数据库环境搭建

复制sky.sql代码到数据库控制台中运行即可
20240906214205

共有11张表
20240906214258

4.前后端联调(在源代码中项目已经实现登录功能)

具体流程如下:
20240906214532

启动之前先使用maven工具中compile进行编译
20240906214641

注意在这里把数据库配置改成自己的
20240906215125

启动项目:
20240906214750

运行结果:
20240906215220

nginx反向代理好处:
  1. 提高访问速度
  2. 进行负载均衡
  3. 保证后端服务安全
  4. 解决跨域问题

三. 完善登录功能(md5加密存储)

思路:

  1. 将密码加密后存储,提高安全性
  2. 使用md5加密方式对明文密码加密

视频中是直接使用了DigestUtils中的MD5加密来提高安全性,鉴于MD5现在已经有点不太安全,市面上已经有了破解的方法,这里使用MD5加盐处理来进一步提高安全性

由于前端问题,这里不再提高注册的方法,直接自创一个类把需要的盐和加密后的密码获取,手动输入到数据库中对应字段

// 生成一个新的盐值
private static final SecureRandom RANDOM = new SecureRandom();
//随机数生成器
private static final int SALT_LENGTH = 16;//盐的长度

String salt = generateSalt();

// 使用生成的盐值对密码进行加密
String password = "123456";
String hashedPassword = hashPassword(password, salt);

// 打印生成的盐值和加密后的密码
System.out.println("Salt: " + salt);
System.out.println("Hashed Password: " + hashedPassword);

// 生成盐的方法
private String generateSalt() {
    byte[] salt = new byte[SALT_LENGTH];
    RANDOM.nextBytes(salt);
    return Base64.getEncoder().encodeToString(salt);
}

// 对密码进行加密的方法
private String hashPassword(String password, String salt) {
    String saltedPassword = salt + password;
    return DigestUtils.md5DigestAsHex(saltedPassword.getBytes());
}

登录验证问题

1.首先打开pojo模块中实体类的employee,添加salt字段

package com.sky.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    private String username;

    private String name;

    private String password;

    private String phone;

    private String sex;

    private String idNumber;

    private Integer status;

    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;

    private Long createUser;

    private Long updateUser;

    private String salt;

}

2.在数据库中employee表新建一个salt字段,注意得是字符串类型

20240907142934

3.修改EmployeeServiceImpl类,添加加密处理

package com.sky.service.impl;

import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Base64;

import java.security.SecureRandom;

@Slf4j
@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    private static final SecureRandom RANDOM = new SecureRandom();//随机数生成器
    private static final int SALT_LENGTH = 16;//盐的长度

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */


    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        //对前端传来的密码进行md5加盐处理,然后再进行比对
        String salt = employee.getSalt();//盐
        String hashedPassword = hashPassword(password, salt);//加密后的密码

        if (!hashedPassword.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    //对密码进行加密
    private String hashPassword(String password, String salt) {
        String saltedPassword = salt + password;
        return DigestUtils.md5DigestAsHex(saltedPassword.getBytes());
    }
}

然后就可以登录成功了

接口文档的导入

这里使用apifox软件来导入
导入时选择YApi的json格式来导入
20240907143439

具体如下:
20240907143544

基于Swagger的Knife4j

使用方式:

  1. 导入Knife4j的Maven坐标
  2. 在配置类中加入Knife4j相关配置
  3. 设置静态资源映射,否则接口文档页面无法访问

具体代码在server中配置文件WebMvcConfiguration类中

/**
     * 通过knife4j生成接口文档
     * @return
     */
    @Bean
    public Docket docket() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("苍穹外卖项目接口文档")
                .version("2.0")
                .description("苍穹外卖项目接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

    /**
     * 设置静态资源映射
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

运行项目后在浏览器输入http://localhost:8080//doc.html即可进入
20240907144202

配置apifox中环境变量
20240907144719

调试:
20240907144741

可以成功

Swagger常用注解​

注解说明(OpenAPI3规范)

OpenApi3规范中文文档

20240907145334

@Tag

用于说明或定义的标签。

部分参数:

name:名称
description:描述

@Schema

用于描述实体类属性的描述、示例、验证规则等,比如 POJO 类及属性。

部分参数:

name:名称
title:标题
description:描述
example:示例值
required:是否为必须
format:属性的格式。如 @Schema(format = "email")
maxLength 、 minLength:指定字符串属性的最大长度和最小长度
maximum 、 minimum:指定数值属性的最大值和最小值
pattern:指定属性的正则表达式模式
type: 数据类型(integer,long,float,double,string,byte,binary,boolean,date,dateTime,password),必须是字符串。如 @Schema=(type="integer")
implementation :具体的实现类,可以是类本身,也可以是父类或实现的接口

@Content

内容注解。

部分参数:

mediaType:内容的类型。比如:application/json
schema:内容的模型定义,使用 @Schema 注解指定模型的相关信息。
@RequestBody(content = @Content(mediaType = "application/json", schema = @Schema(implementation = User.class))) 
@PostMapping("/users")
public void createUser(User user) {
    // ...
}

@Hidden

某个元素(API 操作、实体类属性等)是否在 API 文档中隐藏。
如,getUserById 方法不会显示在 API 文档中

使用在实体类字段中,实现对敏感信息或不需要公开的元素进行隐藏。如:用户密码字段

@Operation

描述 API 操作的元数据信息。常用于 controller 上
部分参数:

summary:简短描述
description :更详细的描述
hidden:是否隐藏
tags:标签,用于分组API
operationId:操作的唯一标识符,建议使用唯一且具有描述性的名称
parameters:指定相关的请求参数,使用 @Parameter 注解来定义参数的详细属性。
requestBody:指定请求的内容,使用 @RequestBody 注解來指定请求的类型。
responses:指定操作的返回内容,使用 @ApiResponse 注解定义返回值的详细属性。

@Parameter

用于描述 API 操作中的参数
部分参数:

name : 指定的参数名
in:参数来源,可选 query、header、path 或 cookie,默认为空,表示忽略
ParameterIn.QUERY 请求参数
ParameterIn.PATH 路径参数
ParameterIn.HEADER header参数
ParameterIn.COOKIE cookie 参数
description:参数描述
required:是否必填,默认为 false
schema :参数的数据类型。如 schema = @Schema(type = "string")

@Parameters

包含多个 @Parameter 注解,指定多个参数。
代码参考:
包含了 param1 和 param2 两个参数

@RequestBody

API 请求的注解

description:请求信息的描述
content:请求的内容
required:是否必须
@ApiResponse
API 的响应信息。
部分参数:

responseCode:响应的 HTTP 状态码
description:响应信息的描述
content:响应的内容

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

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

相关文章

[STL --stack_queue详解]stack、queue,deque,priority_queue,容器适配器

stack stack介绍 1、stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 2、stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供…

原理图库和PCB库的命名规范及创建封装、使用封装管理器

原理图库 命名规范 原理图中元件值标注规则 注:元件值(Component Value)就是元件最主要的特征对应的值。 Component value. Most analog components have a value that must be specified by this field (e.g., 2.7 kΩ). Additional disti…

c++数据结构之队列

目录 一、队列的含义 1.队列的使用 2.队列的结构 二、顺序队列的实现 1.队列的定义 2.队列的初始化 3.清空对列 4.队列是否为空 5.获取队列的长度 6.获取头元素的值 7.入队列 8.出队列 9.遍历队列中的值 10.总代码 11.打印结果 三、链表队列的实现 1.队列的…

【Hot100】LeetCode—347. 前 K 个高频元素

目录 1- 思路自定义Node结点 哈希表实现 2- 实现⭐347. 前 K 个高频元素——题解思路 3- ACM实现 原题连接:347. 前 K 个高频元素 1- 思路 自定义Node结点 哈希表实现 ① 自定义 Node 结点: 自定义 Node 结点中有 value 和 cnt 字段,其中…

力扣接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表…

html css网页制作

​ 大家好,我是程序员小羊! 前言: HTML 和 CSS 是制作网页的基础。HTML 用于定义网页的结构和内容,CSS 用于设计网页的样式和布局。以下是一个详细的网页制作成品教程,包括 HTML 和 CSS 的基础知识,及如何…

MySQL基础(7)- 多表查询

目录 一、笛卡尔积的错误与正确的多表查询 1.出现笛卡尔积错误 2.正确的多表查询:需要有连接条件 3.查询多个表中都存在的字段 4.SELECT和WHERE中使用表的别名 二、等值连接vs非等值连接、自连接vs非自连接 1.等值连接 vs 非等值连接 2.自连接 vs 非自连…

安卓逆向(之)真机root(红米手机)

概览: 1, 手机解锁 2, 下载官方系统包,推荐线刷包,取出镜像文件 3, magisk工具修补 官方系统包 4, adb:命令对手机刷 root 5, 完成 6, 小米手机解锁 点击 小米手机解锁OEM官方教程 记得数据线连接手机电脑 工具下载 点击 下载adb(电脑操作…

进程间通信-进程池

目录 理解​ 完整代码 完善代码 回收子进程&#xff1a;​ 不回收子进程&#xff1a; 子进程使用重定向优化 理解 #include <iostream> #include <unistd.h> #include <string> #include <vector> #include <sys/types.h>void work(int rfd) {…

Windows下使用cmake编译OpenCV

Windows下使用cmake编译OpenCV cmake下载OpenCV下载编译OpenCV cmake下载 下载地址&#xff1a;https://cmake.org/download/ 下载完成&#xff0c;点击选择路径安装即可 OpenCV下载 下载地址&#xff1a;https://github.com/opencv/opencv/releases/tag/4.8.1因为我们是编译…

2024软件测试需要具备的技能(软技能硬技能)

软件测试的必备技能 在往期的文章分享了很多的面试题&#xff0c;索性做一个转型。从零基础开始讲解&#xff0c;结合面试题来和大家一起学习交流软件测试的艺术。 第一个是专业技能&#xff0c;也叫硬技能。 第二个叫做软技能。 我们在上一篇文章中讲到了软件测试流程的5个…

ChatGPT在论文写作领域的应用:初稿设计

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 学术论文写作中&#xff0c;内容清晰、结构合理的初稿至关重要。通过 ChatGPT&#xff0c;写作者可以快速生成内容框架、明确研究问题&#xff0c;并优化表达方式。不仅提高了写作效率&…

笔记整理—内核!启动!—kernel部分(1)驱动与内核的关系

首先&#xff0c;恭喜完成了uboot部分的内容整理&#xff0c;其次补充一点&#xff0c;uboot第一部分和第二部分的工作不是一定的&#xff0c;在不同的版本中&#xff0c;可能这个初始化早一点&#xff0c;那个的又放在了第二部分&#xff0c;版本不同&#xff0c;造成的工作顺…

滑动窗口——632. 最小区间

最近在抽时间写LC上的一个专栏——2024春招冲刺百题计划。挑着做&#xff0c;做了几道和滑动窗口相关的题目&#xff0c;632. 最小区间&#xff0c;LC上标记为困难&#xff0c;第一次写完全没有思考&#xff0c;参考了别人写的答案茅塞顿开&#xff0c;特此记录以鞭策自己学习。…

Android perfetto 简介

Android perfetto 简介 使用 perfetto 工具&#xff0c;您可以通过 Android 调试桥 (adb) 在 Android 设备上收集性能信息。使用 adb shell perfetto ... 命令调用 perfetto 工具。 perfetto 从您的设备上收集性能跟踪数据时会使用多种来源&#xff0c;例如&#xff1a; 使用…

5、const修饰类型和变量

const修饰类型和变量 一、const常量一些注意点1、声明时必须同时初始化2、不可更改3、与宏常量的区别 二、const修饰指针1、常量指针constant pointer2、常指向指针pointer-to-constant pointer 一、const常量一些注意点 1、声明时必须同时初始化 #include <iostream> …

框架template初识

框架初识 框架就是一个别人帮我们搭好的舞台&#xff0c;造好了很多现成的工具供我们使用&#xff0c;让开发过程更快速、简洁。 Gin框架介绍 Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。 Gin是一个用Go语言编写的web框架。它是一个类似于martini 但拥有更好性能的API…

企业网银登录提示请确认您已插入工商银行U盾证书的解决方法

昨天受人之托帮小企业财务解决上网银的问题 因为不是专业做这个的&#xff0c;所以只能安装“常识”行事&#xff0c;但结果实在是令人意想不到。 排错的步骤&#xff1a; 同一台电脑上尝试不同浏览器&#xff0c;发现360浏览器的接受度相当普遍&#xff1b;给U盾换不同的连接…

抖音引流脚本工具,实现自动化引流,解放大家双手

抖音引流脚本工具,实现自动化引流,解放大家双手 #获客引流 推荐阅读&#xff1a; 百收网SEO引流脚本软件不断更新&#xff08;推广全集教程&#xff09;https://www.bsw80.com/post/460.html 我们这篇文章的话&#xff0c;来去给大家说一下这个抖音这个同城评论&#xff0c;…

探索 RAD:5 个最佳实践案例解析

天下武功&#xff0c;唯快不破&#xff01;应用开发&#xff0c;唯速称王&#xff01; 在当今快速发展的科技环境中&#xff0c;企业面临的挑战不断升级。传统的应用开发方法往往因其复杂的流程和较长的开发周期而无法满足快速变化的市场需求。在这种背景下&#xff0c;快速应…