完整的电商平台后端API开发总结
对于开发一个Web项目来说,无论是电商还是其他品类的项目,注册与登录模块都是必不可少的;注册登录功能也是我们在日常生活中最长接触的,对于这个业务场景的需求与逻辑大概是没有什么需要详细介绍的,市面上常见的邮箱注册、手机注册、独立站账号密码注册,其处理方式基本相同,我们这里使用账号密码注册的方式,实现整个平台的注册/登录功能;
让我们开始!
判断用户名是否存在
实现注册部分的代码,首先想到的就是,我们要对前端所发送过来的请求参数做验证,在有些项目中,会将请求参数的格式验证和合法性验证只写在前端校验,而后端只实现业务逻辑,我认为这是极其危险的编码习惯;当我们的项目放在线上的时候,就会有恶意用户绕过前端验证,直接访问我们的服务器,对线上业务造成破坏,因此前端验证是为了减轻一部分请求直接到达后端,但是相应的验证后端也要去做
那么,首先我们要实现的就是验证用户注册的用户名是否存在;我们首先来看一下用户表的结构及设计:
从图上我们可以看到用户表中常用的字段,我们用户表以用户的Id为主键,但注意:ID并不是自增长的,这与传统的Id设计不同,这里不是自增的原因是:当系统达到一定的体量时,用户数量激增,我们需要去做分布式集群,需要分库分表,这时自增的ID会给分库分表带来极大的困难,因为,出于日后系统优化的考虑,我们这里的数据库主键,不是自增的。
电商接口开发
理清业务逻辑,看完数据库结构,我们着手开始编写业务代码;在整个项目代码的编写和接口的实现我们都遵循自底向上的方式,从数据库开始,实现数据的映射,业务实现,结果推送的流程,对应pojo映射---Service编写---Controller控制的过程。
那么,我们开始啦:首先,我们创建一个UserService接口,在接口中,我们编写我们第一个业务方法:
/**
* 判断用户名是否存在
*/
public boolean queryUsernameIsExist(String username);
我们传入一个userName,返回一个布尔值;有了接口之后,我们去实现这个方法:
我们在service工程中,新建一个Impl的包,在里面新建一个类UserServiceImpl,去实现UserService接口,并实现其中的方法;我们在这个方法中,需要操作User这个实体类,那么我们先把UserMapper引入进来:
@Autowired
public UsersMapper usersMapper;
在方法中,我们使用Example这种使用条件查询的方式去做查询:
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public boolean queryUsernameIsExist(String username) {
Example userExample = new Example(Users.class);
Example.Criteria userCriteria = userExample.createCriteria();
userCriteria.andEqualTo("username",username);
Users result = usersMapper.selectOneByExample(userExample);
return result == null ? false : true;
}
在这个方法的实现中,我们使用了Example这种方式,Example映射一个实体类,获得一个example对象,为这个对象去添加相应的条件,Criteria对应的方法有很多,可以判断等于,大于,相似等各类条件,使用起来很方便,感兴趣的同学可以去阅读他的源码;这个方法返回一个Users对象,我们去判空,若为空,则用户名可用,若false,则用户名存在;
实现了Service之后,我们来编写Controller,我们在api工程中,新建一个Controller类。命名为PassportController,我们为他加上RestController注解,并加上路由地址,在这个Controller中,我们需要操作UserService来进行查询,那么,我们先将UserService注入进来:
@Autowired
private UserService userService;
并定义一个方法,声明方法的路由地址:
@GetMapping("/usernameIsExist")
public IMOOCJSONResult usernameIsExist(@RequestParam String username) {
//判断用户名不能为空
if (StringUtils.isBlank(username)) {
return IMOOCJSONResult.errorMsg("用户名不能为空");
}
//查找注册的用户名是否存在
boolean isExist = userService.queryUsernameIsExist(username);
if (isExist) {
return IMOOCJSONResult.errorMsg("用户名已经存在");
}
// 请求成功,用户名没有重复
return IMOOCJSONResult.ok();
}
在这个方法中,我们在判断username为空的时候使用了一个字符串的工具类,他是Apache提供的,我们需要首先引入他的依赖:
<!-- apache 工具类 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
引入之后,我们便可以操作StringUtils,他提供了一个isBlank的方法,来判断字符串是否为空;
同时我们在方法中,可以看到一个IMOOCJSONResult对象,这是一个结果集对象,因为在代码中,我们需要返回的结果值类型很多,很不确定,并且,我们需要返回自定义的响应码来告诉前端请求成功与否,前端对约定好的各类返回值做统一处理,避免前端出现代码报错,影响用户体验,同时,自定义的结果响应能提高我们定位错误的速度,规范接口;因此我们先定义一个结果返回类:
public class IMOOCJSONResult {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
// 响应业务状态
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
...
}
完整的类代码请大家去看源码,不方便在这里粘贴全部代码,只提供类中的属性供大家参考,大家可以参考对应的实现思路去封装自己的结果集,我们使用这样统一的结果类便可以在返回数据的同时,返回请求状态码给前端,提高接口可读性和稳定性。
接口测试
当我们第一个接口编写完成后,我们使用PostMan进行接口测试,postman是一款开源免费的接口调试工具,可以模拟客户端发出请求,是后端开发必备工具:
我们可以看到,我们的请求是成功的,当然图示中,我请求的是我的生产服务器接口,大家在本机调试的时候URL应该是localhost开头的,我们可以看到请求结果的响应也是我们封装的结果集的响应,有响应码和数据体组成,大家可以认识更换请求数据,测试接口功能的完整性。
用户注册
完成了第一个判断用户名是否存在的接口后,我们着手开始进行用户注册的逻辑编写,首先我们在注册的时候,依然是操作UserMapper,所以数据层是已经准备好的,我们在UserService中,定义第二个创建用户的方法:
/**
* 创建用户
* @param userBO
* @return
*/
public Users createUser(UserBO userBO);
这个方法会接收一个表单数据,数据包中包含密码,用户名,甚至更多的信息,如果我们在后端一个一个的接收,显然是不合理的,当请求参数过多时,我们便将请求参数封装成一个请求的实体类,在这里我们封装一个UserBO:
public class UserBO {
@ApiModelProperty(value = "用户名",name = "username",example ="张三",required =true)
private String username;
@ApiModelProperty(value = "密码",name = "password",example ="123456",required =true)
private String password;
@ApiModelProperty(value = "确认密码",name = "confirmPassword",example ="123456",required =false)
private String confirmPassword;
...
}
get/set方法大家自行生成,方法定义好后,我们去实现类中,实现他:
@Transactional(propagation = Propagation.REQUIRED)
@Override
public Users createUser(UserBO userBO) {
//使用工具类生成唯一id
String userId = sid.nextShort();
Users user = new Users();
user.setId(userId);
user.setUsername(userBO.getUsername());
try {
user.setPassword(MD5Utils.getMD5Str(userBO.getPassword()));
} catch (Exception e) {
e.printStackTrace();
}
//默认用户昵称同用户名
user.setNickname(userBO.getUsername());
//默认头像
user.setFace(USER_FACE);
//默认生日
user.setBirthday(DateUtil.stringToDate("1970-01-01"));
//设置性别(使用枚举操作)默认为:保密
user.setSex(Sex.secret.type);
user.setCreatedTime(new Date());
user.setUpdatedTime(new Date());
usersMapper.insert(user);
return user;
}
我们在这里存储密码时,使用了MD5加密机制,防止数据库资源泄露,导致用户数据泄露,保证数据的安全性,MD5的工具类大家可以在源码中获取,我就不贴在这里了;同时使用的工具类还有日期格式化工具类,同样的,大家在源码中获取;我们在新建用户设置性别时,我们可以使用枚举的形式去定义用户的性别,增强代码的可读性:
/**
* @Desc:性别枚举
*/
public enum Sex {
woman(0,"女"),
man(1,"男"),
secret(2,"保密");
public final Integer type;
public final String value;
Sex(Integer type, String value) {
this.type = type;
this.value = value;
}
}
我们在生成唯一ID的时候,我们也会使用工具类,注入Sid对象,使用org.n3r.idworker中的方法为了使用其他包中的方法,我们需要SpringBoot在启动时,扫描到idworker,我们需要在Application中配置:
相关文章:

