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>
原文地址:https://www.cnblogs.com/nadou/p/14000976.html