当前位置: 首页 > news >正文

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&#xff08;mapper&#xff09;层交互 controller&#xff1a;处理数据请求的接口 service&#xff1a;处理请求的数据 dao&#xff08;mapper&#xff09;&#xff1a;对数据进行持久化 下面我将对controller和service.impl进行讲…...

[羊城杯 2020]Blackcat1

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

腾讯云Ubuntu系统安装宝塔,配置Java环境,运行spring boot项目

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

双亲委派机制知识点

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

vue part 11

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

【QT】常用类

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;QMediaPlayer&#x1f449;&#x1f3fb;QMediaPlaylistsetPlaybackMode &#x1f449;&#x1f3fb;QDir&#x1f449;…...

从index_put出发全面学习cuda和pytorch技术

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

浅谈住房城乡建设部科技创新平台布局重点方向

最近住房建设部组织开展住房城乡建设部科技创新平台&#xff08;以下简称部科技创新平台&#xff09;申报工作。详细内容见住房城乡建设部科技创新平台开始申报了 (qq.com)。在这里有4大方向共15个课题。内容见下图&#xff1a; 虽然我是做技术的&#xff0c;但是如何体现创新还…...

调用 write()函数后,如何知道数据是否已经写入磁盘?

在 Linux 中调用 write() 函数后&#xff0c;可以通过以下几种方式来确定数据是否已经写入磁盘&#xff1a; 一、使用同步函数 1. fsync() 函数&#xff1a; - 这个函数会强制将与文件描述符相关的所有修改过的内核缓冲区写入磁盘&#xff0c;并等待直到磁盘 I/O 操作完…...

策略路由与路由策略的区别

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏 华为_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 一、主体不同 二、方式不同 三、规则不同 四、定义和基本概念 一、主体不同 1、路由策略&#xff1a;是为了改…...

从底层原理上理解ClickHouse 中的稀疏索引

稀疏索引&#xff08;Sparse Indexes&#xff09;是 ClickHouse 中一个重要的加速查询机制。与传统数据库使用的 B-Tree 或哈希索引不同&#xff0c;ClickHouse 的稀疏索引并不是为每一行数据构建索引&#xff0c;而是为数据存储的块或部分数据生成索引。这种索引的核心思想是通…...

xtu oj 锐角三角形

锐角三角形 题目描述 n条边&#xff0c;任选3条边&#xff0c;能组成多少个锐角三角形&#xff08;选的边不同就认为是不同的三角形&#xff09;&#xff1f; 输入 第一个是一个整数T(1≤T≤1000)&#xff0c;表示样例的个数。 每个样例占2行&#xff0c;第一行是一…...

MATLAB系列04:循环结构

MATLAB系列04&#xff1a;循环结构 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 …...

虹科方案 | 精准零部件测试!多路汽车开关按键功能检测系统

欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #LIN/CAN总线 #零部件测试 #CAN数据 导读 在汽车制造业中&#xff0c;零部件的安全性、功能性和可靠性是确保车辆整体性能的关键。虹科针对车辆零部件的LIN/CAN总线仿真测试&#xff0c;提出了基于虹科Baby-LIN系列产…...

【加密算法基础——AES CBC模式代码解密实践】

AES 解密实践之代码实现 AES 解密使用python脚本比较灵活&#xff0c;但是一定要保证脚本是调试过的&#xff0c;才能在找到正确的密文&#xff0c;密钥&#xff0c;初始向量的情况下&#xff0c;解出正确的明文。但是对于AES解密&#xff0c;命令行无法处理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的材质球&#xff0c;把alpha Conterbution调到-1&#xff0c;勾选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自带序列化工具类&#xff0c;将java对象序列化为字节数组&#xff0c;用于网络传输。 jdk序列号存在缺陷&#xff0c;&#xff08;不安全&#xff0c;占用空间大等&#xff09; 推荐使用JSON的序列化&#xff1a; springboot扫描包使配置生效&…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作&#xff1a; 压缩包下载&#xff1a;http://download.redis.io/releases 1. 上传压缩包&#xff0c;并进入压缩包所在目录&#xff0c;解压到目标…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...