基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(一)

news2024/11/27 7:43:07

熟悉项目环境

  • 1. 苍穹外卖项目介绍
    • 1.1 项目介绍
    • 1.2 技术选型
  • 2. 开发环境搭建
    • 2.1 前端环境
    • 2.2 后端环境搭建
    • 2.3 Git版本控制
    • 2.4 nginx反向代理和负载均衡
  • 3.登录功能
  • 4. Swagger
    • 4.1 介绍
    • 4.2 使用步骤
    • 4.3 常用注解

1. 苍穹外卖项目介绍

1.1 项目介绍

苍穹外卖是专门为餐饮企业(餐厅、饭店)定制的一款软件产品,包括 系统管理后台 和 小程序端应用 两部分。其中系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的分类、菜品、套餐、订单、员工等进行管理维护,对餐厅的各类数据进行统计,同时也可进行来单语音播报功能。小程序端主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单、支付、催单等。

在这里插入图片描述

项目分为管理端用户端

在这里插入图片描述

1). 管理端

餐饮企业内部员工使用。 主要功能有:

模块描述
登录/退出内部员工必须登录后,才可以访问系统管理后台
员工管理管理员可以在系统后台对员工信息进行管理,包含查询、新增、编辑、禁用等功能
分类管理主要对当前餐厅经营的 菜品分类 或 套餐分类 进行管理维护, 包含查询、新增、修改、删除等功能
菜品管理主要维护各个分类下的菜品信息,包含查询、新增、修改、删除、启售、停售等功能
套餐管理主要维护当前餐厅中的套餐信息,包含查询、新增、修改、删除、启售、停售等功能
订单管理主要维护用户在移动端下的订单信息,包含查询、取消、派送、完成,以及订单报表下载等功能
数据统计主要完成对餐厅的各类数据统计,如营业额、用户数量、订单等

2). 用户端

移动端应用主要提供给消费者使用。主要功能有:

模块描述
登录/退出用户需要通过微信授权后登录使用小程序进行点餐
点餐-菜单在点餐界面需要展示出菜品分类/套餐分类, 并根据当前选择的分类加载其中的菜品信息, 供用户查询选择
点餐-购物车用户选中的菜品就会加入用户的购物车, 主要包含 查询购物车、加入购物车、删除购物车、清空购物车等功能
订单支付用户选完菜品/套餐后, 可以对购物车菜品进行结算支付, 这时就需要进行订单的支付
个人信息在个人中心页面中会展示当前用户的基本信息, 用户可以管理收货地址, 也可以查询历史订单数据

1.2 技术选型

在这里插入图片描述
1). 用户层

本项目中在构建系统管理后台的前端页面,我们会用到H5、Vue.js、ElementUI、apache echarts(展示图表)等技术。而在构建移动端应用时,我们会使用到微信小程序。

2). 网关层

Nginx是一个服务器,主要用来作为Http服务器,部署静态资源,访问性能高。在Nginx中还有两个比较重要的作用: 反向代理和负载均衡, 在进行项目部署时,要实现Tomcat的负载均衡,就可以通过Nginx来实现。

3). 应用层

SpringBoot: 快速构建Spring项目, 采用 “约定优于配置” 的思想, 简化Spring项目的配置开发。

SpringMVC:SpringMVC是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合,可以无缝集成。

Spring Task: 由Spring提供的定时任务框架。

httpclient: 主要实现了对http请求的发送。

Spring Cache: 由Spring提供的数据缓存框架

JWT: 用于对应用程序上的用户进行身份验证的标记。

阿里云OSS: 对象存储服务,在项目中主要存储文件,如图片等。

Swagger: 可以自动的帮助开发人员生成接口文档,并对接口进行测试。

POI: 封装了对Excel表格的常用操作。

WebSocket: 一种通信网络协议,使客户端和服务器之间的数据交换更加简单,用于项目的来单、催单功能实现。

4). 数据层

MySQL: 关系型数据库, 本项目的核心业务数据都会采用MySQL进行存储。

Redis: 基于key-value格式存储的内存数据库, 访问速度快, 经常使用它做缓存。

Mybatis: 本项目持久层将会使用Mybatis开发。

pagehelper: 分页插件。

spring data redis: 简化java代码操作Redis的API。