完整的电商平台后端API开发总结
对于开发一个Web项目来说,无论是电商还是其他品类的项目,注册与登录模块都是必不可少的;注册登录功能也是我们在日常生活中最长接触的,对于这个业务场景的需求与逻辑大概是没有什么需要详细介绍的,市面上常见的邮箱注册…...

游戏中的随机——“动态平衡概率”算法
前言 众所周知计算机模拟的随机是伪随机,但在结果看来依然和现实中的随机差别不大。 例如掷硬币,连续掷很多很多次之后,总有连续七八十来次同一个面朝上的情况出现,计算机中一般的随机函数也能很好模拟这一点。 但在游戏中&…...
AUTOSAR汽车电子嵌入式编程精讲300篇-基于 FIFO 和优先级序列 CAN 总线系统(续)
目录 4.1.2 理想模型的 FIFO 序列分析 4.2 仅有一个缓冲区的模型的可调度性分析...

C# InformativeDrawings 生成素描画
效果 项目 下载 可执行程序exe下载 源码下载...
关于网络协议的若干问题(一)
1、当网络包到达一个网关的时候,可以通过路由表得到下一个网关的 IP 地址,直接通过 IP 地址找就可以了,为什么还要通过本地的 MAC 地址呢? 答:IP报文端到端的传输过程中,在没有NAT情况下,目的地…...

电脑重做系统---win10
电脑重做系统---win10 前言制作启动U盘材料方法打开网址下载启动盘制作工具参照官方说明进行制作使用U盘重做系统 常用软件官网地址 前言 记得最早学习装电脑还是04年左右,最为一个啥也不知道的大一傻白胖,花了几百大洋在电脑版把了个“电脑组装与维修”…...

