springboot项目注册接口

基于eclipse工具上的

一、Controller层

package cn.kooun.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.kooun.pojo.params.UserLoginParam;
import cn.kooun.pojo.params.UserRegisterParam;
import cn.kooun.service.UserService;

/**
 *  用户Controller
 * @author HuangJingNa
 * @date 2019年12月20日 上午9:21:38
 *
 */
@RestController //@Controller+@Responsebody
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserService userService;
    
    /**
     *   用户注册
     * @author HuangJingNa
     * @date 2019年12月20日 上午9:23:15
     *
     * @return
     * 客户端请求的数据一般封装在自定义的pojo类中(XxxParam)
     */
    /* 业务需求
     * 1.校验数据
     *  校验账号(非空、长度、唯一性)
     *  校验密码(非空、长度、格式)
     * 2.数据库操作(插入操作)
     * 3.将数据响应给客户端/页面
     */
    @GetMapping("register")
    public Object register(UserRegisterParam userRegisterParam) {
        return userService.register(userRegisterParam);
    }
}

注册接口参数封装类UserRegisterParam

package cn.kooun.pojo.params;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 *  注册接口参数封装
 * @author HuangJingNa
 * @date 2019年12月20日 上午9:28:47
 *
 */
@Setter
@Getter
@ToString
public class UserRegisterParam {
    /**账号名称*/
    private String username;
    /**账号密码*/   
    private String password;
}

二、service层

业务层:主要分为三步走:
1. 数据校验
2. 数据库的相关操作
3. 返回响应结果给客户端/页面

一般多次创建实例的,可以使用工厂模式
加密:使用Md5(较易破解),可以加入“盐”混合加密,越复杂越难破解
一般的标准校验(非空、长度、格式的判断)放在数据校验工具类中
操作数据库的代码较多,一般封装成一个方法(选中按alt+shift+M可以生成方法)

package cn.kooun.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cn.kooun.common.CheckUtils;
import cn.kooun.common.Md5Utils;
import cn.kooun.common.UuidUtils;
import cn.kooun.common.result.Result;
import cn.kooun.common.result.ResultUtils;
import cn.kooun.mapper.UserMapper;
import cn.kooun.pojo.params.UserLoginParam;
import cn.kooun.pojo.params.UserRegisterParam;
import cn.kooun.pojo.table.User;

/**
 *   用户service
 * @author HuangJingNa
 * @date 2019年12月20日 上午9:29:25
 *
 */
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    /**
     *  注册业务
     * @author HuangJingNa
     * @date 2019年12月20日 上午9:30:21
     *
     * @param userRegisterParam
     * @return
     */
    public Object register(UserRegisterParam userRegisterParam) {
        //数据校验
        Object result = this.checkRegister(userRegisterParam);
        if(result != null) {
            return result;
        }
        //插入数据库
        //由于字段可能会发生变化,插入需要动态生成(使mapper类继承通用mapper)
        this.saveRegister(userRegisterParam);
        //返回友好提示,注册成功(使用工具类)
        return ResultUtils.success("注册成功~", Result.JUMP_LOGIN);
    }
    /**
     *  将账号密码插入数据库中
     * @author HuangJingNa
     * @date 2019年12月20日 下午3:33:48
     *
     * @param userRegisterParam
     */
    private void saveRegister(UserRegisterParam userRegisterParam) {
        User user = new User();
        user.setId(UuidUtils.getUuid());
        user.setUsername(userRegisterParam.getUsername());
        user.setPassword(Md5Utils.getPassword(
                userRegisterParam.getPassword(),
                userRegisterParam.getUsername()));
        user.setNickName("kooun_" + user.getId());
        user.setType(1);
        userMapper.insertSelective(user);
    }
    /**
     *  注册业务数据校验
     * @author HuangJingNa
     * @date 2019年12月20日 下午2:43:37
     *
     * @param userRegisterParam
     * @return
     */
    private Object checkRegister(UserRegisterParam userRegisterParam) {
        String username = userRegisterParam.getUsername();
        String password = userRegisterParam.getPassword();
        
        //校验账号
        if(!CheckUtils.checkUsername(username)) {
            return ResultUtils.error("账号不合法,请输入6-16个字母和数字的组合");
        }
            //校验账号是否存在
        if(userMapper.isExistUserNameByUsername(username)) {
            return ResultUtils.error("账号已被占用了~");
        }
        //校验密码
        if(!CheckUtils.checkPassword(password)) {
            return ResultUtils.error("密码不合法,请输入6-20个字母和数字的组合");
        }
        return null;
    }
}

数据校验工具类CheckUtils

