小试牛刀:开发用户注册服务层接口

本文介绍了如何使用Spring Boot开发用户注册服务。首先分配任务,要求用户提交用户名和密码,后台进行空值校验和用户名唯一性检查,密码加密存储。接着引入Spring安全框架的加密工具。然后自定义异常类,用于封装错误信息。再定义UserRegisterDTO接收前端数据,并设计UserService接口,实现用户注册逻辑,使用构造器注入和密码加密器。最后,通过Mybatis Dynamic SQL模块进行灵活的查询操作。
摘要由CSDN通过智能技术生成

前面我们做了很多开发的铺垫工作,终于到了来开发一个业务功能的时候了,我们就来写一个最简单的用户注册模块吧。

分配任务

先把要开发的任务分配下来,现在我们要开发一个后台的用户注册服务,用户以表单的形式提交post请求,提交的参数包括了用户名、密码。在后台,校验用户名和密码都不能为空,且校验用户名存在则不允许注册,写入用户表时密码要加密存储。

引入依赖

这里我们不再造轮子或者用一些基础加密工具来实现安全的加密逻辑,直接拿来主义,用spring安全框架给我们提供的工具。后续这个安全框架我们也要学习的,现在先用它著名的加密模块帮我们实现密码加密和验证需求。

dependencies {
    ...

    implementation 'org.springframework.security:spring-security-core'
}

自定义异常

因为后台的校验我们是以抛出异常的形式来返回给上层调用的,为此我们自定义一个异常类:

package com.xiaojuan.boot.common.exception;

import ...

@Getter
public class BusinessException extends RuntimeException {
    private String errCode;
    @Nullable
    private Object data;
    public BusinessException(String msg) {
        super(msg);
    }
    public BusinessException(String msg, String errCode) {
        this(msg);
        this.errCode = errCode;
    }
    public BusinessException(String msg, String errCode, Object data) {
        this(msg, errCode);
        this.data = data;
    }
}

在这个异常类中,我们会包装错误信息、错误码以及可能返回的错误数据。注意它是从RuntimeException继承的,在编译阶段不敏感,不受检查,上层调用无需捕获处理,只关心调用就行。

开发用户注册模块

UserRegisterDTO

这里我们将定义一个DTO来接受前端提交的注册表单数据,DTO可以在web层和Service层之间传输,在service层与DAO层之间与model进行相互转换,引入DTO就是为了让Service和DAO之间进行解耦。

package com.xiaojuan.boot.dto;

import ...

@Data
public class UserRegisterDTO {
    private String username;
    private String password;
}

UserService接口

package com.xiaojuan.boot.service;

import ...

public interface UserService {

    void register(UserRegisterDTO userRegisterDTO) throws BusinessException;
    
}

接口实现逻辑:

package com.xiaojuan.boot.service.impl;

import ...

import static com.xiaojuan.boot.dao.generated.mapper.UserDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.*;

@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    private final PasswordEncoder passwordEncoder;

    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
        this.passwordEncoder = new BCryptPasswordEncoder();
    }

    @Override
    public void register(UserRegisterDTO userRegisterDTO) throws BusinessException {
        String username = userRegisterDTO.getUsername();
        String password = userRegisterDTO.getPassword();

        Assert.hasText(username, "用户名不能为空");
        Assert.hasText(password, "密码不能为空");

        // 先查询用户名是否存在
        long userCount = userMapper.count(c -> c.where(UserDynamicSqlSupport.username, isEqualTo(username)));
        if (userCount > 0) {
            throw new BusinessException("用户名已存在");
        }

        // 密码加密
        String encodedPwd = passwordEncoder.encode(password);

        // 新用户入库
        User user = new User();
        user.setUsername(username);
        user.setPassword(encodedPwd);
        Date currDate = new Date();
        user.setCreateTime(currDate);
        user.setUpdateTime(currDate);
        userMapper.insertSelective(user);
    }
}

代码说明

在service实现类中我们注入了UserMapper接口,注意,这里更推荐用构造器注入的方式;同时,我们将密码加密器对象提升为成员变量,在无参构造中进行了初始化。因为我们的用户注册和将来的用户登录方法在处理密码时都要用到它。

register(userRegisterDTO)方法中,只要逻辑校验失败就抛出异常。这里在判断字段不能为空时,我们建议使用spring提供的Assert类。在执行user查询时我们并没有开发新的UserMapper接口方法,这得益于mybatis dynamic sql模块给我们提供的灵活且通用的查询套路实现。

现在我们的开发任务结束了,该到验证逻辑是否ok的时候了,咱下一节再见!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java小卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值