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异步爬虫实战:如何避免aiohttp的ServerDisconnectedError(附完整代码)
Python异步爬虫实战:深度解决aiohttp的ServerDisconnectedError问题 最近在帮朋友优化一个电商价格监控项目时,遇到了令人头疼的ServerDisconnectedError。每当爬取量超过5000条商品数据时,程序就会随机崩溃,控制台满是红色错误日…...
Nunchaku FLUX.1-dev效果展示:4步生成惊艳图片案例分享
Nunchaku FLUX.1-dev效果展示:4步生成惊艳图片案例分享 你是否曾经被AI生成图片的漫长等待时间所困扰?传统文生图模型往往需要20步以上的推理才能获得理想效果,而今天我要展示的Nunchaku FLUX.1-dev模型,仅需4步就能生成令人惊艳…...
Java Web 入门学习笔记:Servlet 请求响应与登录功能实战
一、开篇:今日学习核心与目标学习背景:Java Web 入门阶段核心 ——Servlet 与 HTTP 请求响应交互学习目标:掌握 HttpServletRequest/HttpServletResponse 核心用法实现「登录表单提交→Servlet 验证→页面重定向」完整流程解决实操中 404、中…...
springcloud项目如何禁用三方依赖的拦截器
背景: 原始代码中有一个自定义的通用依赖,这个依赖中有很多通用方法和拦截器供整个系统使用。 需求: 禁用其中一个拦截器,保留其他方法和拦截器,过滤器等。 拦截器介绍 原有拦截器,自己封装了一个jdk&#…...
3大突破!零基础用开源表盘工具创作专业级小米手表表盘
3大突破!零基础用开源表盘工具创作专业级小米手表表盘 【免费下载链接】Mi-Create Unofficial watchface creator for Xiaomi wearables ~2021 and above 项目地址: https://gitcode.com/gh_mirrors/mi/Mi-Create 如何突破官方表盘千篇一律的设计限制&#x…...
MouseClick:让重复点击成为过去的智能鼠标自动化工具
MouseClick:让重复点击成为过去的智能鼠标自动化工具 【免费下载链接】MouseClick 🖱️ MouseClick 🖱️ 是一款功能强大的鼠标连点器和管理工具,采用 QT Widget 开发 ,具备跨平台兼容性 。软件界面美观 ,操…...
收藏级|2026大模型全景解析(小白/程序员必看):技术迭代+梯队格局+产业链+落地案例
2026年,全球AI产业正式迈入“寡头固化垂直突围”的成熟发展阶段,大模型技术彻底告别此前的参数竞赛,转向核心能力深耕与商业化落地。对于刚入门大模型的小白、深耕技术的程序员而言,本文将系统梳理国内外顶尖大模型的迭代成果与梯…...
提升 10 倍的学习效率,这款浏览器必装的AI插件为什么火了?
花了3 周时间写了一个浏览器插件,一个月陆陆续续下载量破 1000 啦 安装链接 为什么要做这个项目? 一开始我入门学习 langchain 大模型agent开发,在之前我不懂的问题需要在 google 上搜索非常多的资料 融会贯通以后才能得到答案࿰…...
TDEngine-OSS-3.3.7.5开源版高可用部署实战(单节点快速入门与三副本集群搭建详解)
1. TDEngine开源版入门:为什么选择它? 如果你正在寻找一个高性能、开源的时序数据库,TDEngine绝对值得考虑。这个由涛思数据推出的产品,专门为物联网、工业互联网等场景设计,能够轻松处理海量时间序列数据。我最近在实…...
告别除法器!用BCD8421码在Nexys4 DDR FPGA上高效驱动8位数码管(附完整Vivado工程)
基于BCD8421码的FPGA数码管驱动优化设计与实现 在数字系统设计中,FPGA开发者经常面临如何在有限硬件资源下实现高效数据转换的挑战。传统方法使用除法器进行二进制到十进制转换,不仅消耗大量逻辑资源,还会引入额外的时序延迟。本文将深入探讨…...