HTML基础入门02
目录 1.格式化标签 2.图片标签: img 3.超链接标签: a 4.综合案例: 展示博客2 5.表格标签 5.1基本使用 5.2合并单元格 6.列表标签 1.格式化标签 加粗:strong标签和b标签 倾斜:em标签和i标签 删除线:del标签和s标签 下划线:i…...

【C++】如何使用RapidXML读取和创建XML文件
2023年10月11日,周三下午 目录 RapidXML的官网使用rapidXML读取XML文件中的元素的属性和值此次要读取的XML文件:ReadExample.xml用于读取此XML文件的C代码运行结果使用rapidXML创建XML文件用于创建XML文件的C代码 如果上面的代码无法运行运行结果编辑…...

《UnityShader入门精要》学习3
笛卡尔坐标系(Cartesian Coordinate System) 二维笛卡儿坐标系 一个二维的笛卡儿坐标系包含了两个部分的信息: 一个特殊的位置,即原点,它是整个坐标系的中心。两条过原点的互相垂直的矢量,即x轴和y轴。这…...
使用Python将MP4视频转换为图像
介绍: 在计算机视觉和机器学习领域,我们经常需要处理视频数据。有时候,我们可能需要将视频转换为图像序列,以便进行后续的分析和处理。本文将介绍如何使用Python和OpenCV库将MP4视频文件转换为图像序列。 步骤: 导入…...
【Vue Router 3】入门
简介 Vue Router让SPA(Single-page Application)的构建更加容易。 Vue Router的功能: 嵌套的路由/视图映射模块化的、基于组件的router配置route params, query, wildcards由Vue过渡系统支持的视图过渡效果细粒度(fine-grained…...
SpringMVC中@RequestMapping注解的详细说明
RequestMapping 是Spring MVC中一个用于映射HTTP请求和控制器方法之间关系的注解。它用于定义控制器方法如何响应特定的HTTP请求,包括GET、POST、PUT、DELETE等。以下是RequestMapping注解的详细说明: 基本用法: RequestMapping("/examp…...
Java - 发送 HTTP 请求的及其简单的方法模块 - hutool
目录 一、POST 传递简单的字符串内容 .body(params)二、POST 传递 Json 数据,以表单类型传递 .form(params)二、POST 传递 Json 数据,以表单类型传递 .form(params) 和 .body(params) 方法效果等效的思路四、传统接口带 token 验证的代码模板参考链接 一…...
Nie et al. 2010 提出的不等式定理
这里写自定义目录标题 定理 定理 For any vector a a a and b b b, we have ∥ a ∥ 2 − ∥ a ∥ 2 2 2 ∥ b ∥ 2 ≤ ∥ b ∥ 2 − ∥ b ∥ 2 2 2 ∥ b ∥ 2 \|a\|_{2} - \frac{\|a\|_{2}^{2}}{2\|b\|_{2}} \leq \|b\|_{2} - \frac{\|b\|_{2}^{2}}{2\|b\|_{2}} ∥a∥2−…...
chatGLM2-6B模型LoRA微调数据集实现大模型的分类任务
【TOC】 1.chatglm介绍 ChatGLM 模型是由清华大学开源的、支持中英双语问答的对话语言模型,并针对中文进行了优化。该模型基于 General Language Model(GLM)架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署。 ChatGLM 具备以下特点: 充…...
Elasticsearch6实践
目录 目录 一、需求 二、ES索引设计 三、页面搜索条件 四、ES的分页搜索DSL语句 五、其他 一、需求 公告列表,需要支持以下搜索 1、根据文本输入,模糊搜索公告标题和公告正文。 2、支持公告类型搜索,单选 3、支持根据公告所在省市区搜…...

云原生Kubernetes:K8S集群版本升级(v1.20.6 - v1.20.15)
目录 一、理论 1.K8S集群升级 2.集群概况 3.升级集群 4.验证集群 二、实验 1.升级集群 2.验证集群 三、问题 1.给node1节点打污点报错 一、理论 1.K8S集群升级 (1)概念 搭建K8S集群的方式有很多种,比如二进制,kubeadm…...

毅速丨3D打印随形水路模具日常如何保养
3D打印随形水路的蜿蜒曲折甚至细微水路,使得其容易发生堵塞并难以清洗,一旦堵塞将对生产带来不小的影响。事实上,堵塞的发生是逐步发展的,所以在生产过程中应注意监控,一旦发现冷却效果下降应及时检查。以下是一些防患…...

尚品甄选2023全新SpringBoot+SpringCloud企业级微服务项目
最适合新手入门的SpringBootSpringCloud企业级微服务项目来啦!如果你已经学习了Java基础、SSM框架、SpringBoot、SpringCloud,想找一个项目来实战练习;或者你刚刚入行,需要可以写到简历中的微服务架构项目! 项目采用前…...

204、RabbitMQ 之 使用 topic 类型的 Exchange 实现通配符路由
目录 ★ 使用topic实现通配符路由代码演示topic通配符类型的Exchange代码演示:ConstantUtilConnectionUtilProducerConsumer01执行结果生产者消费者01消费者02 完整代码:ConstantUtilConnectionUtilProducerConsumer01Consumer02pom.xml ★ 使用topic实现通配符路由…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...