5). 工具

git: 版本控制工具, 在团队协作中, 使用该工具对项目中的代码进行管理。

maven: 项目构建工具。

junit:单元测试工具,开发人员功能实现完毕后,需要通过junit对功能进行单元测试。

postman: 接口测工具,模拟用户发起的各类HTTP请求,获取对应的响应结果。

2. 开发环境搭建

在这里插入图片描述

2.1 前端环境

1). 前端工程基于 nginx

双击 nginx.exe 即可启动 nginx 服务,访问端口号为 80

http://localhost:80

在这里插入图片描述
(如果启动不了,可能是端口号冲突,在nginx的配置文件中修改端口号即可)。

2.2 后端环境搭建

后端工程基于 maven 进行项目构建,并且进行分模块开发。

1). 用 IDEA 打开初始工程,了解项目的整体结构:

在这里插入图片描述
2). 数据库共11张表,每张表的说明:

序号表名中文名
1employee员工表
2category分类表
3dish菜品表
4dish_flavor菜品口味表
5setmeal套餐表
6setmeal_dish套餐菜品关系表
7user用户表
8address_book地址表
9shopping_cart购物车表
10orders订单表
11order_detail订单明细表

3). 导入接口文档:
项目是基于前后端分离开发的·,所有需要根据接口文档来开发。
在这里插入图片描述

2.3 Git版本控制

使用Git进行项目代码的版本控制,具体操作:

1). 创建Git本地仓库

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

当Idea中出现:

在这里插入图片描述
说明本地仓库创建成功。

2). 创建Git远程仓库

访问https://gitee.com/,新建仓库
在这里插入图片描述

点击 创建
在这里插入图片描述
3). 将本地文件推送到Git远程仓库

  1. 提交文件至本地仓库

    忽略以下类型文件

在这里插入图片描述

开始提交

在这里插入图片描述

中间出现:点击commit

在这里插入图片描述

  1. 添加Git远程仓库地址

    复制远程地址:

在这里插入图片描述

添加地址:

在这里插入图片描述
在这里插入图片描述

  1. 推送

在这里插入图片描述

成功推送至远程仓库

在这里插入图片描述

2.4 nginx反向代理和负载均衡

我们先思考一个问题:前端发送的请求,是如何请求到后端服务的?

前端请求地址:http://localhost/api/employee/login
在这里插入图片描述
后端接口地址:http://localhost:8080/admin/employee/login
在这里插入图片描述

很明显,两个地址不一致,那是如何请求到后端服务的呢?

在这里插入图片描述

1). nginx反向代理

nginx 反向代理,就是将前端发送的动态请求由 nginx 转发到后端服务器

在这里插入图片描述

那为什么不直接通过浏览器直接请求后台服务端,需要通过nginx反向代理呢?

nginx 反向代理的好处:

  • 提高访问速度

    因为nginx本身可以进行缓存,如果访问的同一接口,并且做了数据缓存,nginx就直接可把数据返回,不需要真正地访问服务端,从而提高访问速度。

  • 进行负载均衡

    所谓负载均衡,就是把大量的请求按照我们指定的方式均衡的分配给集群中的每台服务器。

  • 保证后端服务安全

    因为一般后台服务地址不会暴露,所以使用浏览器不能直接访问,可以把nginx作为请求访问的入口,请求到达nginx后转发到具体的服务中,从而保证后端服务的安全。

在这里插入图片描述

nginx 反向代理的配置方式:

server{
    listen 80;
    server_name localhost;
    
    location /api/{
        proxy_pass http://localhost:8080/admin/; #反向代理
    }
}

proxy_pass:该指令是用来设置代理服务器的地址,可以是主机名称,IP地址加端口号等形式。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/…/…这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://localhost:8080/admin/上来。

接下来,进到nginx-1.20.2\conf,打开nginx配置

# 反向代理,处理管理端发送的请求
location /api/ {
	proxy_pass   http://localhost:8080/admin/;
    #proxy_pass   http://webservers/admin/;
}

当在访问http://localhost/api/employee/login,nginx接收到请求后转到http://localhost:8080/admin/,故最终的请求地址为http://localhost:8080/admin/employee/login,和后台服务的访问地址一致。

