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

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;

    @Override
    public 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());

        //生成token
        String 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));
    }

    @Override
    public 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());

        //生成token
        String token = JwtUtils.generateJwt(claims);
        redisTemplate.opsForValue().set(RedisConstant.USER_CHECK_TOKEN,token,2, TimeUnit.HOURS);

        return token;
    }

    @Override
    public 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;
    }

    @Override
    public UserInfoVo info() {
        Long userId = UserHolder.getUserId();
        User user = userMapper.selectById(userId);
        return BeanUtil.copyProperties(user, UserInfoVo.class);

    }

    @Override
    public 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;
    }

    @Override
    public 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> {
}


http://www.kler.cn/a/308306.html

相关文章:

  • 3D编辑器教程:如何实现3D模型多材质定制效果?
  • 前端请求后端php接口跨域 cors问题
  • 【面试题】发起一次网络请求,当请求>=1s,立马中断
  • 树形dp总结
  • 【专题】计算机网络之网络层
  • Nuxt 版本 2 和 版本 3 的区别
  • vue3 + vite2 vue 打包后router-view空白
  • 用最新方案为数据密集型AI供能:将服务器农场沉入旧金山湾
  • 【YashanDB知识库】数据库获取时间和服务器时间不一致
  • Facebook的虚拟现实功能简介:社交网络的新前沿
  • 腾讯地图SDK Android版开发 11 覆盖物示例 4 线
  • 什么是蜘蛛池?有什么作用
  • 【原创】java+swing+mysql长途客车售票管理系统设计与实现
  • CACTI 0.8.7 迁移并升级到 1.2.7记录
  • 【零散技术】详解Odoo17邮件发送(一)
  • Unity 编辑器设置中文
  • 对称密码中的密钥是如何实现安全配送的?
  • 【数据结构】快速排序详解(递归版本)
  • 初始爬虫7
  • 时间安全精细化管理平台存在未授权访问漏洞
  • 项目管理 | 一文读懂什么是敏捷开发管理
  • Zotero使用(一)PDF文件导入不会自动识别
  • 3C认证---GB 4706.1-2005
  • 【Java EE】冯·诺依曼体系结构及其在 JavaEE 中的应用
  • systemctl控制服务和守护进程
  • Redis——常用数据类型set