SSM 框架 个人使用习惯 详细
SpringMVC主要是controller、service、dao(mapper)层交互
controller:处理数据请求的接口
service:处理请求的数据
dao(mapper):对数据进行持久化
下面我将对controller和service.impl进行讲解
1.controller层 (代码讲解):
对于需要返回的数据:比如登录、获取用户信息等操作都是直接返回数据的
对于不需要返回数据:比如进行注册、注销、修改密码等操作,这些只需要知道是否执行成功即可,不需要返回的数据,需要对其结果进行布尔值判断,如果成功则返回Result.ok,失败则返回Result.fail的结果。
你会发现我使用的是@RequiredArgsConstructor,
而不是@Autowired,其实两种方式可以提供依赖注入,但是我个人习惯于使用@RequiredArgsConstructor
的方式进行依赖注入。
@RequiredArgsConstructor
通过构造函数为不可变字段提供依赖注入,适用于需要final字段的情况。@Autowired
则提供更灵活的注入方式,可以用于字段、构造函数或方法,不需要字段是final。
具体详细的过程如下所示:
@Tag(name = "用户接口管理")
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@Operation(summary = "用户密码验证登录")@PostMapping("/login")public Result<String> login(@RequestBody UserLoginForm userLoginForm){return Result.ok(userService.login(userLoginForm));}@Operation(summary = "用户短信验证登录")@PostMapping("/loginBySms")public Result<String> loginBySms(@RequestBody UserLoginSmsForm userLoginSmsForm){return Result.ok(userService.loginBySms(userLoginSmsForm));}@Operation(summary = "用户注册")@PostMapping("/register")public Result<Void> register(@RequestBody UserRegisterForm userRegisterForm){if(userService.register(userRegisterForm)){return Result.fail();}return Result.ok();}@Operation(summary = "用户修改密码")@PutMapping("/modifyPassword")public Result<Void> modifyPassword(@RequestBody UserModifyPasswordForm userModifyPasswordForm){if(!userService.modifyPassword(userModifyPasswordForm)){return Result.fail();}return Result.ok();}@Operation(summary = "用户注销")@DeleteMapping("/logout")public Result<Void> logout(){if(!userService.logout()){return Result.fail();}return Result.ok();}@Operation(summary = "获取用户信息")@GetMapping("/info")public Result<UserInfoVo> info(){return Result.ok(userService.info());}}
2.service层:
service层一般的写法是先写service的接口类,再写对应的实现类进行实现,如下所示:
service接口:
public interface IUserService extends IService<User> {String login(UserLoginForm userLoginForm);String loginBySms(UserLoginSmsForm userLoginSmsForm);boolean register(UserRegisterForm userRegisterForm);UserInfoVo info();boolean modifyPassword(UserModifyPasswordForm userModifyPasswordForm);boolean logout();
}
service接口实现类(service.impl)中的代码:
观察下面的代码:
对于不正确的数据,我会选择抛出自定义异常BusinessRuntimeException进行处理,
对于需要返回布尔类型直接对返回的结果行rows==1进行判断即可,
对于注销用户操作,不要直接删除数据中的数据,需要进行逻辑删除,而不是直接真正的删除数据库中的数据
对于用户的密码相关操作,因为这里的密码是用MD5进行加密的,所以对于密码的校验操作需要考虑MD5的转换
对于用户登录操作,需要返回token值,这样便于操作请求时进行校验操作
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {private final UserMapper userMapper;private final RedisTemplate<String,Object> redisTemplate;@Overridepublic String login(UserLoginForm userLoginForm) {User user = selectUserByName(userLoginForm.getUsername());//用户不存在if(user == null){throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_ERROR);}//密码不正确if(!user.getPassword().equals(MD5.encrypt(userLoginForm.getPassword()))){throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);}//账号已经被注销了if(user.getIsDelete()==1){throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_STOP);}Map<String,Object> claims = new HashMap<>();claims.put("id",user.getId());claims.put("username",user.getUsername());claims.put("profile",user.getProfile());//生成tokenString token = JwtUtils.generateJwt(claims);redisTemplate.opsForValue().set(RedisConstant.USER_CHECK_TOKEN,token,2, TimeUnit.HOURS);return token;}public User selectUserByName(String username){return userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,username));}@Overridepublic String loginBySms(UserLoginSmsForm userLoginSmsForm) {User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userLoginSmsForm.getPhone()));//用户不存在if(user == null){throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_ERROR);}//账号已经被注销了if(user.getIsDelete()==1){throw new BusinessRuntimeException(ResultCodeEnum.ACCOUNT_STOP);}//未输入验证码if(StringUtils.isEmpty(userLoginSmsForm.getVerifyCode())){throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_EMPTY);}String verifyCode = (String) redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_SMS_CODE);//验证码过期或未发送验证码if(StringUtils.isEmpty(verifyCode)){throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_EXPIRED);}//验证码错误if(!verifyCode.equals(userLoginSmsForm.getVerifyCode())){throw new BusinessRuntimeException(ResultCodeEnum.VALIDATECODE_ERROR);}Map<String,Object> claims = new HashMap<>();claims.put("id",user.getId());claims.put("username",user.getUsername());claims.put("profile",user.getProfile());//生成tokenString token = JwtUtils.generateJwt(claims);redisTemplate.opsForValue().set(RedisConstant.USER_CHECK_TOKEN,token,2, TimeUnit.HOURS);return token;}@Overridepublic boolean register(UserRegisterForm userRegisterForm) {String username = userRegisterForm.getUsername();String password = userRegisterForm.getPassword();//输入的密码为空if(StringUtils.isEmpty(password) || StringUtils.isEmpty(userRegisterForm.getPasswordAgain())){throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);}//两次输入的密码不一致if(!password.equals(userRegisterForm.getPasswordAgain())){throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);}//注册的用户名不存在if(selectUserByName(username) == null){User user = new User();user.setGender(0);user.setRole(0);user.setUsername(username);user.setPassword(MD5.encrypt(password));user.setIsDelete(0);user.setCreateTime(new Date());user.setUpdateTime(new Date());int rows = userMapper.insert(user);return rows == 1;}return false;}@Overridepublic UserInfoVo info() {Long userId = UserHolder.getUserId();User user = userMapper.selectById(userId);return BeanUtil.copyProperties(user, UserInfoVo.class);}@Overridepublic boolean modifyPassword(UserModifyPasswordForm userModifyPasswordForm) {Long userId = UserHolder.getUserId();User user = userMapper.selectById(userId);String password = userModifyPasswordForm.getPassword();String newPassword = userModifyPasswordForm.getNewPassword();//校验密码if(!user.getPassword().equals(MD5.encrypt(password))){throw new BusinessRuntimeException(ResultCodeEnum.PASSWORD_ERROR);}user.setPassword(MD5.encrypt(newPassword));int rows = userMapper.updateById(user);return rows == 1;}@Overridepublic boolean logout() {Long userId = UserHolder.getUserId();User user = userMapper.selectById(userId);//设置逻辑删除状态user.setIsDelete(1);user.setUpdateTime(new Date());UserHolder.removeUserId();return true;}
}
3.dao(mapper)层:
如果你学过Mybatis-plus,你就会发现原来,我使用的是Mybatis-plus进行操作,非常便利
public interface UserMapper extends BaseMapper<User> {
}
相关文章:
SSM 框架 个人使用习惯 详细
SpringMVC主要是controller、service、dao(mapper)层交互 controller:处理数据请求的接口 service:处理请求的数据 dao(mapper):对数据进行持久化 下面我将对controller和service.impl进行讲…...

[羊城杯 2020]Blackcat1
知识点:数组加密绕过 进入页面熟悉的web三部曲(url地址,web源代码,web目录扫描) url地址没有什么东西去看看源代码. 这有一个mp3文件点一下看看. 在最后面发现了 PHP源码. if(empty($_POST[Black-Cat-Sheriff]) || em…...

腾讯云Ubuntu系统安装宝塔,配置Java环境,运行spring boot项目
致谢 本次学习宝塔部署spring boot项目,参考如下资料 https://www.cnblogs.com/daen/p/15997872.html 系统安装宝塔 直接用的腾讯云云服务器面板上的登录,你可以换成 xshell 进入宝塔官网: https://www.bt.cn/new/download.html 我们采…...

双亲委派机制知识点
类加载器 双亲委派模型 为什么采用双亲委派模型 打破双亲委派机制的场景 Tomcat 打破双亲委派机制:目的是可以加载不同版本的jar包 实现类隔离:在Tomcat中,每个Web应用使用独立的类加载器加载类文件,这样做的好处在于,当在同一T…...

vue part 11
vuex的模块化与namespace 115_尚硅谷Vue技术_vuex模块化namespace_1_哔哩哔哩_bilibili 116_尚硅谷Vue技术_vuex模块化namespace_2_哔哩哔哩_bilibili vue-router路由 很常见的很重要的应用:Ajax请求,将响应的数据替换掉原先的代码从而实现不跳转页面…...

【QT】常用类
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:QT 目录 👉🏻QMediaPlayer👉🏻QMediaPlaylistsetPlaybackMode 👉🏻QDir👉…...

从index_put出发全面学习cuda和pytorch技术
一 前言 深感目前对于cuda和pytorch所涉及知识的广度和深度,但一时又不知道该如何去学习,经过多日的考虑,还是决定管中窥豹,从一个算子出发,抽丝剥茧,慢慢学习,把学习中碰到的问题都记录下来,希望可以坚持下去。 二 函数功能描述 【torch算子】torch.index_put和tor…...

浅谈住房城乡建设部科技创新平台布局重点方向
最近住房建设部组织开展住房城乡建设部科技创新平台(以下简称部科技创新平台)申报工作。详细内容见住房城乡建设部科技创新平台开始申报了 (qq.com)。在这里有4大方向共15个课题。内容见下图: 虽然我是做技术的,但是如何体现创新还…...
调用 write()函数后,如何知道数据是否已经写入磁盘?
在 Linux 中调用 write() 函数后,可以通过以下几种方式来确定数据是否已经写入磁盘: 一、使用同步函数 1. fsync() 函数: - 这个函数会强制将与文件描述符相关的所有修改过的内核缓冲区写入磁盘,并等待直到磁盘 I/O 操作完…...

策略路由与路由策略的区别
🐣个人主页 可惜已不在 🐤这篇在这个专栏 华为_可惜已不在的博客-CSDN博客 🐥有用的话就留下一个三连吧😼 目录 一、主体不同 二、方式不同 三、规则不同 四、定义和基本概念 一、主体不同 1、路由策略:是为了改…...
从底层原理上理解ClickHouse 中的稀疏索引
稀疏索引(Sparse Indexes)是 ClickHouse 中一个重要的加速查询机制。与传统数据库使用的 B-Tree 或哈希索引不同,ClickHouse 的稀疏索引并不是为每一行数据构建索引,而是为数据存储的块或部分数据生成索引。这种索引的核心思想是通…...
xtu oj 锐角三角形
锐角三角形 题目描述 n条边,任选3条边,能组成多少个锐角三角形(选的边不同就认为是不同的三角形)? 输入 第一个是一个整数T(1≤T≤1000),表示样例的个数。 每个样例占2行,第一行是一…...

MATLAB系列04:循环结构
MATLAB系列04:循环结构 4. 循环结构4.1 while循环4.2 for循环4.2.1 运算的细节4.2.2 break语句和continue语句4.2.3 嵌套循环 4.3 逻辑数组和向量化4.3.1 逻辑数组的重要性4.3.2 用 if/else 结构和逻辑数组创建等式 4.4 总结 4. 循环结构 循环(loop)是一种 MATLAB …...

虹科方案 | 精准零部件测试!多路汽车开关按键功能检测系统
欢迎关注虹科,为您提供最新资讯! #LIN/CAN总线 #零部件测试 #CAN数据 导读 在汽车制造业中,零部件的安全性、功能性和可靠性是确保车辆整体性能的关键。虹科针对车辆零部件的LIN/CAN总线仿真测试,提出了基于虹科Baby-LIN系列产…...
【加密算法基础——AES CBC模式代码解密实践】
AES 解密实践之代码实现 AES 解密使用python脚本比较灵活,但是一定要保证脚本是调试过的,才能在找到正确的密文,密钥,初始向量的情况下,解出正确的明文。但是对于AES解密,命令行无法处理key截断的问题。 实…...

【ViT+Dis】Deepfake Detection Scheme Based on Vision Transformer and Distillation
文章目录 Deepfake Detection Scheme Based on Vision Transformer and Distillationkey points深伪检测检测算法蒸馏法与教师网络实验训练:参数总结Deepfake Detection Scheme Based on Vision Transformer and Distillation 会议:2021 作者: key points 以往基于CNN结…...

maya-vray渲染蒙版
要用一个叫vrayMulWrapper的材质球,把alpha Conterbution调到-1,勾选matte surface启用蒙版物体。...

计网简简单单复习一下
文章目录 基础体系结构(分层模型)为什么要分层?OSI 七层模型?每一层的作用?TCP/IP 四层模型是什么?每一层的作用是什么?五层体系结构以及对应的协议每一层常见协议有哪些?从输入 URL 到页面展示到底发生了什么?URI和URL的区别;forward和redirect的区别DNS作用是什么?D…...

PyQt5-loading-圆环加载效果
效果预览 代码实现 from PyQt5.QtCore import QSize, pyqtProperty, QTimer, Qt, QThread, pyqtSignal from PyQt5.QtGui import QColor, QPainter from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QVBoxLayout, QLabel, QGridLayoutclass Cir…...

RabbitMQ Spring客户端使用
注解声明式队列和交换机 java自带序列化工具类,将java对象序列化为字节数组,用于网络传输。 jdk序列号存在缺陷,(不安全,占用空间大等) 推荐使用JSON的序列化: springboot扫描包使配置生效&…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...