2). nginx 负载均衡

当如果服务以集群的方式进行部署时,那nginx在转发请求到服务器时就需要做相应的负载均衡。其实,负载均衡从本质上来说也是基于反向代理来实现的,最终都是转发请求。

nginx 负载均衡的配置方式:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}
server{
    listen 80;
    server_name localhost;
    
    location /api/{
        proxy_pass http://webservers/admin;#负载均衡
    }
}

upstream:如果代理服务器是一组服务器的话,我们可以使用upstream指令配置后端服务器组。

如上代码的含义是:监听80端口号, 然后当我们访问 http://localhost:80/api/…/…这样的接口的时候,它会通过 location /api/ {} 这样的反向代理到 http://webservers/admin,根据webservers名称找到一组服务器,根据设置的负载均衡策略(默认是轮询)转发到具体的服务器。

:upstream后面的名称可自定义,但要上下保持一致。

nginx 负载均衡策略:

名称说明
轮询默认方式
weight权重方式,默认为1,权重越高,被分配的客户端请求就越多
ip_hash依据ip分配方式,这样每个访客可以固定访问一个后端服务
least_conn依据最少连接方式,把请求优先分配给连接数少的后端服务
url_hash依据url分配方式,这样相同的url会被分配到同一个后端服务
fair依据响应时间方式,响应时间短的服务将会被优先分配

具体配置方式:

轮询:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

weight:

upstream webservers{
    server 192.168.100.128:8080 weight=90;
    server 192.168.100.129:8080 weight=10;
}

ip_hash:

upstream webservers{
    ip_hash;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

least_conn:

upstream webservers{
    least_conn;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

url_hash:

upstream webservers{
    hash &request_uri;
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
}

fair:

upstream webservers{
    server 192.168.100.128:8080;
    server 192.168.100.129:8080;
    fair;
}

3.登录功能

问题:员工表中的密码是明文存储,安全性太低。

在这里插入图片描述

解决思路:

  1. 将密码加密后存储,提高安全性

在这里插入图片描述

  1. 使用MD5加密方式对明文密码加密

在这里插入图片描述

实现步骤:

  1. 修改数据库中明文密码,改为MD5加密后的密文
    在这里插入图片描述1.Controller层

在sky-server模块中,com.sky.controller.admin.EmployeeController

/**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        log.info("员工登录:{}", employeeLoginDTO);
		//调用service方法查询数据库
        Employee employee = employeeService.login(employeeLoginDTO);

        //登录成功后,生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
                .id(employee.getId())
                .userName(employee.getUsername())
                .name(employee.getName())
                .token(token)
                .build();

        return Result.success(employeeLoginVO);
    }

2.Service层

在sky-server模块中,com.sky.service.impl.EmployeeServiceImpl

 /**
        * 员工登录
        *
        * @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加密,然后再进行比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());


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

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

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

3.Mapper层

在sky-server模块中,com.sky.mapper.EmployeeMapper

package com.sky.mapper;

import com.sky.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface EmployeeMapper {

    /**
     * 根据用户名查询员工
     * @param username
     * @return
     */
    @Select("select * from employee where username = #{username}")
    Employee getByUsername(String username);

}

4. Swagger

4.1 介绍

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是:

  1. 使得前后端分离开发更加方便,有利于团队协作

  2. 接口的文档在线自动生成,降低后端开发人员编写接口文档的负担

  3. 功能测试

    Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!

目前,一般都使用knife4j框架。

4.2 使用步骤

  1. 导入 knife4j 的maven坐标

    在pom.xml中添加依赖

    <dependency>
       <groupId>com.github.xiaoymin</groupId>
       <artifactId>knife4j-spring-boot-starter</artifactId>
    </dependency>
    
  2. 在配置类中加入 knife4j 相关配置

    WebMvcConfiguration.java

    /**
         * 通过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;
        }
    
  3. 设置静态资源映射,否则接口文档页面无法访问

    WebMvcConfiguration.java

    /**
         * 设置静态资源映射
         * @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/");
    }
    
  4. 访问测试

    接口文档访问路径为 http://ip:port/doc.html —> http://localhost:8080/doc.html

在这里插入图片描述

4.3 常用注解

通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:

注解说明
@Api用在类上,例如Controller,表示对类的说明
@ApiModel用在类上,例如entity、DTO、VO
@ApiModelProperty用在属性上,描述属性信息
@ApiOperation用在方法上,例如Controller的方法,说明方法的用途、作用

接下来,使用上述注解,生成可读性更好的接口文档

在sky-pojo模块中

EmployeeLoginDTO.java

@Data
@ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable {

    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("密码")
    private String password;

}

EmployeeLoginVo.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "员工登录返回的数据格式")
public class EmployeeLoginVO implements Serializable {

    @ApiModelProperty("主键值")
    private Long id;

    @ApiModelProperty("用户名")
    private String userName;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("jwt令牌")
    private String token;

}

在sky-server模块中

EmployeeController.java

/**
 * 员工管理
 */
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "员工相关接口")
public class EmployeeController {
    /**
     * 登录
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) 	{
        //.............
    }

    /**
     * 退出
     */
    @PostMapping("/logout")
    @ApiOperation("员工退出")
    public Result<String> logout() {
        return Result.success();
    }

}