package cn.kooun.common;

import org.springframework.util.StringUtils;

/**
 *  数据校验工具
 * @author HuangJingNa
 * @date 2019年12月20日 下午2:49:58
 *
 */
public class CheckUtils {
    /**
     *  校验账户数据
     * @author HuangJingNa
     * @param username 
     * @date 2019年12月20日 下午2:50:11
     *
     * @return
     */
    public static boolean checkUsername(String username) {
        boolean flag = true;
        if(StringUtils.isEmpty(username)) {
            return !flag;
        }
        if(!username.matches("[0-9a-zA-Z]{6,16}")) {
            return !flag;
        }
        return flag;
    }
    /**
     *  校验密码数据
     * @author HuangJingNa
     * @date 2019年12月20日 下午3:28:00
     *
     * @param password
     * @return
     */
    public static boolean checkPassword(String password) {
        boolean flag = true;
        if(StringUtils.isEmpty(password)) {
            return !flag;
        }
        if(!password.matches("[0-9a-zA-Z]{6,20}")) {
            return !flag;
        }
        return flag;
    }

}

响应消息封装工具类
响应返回的数据Result

package cn.kooun.common.result;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 *  通用响应数据模型
 * @author HuangJingNa
 * @date 2019年12月20日 下午2:57:50
 *
 */
@Setter
@Getter
@ToString
public class Result {
    /*
     * {
     *  status: "success/error",
     *  message: "友好提示消息",
     *  result: "业务数据",
     *  jump: "跳转标记=> index(首页),login(登录页)"
     * }
     */
    /**成功状态*/
    public static final String STATUS_SUCCESS = "success";
    /**错误状态*/
    public static final String STATUS_ERROR = "error";
    /**登录页跳转*/
    public static final String JUMP_LOGIN = "login";
    /**首页跳转*/
    public static final String JUMP_INDEX = "index";
    
    
    /**响应状态*/
    private String status;
    /**响应消息*/
    private String message;
    /**响应数据*/
    private Object result;
    /**跳转标识*/
    private String jump;
}

工具类

package cn.kooun.common.result;

import cn.kooun.common.factory.ErrorResultFactory;
import cn.kooun.common.factory.SuccessResultFactory;

/**
 *  业务响应标准类
 * @author HuangJingNa
 * @date 2019年12月20日 下午2:54:48
 *
 */
public class ResultUtils {
    /**
     *  业务成功响应
     * @author HuangJingNa
     * @date 2019年12月20日 下午2:56:45
     *
     * @param string
     * @return
     */
    public static Object success(String message) {
        SuccessResult successResult = SuccessResultFactory.getInstance();
        successResult.setMessage(message);
        return successResult;
    }
    /**
     *  业务成功响应
     * @author HuangJingNa
     * @date 2019年12月20日 下午2:56:45
     *
     * @param string
     * @return
     */
    public static Object success(String message, String jump) {
        SuccessResult successResult = SuccessResultFactory.getInstance();
        successResult.setMessage(message);
        successResult.setJump(jump);
        return successResult;
    }
    /**
     *  业务错误响应
     * @author HuangJingNa
     * @date 2019年12月20日 下午3:30:09
     *
     * @param string
     * @return
     */
    public static Object error(String message) {
        ErrorResult errorResult = ErrorResultFactory.getInstance();
        errorResult.setMessage(message);
        return errorResult;
    }
    /**
     *  业务成功响应
     * @author HuangJingNa
     * @date 2019年12月20日 下午7:57:51
     *
     * @param string
     * @param jumpIndex
     * @param ticket
     * @return
     */
    public static Object success(
            String message,
            String jump, 
            Object result) {
        SuccessResult successResult = SuccessResultFactory.getInstance();
        successResult.setMessage(message);
        successResult.setJump(jump);
        successResult.setResult(result);
        return successResult;
    }
}

成功数据封装

package cn.kooun.common.result;

/**
 *  成功业务封装数据
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:01:58
 *
 */
public class SuccessResult extends Result{
    {
        this.setStatus(Result.STATUS_SUCCESS);
    }
}

错误数据封装

package cn.kooun.common.result;

/**
 *  错误业务封装数据
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:01:58
 *
 */
public class ErrorResult extends Result{
    {
        this.setStatus(Result.STATUS_ERROR);
    }
}

由于要多次创建对象,则使用工厂模式
抽象工厂

package cn.kooun.common.factory;

/**
 *  响应结果抽象工厂
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:11:37
 *
 */
public interface Factory<T> {
    /**
     *   创建具体实例
     * @author HuangJingNa
     * @date 2019年12月20日 下午3:12:50
     *
     * @return
     */
    T newInstance();
}

