我们先来实现一个简单的注册功能,因为需要进行数据库的基本操作,而且是前后端分离式开发。所以我们首先要进行数据库的设计,然后根据数据库进行编写服务端API接口,接着来到客户端或移动端,进行登录与注册的界面设计,接收服务端提供的数据并显示在界面上。
本文主要进行后端注册API接口设计。后面会进行前端框架数据交互设计。

一.设计数据库

根据一般登录与注册的需求,数据库的用户表结构如下:
数据库用户表.png

DDD语句如下:

CREATE TABLE `morse_user` (
  `id` bigint(40) NOT NULL COMMENT '主键',
  `user_name` varchar(255) NOT NULL COMMENT '用户姓名',
  `login_name` varchar(255) NOT NULL COMMENT '登录用户名',
  `user_password` varchar(255) NOT NULL COMMENT '登陆密码',
  `job_number` bigint(55) NOT NULL COMMENT '用户工号',
  `position_id` bigint(20) NOT NULL COMMENT '职位id',
  `department_id` bigint(20) NOT NULL COMMENT '部门id',
  `user_phone` varchar(255) NOT NULL COMMENT '手机号码',
  `user_email` varchar(255) NOT NULL COMMENT '邮箱',
  `is_manager` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否为管理者 0==管理者 1==员工',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态,0:正常,1:删除,2封禁',
  `user_description` varchar(255) NOT NULL DEFAULT '' COMMENT '用户描述信息',
  `creater` varchar(255) NOT NULL COMMENT '创建人',
  `creater_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';

二.持久层开发

1.创建用户实体类

package com.jinghang.service.morse.repository.mybatis.pojo;

import java.io.Serializable;
import java.sql.Timestamp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author 
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MorseUserPo implements Serializable {
    /**
     * 主键
     */
    private Long id;

    /**
     * 用户姓名
     */
    private String userName;

    /**
     * 登录用户名
     */
    private String loginName;

    /**
     * 登陆密码
     */
    private String userPassword;

    /**
     * 用户工号
     */
    private Long jobNumber;

    /**
     * 职位id
     */
    private Long positionId;

    /**
     * 部门id
     */
    private Long departmentId;

    /**
     * 手机号码
     */
    private String userPhone;

    /**
     * 邮箱
     */
    private String userEmail;

    /**
     * 是否为管理者 0==管理者 1==员工
     */
    private Integer isManager;

    /**
     * 状态,0:正常,1:删除,2封禁
     */
    private Integer status;

    /**
     * 用户描述信息
     */
    private String userDescription;

    /**
     * 创建人
     */
    private String creater;

    /**
     * 创建时间
     */
    private Timestamp createrTime;

    /**
     * 更新时间
     */
    private Timestamp updateTime;

    private static final long serialVersionUID = 1L;
}

2.创建mapper接口

package com.jinghang.service.morse.repository.mybatis.mapper;

import com.jinghang.service.morse.repository.mybatis.pojo.MorseUserPo;
import com.jinghang.service.morse.repository.mybatis.pojo.MorseUserPoExample;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface MorseUserDao {
    long countByExample(MorseUserPoExample example);

    int deleteByExample(MorseUserPoExample example);

    int deleteByPrimaryKey(Long id);

    int insert(MorseUserPo record);

    int insertSelective(MorseUserPo record);

    int insertUidSelective(MorseUserPo record);

    List<MorseUserPo> selectByExample(MorseUserPoExample example);

    MorseUserPo selectByPrimaryKey(Long id);

    int updateByExampleSelective(@Param("record") MorseUserPo record, @Param("example") MorseUserPoExample example);

    int updateByExample(@Param("record") MorseUserPo record, @Param("example") MorseUserPoExample example);

    int updateByPrimaryKeySelective(MorseUserPo record);

    int updateByPrimaryKey(MorseUserPo record);
}

3.创建mapper映射文件

鉴于篇幅,在此省略。毕竟这个可以自动生成。

三.业务层开发

1.请求实体类

package com.jinghang.service.morse.service.request;


import lombok.Data;

@Data
public class UserInfoRequest {

    /**
     * 用户姓名
     */
    private String userName;

    /**
     * 登录用户名
     */
    private String loginName;

    /**
     * 登陆密码
     */
    private String userPassword;

    /**
     * 用户工号
     */
    private Long jobNumber;

    /**
     * 职位id
     */
    private Long positionId;

    /**
     * 部门id
     */
    private Long departmentId;

    /**
     * 手机号码
     */
    private String userPhone;

    /**
     * 邮箱
     */
    private String userEmail;

    /**
     * 是否为管理者 0==管理者 1==员工
     */
    private Integer isManager;

    /**
     * 创建人
     */
    private String creater;
}

2.service实现

package com.jinghang.service.morse.service.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.jinghang.service.morse.exception.UserNullException;
import com.jinghang.service.morse.repository.mybatis.mapper.MorseUserDao;
import com.jinghang.service.morse.repository.mybatis.pojo.MorseUserPo;
import com.jinghang.service.morse.repository.mybatis.pojo.MorseUserPoExample;
import com.jinghang.service.morse.service.request.UserInfoRequest;
import com.jinghang.service.morse.service.service.MorseUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class MorseUserServiceImpl implements MorseUserService {
    @Autowired
    private MorseUserDao morseUserDao;

    public String userRegister(UserInfoRequest userInfoRequest) throws UserNullException {
        //查询是否有重名的登录名
        MorseUserPoExample morseUserPoExample = new MorseUserPoExample();
        morseUserPoExample.or().andLoginNameEqualTo(userInfoRequest.getLoginName()).andStatusEqualTo(0);
        long sameLoginNameCount = morseUserDao.countByExample(morseUserPoExample);

        if (sameLoginNameCount == 0) {
            MorseUserPo morseUserPo = new MorseUserPo();
            //参数1为终端ID
            //参数2为数据中心ID
            //雪花算法生成用户唯一uid
            Snowflake snowflake = IdUtil.getSnowflake(1, 1);
            long uid = snowflake.nextId();
            morseUserPo.setId(uid);
            morseUserPo.setUserName(userInfoRequest.getUserName());
            morseUserPo.setLoginName(userInfoRequest.getLoginName());
            morseUserPo.setUserPassword(userInfoRequest.getUserPassword());
            morseUserPo.setJobNumber(userInfoRequest.getJobNumber());
            morseUserPo.setPositionId(userInfoRequest.getPositionId());
            morseUserPo.setDepartmentId(userInfoRequest.getDepartmentId());
            morseUserPo.setUserPhone(userInfoRequest.getUserPhone());
            morseUserPo.setUserEmail(userInfoRequest.getUserEmail());
            morseUserPo.setIsManager(userInfoRequest.getIsManager());
            morseUserPo.setCreater(userInfoRequest.getCreater());

            morseUserDao.insertUidSelective(morseUserPo);
            return "注册成功";

        } else {
            return "用户名已被注册";
        }
    }
}

四.创建全局统一响应格式

package com.jinghang.service.morse.tool;


import com.jinghang.service.morse.enums.ResultCodeEnums;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;


@Setter
@Getter
public class ResultObjectModel<T> implements Serializable {
    /**
     * 返回是否成功
     */
    private Boolean success;

    /**
     * 提示信息
     */
    private String message;

    /**
     * 提示信息code
     */
    private int resultCode;

    /**
     * 返回数据内容
     */
    private T data;

    public ResultObjectModel() {
    }

    public ResultObjectModel(Boolean success, String message, int resultCode, T data) {
        this.success = success;
        this.message = message;
        this.resultCode = resultCode;
        this.data = data;
    }

    /**
     * 返回成功
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultObjectModel success(T data) {
        return new ResultObjectModel(true, ResultCodeEnums.SUCCESS.getMsg(), ResultCodeEnums.SUCCESS.getCode(), data);
    }

    /**
     * 自定义返回成功
     *
     * @param message
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultObjectModel success(String message, int resultCode, T data) {
        return new ResultObjectModel(true, message, resultCode, data);
    }


    /**
     * 失败
     *
     * @param message
     * @param resultCode
     * @return
     */
    public static ResultObjectModel fail(String message, int resultCode) {
        return new ResultObjectModel(false, message, resultCode, null);
    }

    /**
     * 自定义失败
     *
     * @param message
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultObjectModel fail(String message, int resultCode, T data) {
        return new ResultObjectModel(false, message, resultCode, data);
    }
}

五.控制器代码编写

package com.jinghang.service.morse.api.controller;


import com.jinghang.service.morse.service.request.UserInfoRequest;
import com.jinghang.service.morse.service.service.MorseUserService;
import com.jinghang.service.morse.tool.ResultObjectModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/morse-api")
@Slf4j
public class TestController {

    @Autowired
    private MorseUserService morseUserService;

    @ResponseBody
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public ResultObjectModel<String> userInfoRegister(@RequestBody UserInfoRequest userInfoRequest) {
        String userInfoRegisterResponse = morseUserService.userRegister(userInfoRequest);

        return ResultObjectModel.success(userInfoRegisterResponse);


    }
}

六.测试

注册成功:
注册demo成功.png

注册失败:
注册demo失败.png

七.思考

我们可以看到,当用户已被注册时,我们的统一返回接口中,还是显示"success:true"。不利于前端判断是否真的成功。
另外,也没有对参数做校验,如果用户瞎填一个手机号或者邮箱,也能成功注册。需要对一些字段做内容或者长度或者格式的校验。
下一章,我们引入全局异常处理和自定义异常处理以及参数校验。来详细讲讲具体做法。

Q.E.D.





莫道君行早,更有早行人。