启动服务:访问http://localhost:8080/doc.html

在这里插入图片描述

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹

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

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

相关文章

SRC | CORS跨资源共享漏洞

CORS跨资源共享 跨源资源共享 (CORS) 是一种浏览器机制&#xff0c;允许网页使用来自其他页面或域的资产和数据。 大多数站点需要使用资源和图像来运行它们的脚本。这些嵌入式资产存在安全风险&#xff0c;因为这些资产可能包含病毒或允许服务器访问黑客。 CORS响应头 CORS通…

C-DS二叉树_另一棵树的子树

Description 给你两棵二叉树tree1和tree2,检验tree1中是否包含和tree2具有相同结构和结点值的子树。如果存在,输出true;否则,输出false。 Input 第一行输入t,表示有t个测试样例。 第二行首先输入n1,接着输入n1个整数,表示二叉树tree1。 第三行首先输入n2,接着输入n…

Keras人工智能神经网络 Classifier 分类 神经网络搭建

前期我们分享tensorflow以及pytorch时&#xff0c;分享过tensorflow以及pytorch的分类神经网络的搭建步骤&#xff0c;在哪里我们使用的训练集是mnist&#xff0c;同样Keras分类神经网络的搭建&#xff0c;我们同样使用mnist数据集来进行分类神经网络的搭建&#xff08;有关mni…

【NI-DAQmx入门】NI-DAQmx之Python

NI-DAQmx Python GitHub资源&#xff1a; NI-DAQmx Python 文档说明&#xff1a;NI-DAQmx Python Documentation — NI-DAQmx Python API 0.9 documentation nidaqmx支持 CPython 3.7和 PyPy3&#xff0c;需要注意的是多支持USB DAQ和PCI DAQ&#xff0c;cDAQ需要指定…

改进的yolov5

The networkstructure of these models is constant, but the modules and con-volution kernels are scaled, which alters the complexity and sizeof each model.&#xff08;这些模型的网络结构是恒定的&#xff0c;但模块和卷积核被缩放&#xff0c;这改变了每个模型的复杂…

自动驾驶算法(五):基于遗传算法的路径规划(上)

目录 1 遗传算法介绍 2 遗传算法代码详解--绘制地图与种群初始化代码讲解 1 遗传算法介绍 模拟生物进化过程&#xff0c;物竞天择&#xff0c;适者生存。 我们先为栅格地图进行编码&#xff1a;从起点0出发到终点24这个栅格。我们首先有一条路径&#xff08;0&#xff0c;6&a…

最近面了12个人,发现连这种基础题都答不上来.....

一般面试我都会问一两道很基础的题目&#xff0c;来考察候选人的“地基”是否扎实&#xff0c;有些是操作系统层面的&#xff0c;有些是 python语言方面的&#xff0c;还有些… 深耕IT行业多年&#xff0c;我们发现&#xff0c;对于一个程序员而言&#xff0c;能去到一线互联网…

golang工程中间件——redis常用结构及应用(string, hash, list)

Redis 命令中心 【golang工程中间件——redisxxxxx】这些篇文章专门以应用为主&#xff0c;原理性的后续博主复习到的时候再详细阐述 string结构以及应用 字符数组&#xff0c;redis字符串是二进制安全字符串&#xff0c;可以存储图片等二进制数据&#xff0c;同时也可以存…