成功响应实例工厂

package cn.kooun.common.factory;

import cn.kooun.common.result.SuccessResult;

/**
 *  成功响应数据工厂
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:31:15
 *
 */
public class SuccessResultFactory implements Factory<SuccessResult> {
    //懒汉式
    private static SuccessResultFactory successResultFactory;
    static{
        if(successResultFactory == null) {
            successResultFactory = new SuccessResultFactory();
        }
    }
    
    /**
     *  创建具体实例
     */
    public SuccessResult newInstance() {
        return new SuccessResult();
    }

    /**
     *  创建具体实例
     */
    public static SuccessResult getInstance() {
        return new SuccessResultFactory().newInstance();
    }
}

失败响应实例工厂

package cn.kooun.common.factory;

import cn.kooun.common.result.ErrorResult;

/**
 *  错误响应数据工厂
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:31:07
 *
 */
public class ErrorResultFactory implements Factory<ErrorResult> {
    private static ErrorResultFactory errorResultFactory;
    static{
        if(errorResultFactory == null) {
            errorResultFactory = new ErrorResultFactory();
        }
    }
    
    /**
     *  创建具体实例
     */
    public ErrorResult newInstance() {
        return new ErrorResult();
    }

    /**
     *  创建具体实例
     */
    public static ErrorResult getInstance() {
        return new ErrorResultFactory().newInstance();
    }
}

三、使用逆向工程生成pojo类和mapper接口及mapper.xml文件

逆向工程的生成:https://www.jianshu.com/p/c61f0bf1efe0
数据库创建表通常都有的字段封装到一个基础表类中(BaseTable),要实现序列化,便于客户端使用json数据(要求实现序列化以及拥有序列化id)响应

package cn.kooun.pojo.table.base;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 *  基础表
 *  需要实现序列化,给与一个序列化id
 * @author HuangJingNa
 * @date 2019年12月20日 下午2:30:37
 *
 */
@Setter
@Getter
@ToString
public class BaseTable implements Serializable{
    
    //由于createTime和updateTime每次创建对象的时候需要赋值
    //可以使用构造代码块,避免每次创建对象时都需要set
    {
        this.setCreateTime(new Date());
        this.setUpdateTime(new Date());
    }

    private static final long serialVersionUID = 8533571383425561865L;
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY,generator="Mysql")
    private String id;
    
    //@Column(name = "create_time")//告诉通用mapper此变量对应表的字段名
    //这里开启了驼峰命名,可以省略以上步骤
    private Date createTime;
    
    private Date updateTime;
}

pojo类:User.java

package cn.kooun.pojo.table;

import javax.persistence.Table;

import cn.kooun.pojo.table.base.BaseTable;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 *  用户表
 * @author HuangJingNa
 * @date 2019年12月20日 下午2:32:09
 *  1.通过lombok日志包可以通过注解动态生成get&set方法,但是需要注明是哪一张表,方便映射
 *  2.开启驼峰命名,可以在类和数据库中将两个单词通过_连接,改为小驼峰命名,
 *      同时可以省略注解@Column(name = "create_time")
 *  3.主键需要注明,以及自动增长
 */
@Setter
@Getter
@ToString
//@Data  //@Setter+@Getter+@ToString等的集合体
@Table(name = "u_user")
public class User extends BaseTable{
    private static final long serialVersionUID = -2649200110993098831L;
    /**账号名称*/
    private String username;
    /**账号密码*/
    private String password;
    /**账号类型*/
    private Integer type;
    /**账号昵称*/
    private String nickName;

}

mapper接口:UserMapper.java

package cn.kooun.mapper;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import cn.kooun.pojo.table.User;
import tk.mybatis.mapper.common.Mapper;
/**
 *  用户mapper
 *  1.需要继承通过Mapper的泛型类,可以获取其本身拥有的增删改查操作
 * @author HuangJingNa
 * @date 2019年12月20日 下午3:44:22
 *
 */
public interface UserMapper extends Mapper<User>{
    /**
     *   判断该用户是否存在
     * @author HuangJingNa
     * @date 2019年12月20日 下午3:44:02
     *
     * @param username
     * @return
     */
    @Select("SELECT " + 
            "   CASE COUNT(u.id) WHEN 0 THEN 0 ELSE 1 END" + 
            " FROM u_user u" + 
            " WHERE u.username = #{username}")
    boolean isExistUserNameByUsername(@Param("username")String username);
}

mapper.xml文件:UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.kooun.mapper.UserMapper">
  
</mapper>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容