ns3入门基础教程

ns3入门基础教程 文章目录 ns3入门基础教程ns环境配置测试ns3环境ns3简单案例 ns环境配置 官方网站&#xff1a;https://www.nsnam.org/releases/ 代码仓库&#xff1a;https://gitlab.com/nsnam/ns-3-dev 如果安装遇到问题&#xff0c;可以参考以下博文&#xff1a; https://…

19、Flink 的Table API 和 SQL 中的内置函数及示例(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

吴恩达《机器学习》6-4->6-7:代价函数、简化代价函数与梯度下降、高级优化、多元分类:一对多

一、代价函数 逻辑回归的代价函数是用来度量模型预测与实际结果之间的差异的。与线性回归使用均方误差不同&#xff0c;逻辑回归使用的代价函数在数学上更为复杂。为了理解逻辑回归的代价函数&#xff0c;首先要明白逻辑回归的假设函数&#xff1a; ℎ&#x1d703;(&#x1…

【高德地图API】JS高德地图API实现多边形绘画,高德获取多边形提交数据

目录 前言效果实现引入js 在项目中使用效果图引入htmlCSS具体实现JS调用说明添加的时候修改的时候判断是否在范围内 java绘画和判断是否在范围内pom.xml依赖引入import引入实现 前言 高德地图官方API&#xff1a;https://lbs.amap.com/demo/javascript-api/example/overlayers…

计算机编程软件编程基础知识,中文编程工具下载分享

计算机编程软件编程基础知识&#xff0c;中文编程工具下载分享 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件&#xff0c;象如图这个实例…

LangChain+LLM实战---用AI(大模型)重构推荐系统

原文&#xff1a;Reimagining the Recommendation Engine AI助手的崛起 人工智能正在改变我们与在线应用程序互动的方式。目前&#xff0c;我们使用搜索引擎、新闻源和精心设计的菜单来导航&#xff0c;这些菜单引导我们找到所需的信息或服务。然而&#xff0c;我相信目前人工…

【IK分词器安装】

安装IK分词器&#xff1a; 下载链接&#xff08;如果es版本不同可以修改下版本号&#xff09;&#xff1a;https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip 通常下载是比较慢的&#xff1a;有需要可以从…

OFDM同步--载波频率偏差CFO

参考书籍&#xff1a;《MIMO-OFDM无线通信技术及MATLAB实现》 实验图基本都截取自该本书 一、什么是CFO OFDM解调是采用同步检波的方式&#xff0c;需要在接收机使用与发射机相同的载波信号进行向下变换恢复出基带信号。但在实际使用中无法获得完全相同的载波信号&#xff0c;…

Mybatis-Plus自动填充功能配置和使用 [MyBatis-Plus系列] - 第494篇

历史文章(文章累计490+) 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《

测试开发之自动化篇-有效测试数据管理

我们知道在测试设计时&#xff0c;对于一些操作相似的场景&#xff0c;可以采用步骤同数据相分离的方法来描述。这样的用例内容精炼、逻辑清晰&#xff0c;也利于未来自动化测试脚本的复用。 数据驱动测试是一种流行的软件测试方法&#xff0c;用于归纳性、结构化和集中化地描…

Linux开发板移植FTP服务器和OpenSSH时发现的问题

先上结论&#xff1a;如果在linux开发板上移植了OpenSSH&#xff0c;那么不仅可以远程登录Linux开发板&#xff0c;还可以用FileZilla在windows和Linux开发板之间传输文件&#xff0c;这时候就不需要移植vsftpd(移植vsftpd后windows可以用FileZilla跟Linux开发板传输文件)了&am…

【Unity ShaderGraph】| 快速制作一个 表面水纹叠加效果

前言 【Unity ShaderGraph】| 快速制作一个 表面水纹叠加效果一、效果展示二、表面水纹叠加效果三、应用实例 前言 本文将使用ShaderGraph制作一个表面水纹叠加效果&#xff0c;可以直接拿到项目中使用。对ShaderGraph还不了解的小伙伴可以参考这篇文章&#xff1a;【Unity Sh…