大家好,欢迎来到IT知识分享网。
项目功能- 用户注册功能
1 创建数据表
-- 创建用户信息表 CREATE TABLE `store`.`t_user`( `uid` int NOT NULL AUTO_INCREMENT COMMENT '用户id', `username` varchar(20) NOT NULL UNIQUE COMMENT '用户名', `password` varchar(32) NOT NULL COMMENT '密码', `salt` varchar(36) NULL COMMENT '盐值', `phone` varchar(20) NULL COMMENT '电话号码', `email` varchar(30) NULL COMMENT '电子邮箱', `gender` int NULL COMMENT '性别:0-女;1-男', `avatar` varchar(50) NULL COMMENT '头像', `is_delete` int NULL COMMENT '是否删除:0-未删除;1-已删除', `created_user` varchar(20) NULL COMMENT '创建人', `created_time` datetime NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间', `modified_user` varchar(20) NULL COMMENT '更新人', `modified_time` datetime NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`uid`) )ENGINE=INNODB DEFAULT CHARSET=utf8;
2 创建用户实体类
2-1 创建实体类的基类
将类中公共的属性抽取出来形成一个基类,被所有实体类继承
package com.cy.store.common; import lombok.Data; import java.io.Serializable; import java.util.Date; /* 实体类的基类 */ @Data public class BaseEntity implements Serializable {
// 创建人 private String createdUser; //创建时间 private Date createdTime; //更新人 private String modifiedUser; //更新时间 private Date modifiedTime; //是否删除:0-未删除;1-已删除 private Integer isDelete; }
2-2 创建用户实体类 继承基类
package com.cy.store.entity; import com.cy.store.common.BaseEntity; import lombok.Data; import java.io.Serializable; /* 用户对象实体类 */ @Data public class UserEntity extends BaseEntity implements Serializable {
// 用户id private Integer uid; // 用户名 private String username; // 密码 private String password; // 盐值 private String salt; // 电话号码 private String phone; // 电子邮箱 private String email; // 性别:0-女;1-男 private Integer gender; // 头像 private String avatar; }
3 注册-持久层
3-1 规划需要执行的sql语句
用户注册功能,相当于在做数据库的插入操作。
insert into t_user (username,password,...) values (....);
3-2 设计接口和抽象方法
定义mapper接口。
package com.cy.store.mapper; import com.cy.store.entity.UserEntity; /* 用户持久层mapper接口 */ public interface UserMapper {
/ * 插入用户 * @param userEntity 用户对象 * @return 影响的行数 */ Integer insertUser(UserEntity userEntity); / * 通过用户名查询用户信息 * @param username 用户名称 * @return UserEntity 用户对象 */ UserEntity selectByUserName(String username); }
3-3 编写映射
定义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="com.cy.store.mapper.UserMapper"> <!-- 当数据表中的字段与实体类中不一致时,做映射关系处理 --> <resultMap id="userMap" type="com.cy.store.entity.UserEntity"> <result property="isDelete" column="is_delete"/> <result property="modifiedTime" column="modified_time"/> <result property="modifiedUser" column="modified_user"/> <result property="createdTime" column="created_time"/> <result property="createdUser" column="created_user"/> </resultMap> <!-- 重复使用的sql片段 --> <sql id="userColumn"> uid, username, password, salt, phone, email, gender, avatar, is_delete, created_time, created_user, modified_time, modified_user </sql> <!-- 根据用户名称查询用户信息 --> <select id="selectByUserName" parameterType="string" resultMap="userMap"> select <include refid="userColumn"></include> from Blog where username= #{username} </select> <!-- 插入用户 --> <insert id="insertUser" parameterType="com.cy.store.entity.UserEntity" useGeneratedKeys="true" keyProperty="uid"> insert into t_user (<include refid="userColumn"></include>) values ( #{username},#{password},#{salt},#{phone},#{email},#{gender},#{avatar},#{isDelete},#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime} ) </insert> </mapper>
3-4 单元测试
每一个层都应要写单元测试,对已开发好的功能做自测,确保没有问题后才可以发布到测试环境,移交测试人员进行测试。
4 注册-业务层()
业务功能层是整个系统实现过程中最重要的一层。因为这层不仅需要考虑具体功能的实现过程,还要考虑问题的出现。
- 功能具体实现的逻辑设计
- 实现该功能时有可能出现的问题,也就是异常的规划。
4-1 异常的规划
1 设计业务层的异常机制
分析 业务层的异常首先是属于运行时抛出的异常,所有我们设计的异常都是 RunTimeException的子类,因为异常是有很多的,所以我们应该设计一个异常基类,用于被其他不同业务异常继承。
具体实现如下:
package com.cy.store.common; /* 设计整个系统的异常基类,这个类继承RunTimeException 并重写父类中的构造方法 */ public class ServiceException extends RuntimeException{
public ServiceException() {
super(); } public ServiceException(String message) {
super(message); } public ServiceException(String message, Throwable cause) {
super(message, cause); } public ServiceException(Throwable cause) {
super(cause); } protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); } }
可能出现的异常
- 注册时用户已经存在,被占用异常。
- 数据插入时异常。
package com.cy.store.service.ex; import com.cy.store.common.ServiceException; / * 数据插入异常 */ public class InsertException extends ServiceException {
public InsertException() {
super(); } public InsertException(String message) {
super(message); } public InsertException(String message, Throwable cause) {
super(message, cause); } public InsertException(Throwable cause) {
super(cause); } protected InsertException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); } }
4-2 业务层接口以及实现类设计
- 接口设计
package com.cy.store.service; import com.cy.store.entity.UserEntity; public interface UserService {
// 用户注册功能,这里不需要返回。业务层通过mapper的影响行数做逻辑判断。 void register(UserEntity userEntity); // 用户查询功能 UserEntity queryByName(String username); }
- 实现类设计
package com.cy.store.service.impl; import com.cy.store.entity.UserEntity; import com.cy.store.mapper.UserMapper; import com.cy.store.service.UserService; import com.cy.store.service.ex.InsertException; import com.cy.store.service.ex.UserDuplicatedException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Date; import java.util.InvalidPropertiesFormatException; @Service public class UserServiceImpl implements UserService {
@Autowired private UserMapper userMapper; @Override public void register(UserEntity userEntity) {
// 判断参数是否为空 String username = userEntity.getUsername(); if (username == null || username == "") {
throw new NullPointerException("用户名不能为空"); } // 查询用户是否存在 UserEntity entity = userMapper.selectByUserName(username); if (entity != null) {
throw new UserDuplicatedException("用户已存在"); } // 插入用户信息 userEntity.setIsDelete(0); userEntity.setCreatedUser("system"); userEntity.setCreatedTime(new Date()); userEntity.setModifiedUser("system"); userEntity.setModifiedTime(new Date()); Integer integer = userMapper.insertUser(userEntity); if (integer != 1) {
throw new InsertException("用户插入时出现异常"); } } @Override public UserEntity queryByName(String username) {
if (username == "" || username == null) {
throw new NullPointerException("用户姓名不能为空"); } UserEntity userEntity = userMapper.selectByUserName(username); return userEntity; } }
4-3 单元测试 略
4-4 业务层逻辑补充-密码处理
分析:
- 1、确定密码加密的算法逻辑。
- 2、使用UUID类生成一个随机的盐值,并将盐值保留存入数据库表中,这个字段在后面用户登录的时候 需要解密使用。
- 3、将 用户输入的M密码+盐值,利用加密算法加密,等到新的加密密码保存在数据库表中。这样就做到了密码的加密。
- 4、用户登入的时候,可以利用原始密码+盐值 进行加码 得到的密码与 数据库中注册时存入的你密码做比对。一致则登入成功,否则失败。
代码实现:
package com.cy.store.utils; import org.springframework.util.DigestUtils; public class EncryptMD5 {
/ * * @param oldPassword 原始密码 * @param salt 盐值 * @return 新的密码 */ public static String MD5PASSWORD(String oldPassword,String salt){
String newPassword = oldPassword + salt; for (int i = 0; i < 3; i++) {
newPassword = DigestUtils.md5DigestAsHex(newPassword.getBytes()); } return newPassword; } }
package com.cy.store.service.impl; import com.cy.store.entity.UserEntity; import com.cy.store.mapper.UserMapper; import com.cy.store.service.UserService; import com.cy.store.service.ex.InsertException; import com.cy.store.service.ex.UserDuplicatedException; import com.cy.store.utils.EncryptMD5; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.util.Date; import java.util.InvalidPropertiesFormatException; import java.util.UUID; @Service public class UserServiceImpl implements UserService {
@Autowired private UserMapper userMapper; @Override public void register(UserEntity userEntity) {
// 判断参数是否为空 String username = userEntity.getUsername(); String oldPassword = userEntity.getPassword(); if (username== null || username == "") {
throw new NullPointerException("用户名不能为空"); } // 查询用户是否存在 UserEntity entity = userMapper.selectByUserName(username); if (entity != null) {
throw new UserDuplicatedException("用户已存在"); } // 插入用户信息 userEntity.setIsDelete(0); userEntity.setCreatedUser("system"); userEntity.setCreatedTime(new Date()); userEntity.setModifiedUser("system"); userEntity.setModifiedTime(new Date()); // 密码加密处理 String salt = UUID.randomUUID().toString().replace("-", ""); userEntity.setSalt(salt); String newPassword = EncryptMD5.MD5PASSWORD(oldPassword, salt); userEntity.setPassword(newPassword); Integer integer = userMapper.insertUser(userEntity); if (integer != 1) {
throw new InsertException("用户插入时出现异常"); } } @Override public UserEntity queryByName(String username) {
if (username == "" || username == null) {
throw new NullPointerException("用户姓名不能为空"); } UserEntity userEntity = userMapper.selectByUserName(username); return userEntity; } }
5 注册-控制层
5-1 统一结果数据封装
分析: 前端请求后得到的结果,可以看做是一个对象。这个对象包含的属性有:状态码、数据、描述信息。
封装响应对象
package com.cy.store.common; import java.io.Serializable; / * Json格式的数据对象 */ public class JsonResult<E> implements Serializable {
// 业务状态码 private Integer code; // 描述信息 private String msg; // 数据对象 private E data; public JsonResult() {
} public Integer getCode() {
return code; } public void setCode(Integer code) {
this.code = code; } public String getMsg() {
return msg; } public void setMsg(String msg) {
this.msg = msg; } public E getData() {
return data; } public void setData(E data) {
this.data = data; } / * 逻辑处理正常,返回成功场景 * @param data 返回数据 * @param msg 返回消息 * @param <E> 数据类型 * @return JsonResult 对象 */ public static <E> JsonResult<E> ok(E data ,String msg){
JsonResult<E> result = new JsonResult<>(); result.setCode(1001); result.setMsg(msg); result.setData(data); return result; } / * 逻辑处理异常,返回失败场景 * @param msg * @param <E> * @return */ public static JsonResult<Void> fail(String msg){
JsonResult<Void> result = new JsonResult<>(); result.setCode(9999); result.setMsg(msg); return result; } }
5-2 设计请求
分析: 对于注册功能来说
- 请求路径: /user/reg
- 请求参数: User user
- 请求方式: post
- 响应结果: JsonResult
创建一个Controller类用来接受处理请求,UserController
。
package com.cy.store.controller; import com.cy.store.common.JsonResult; import com.cy.store.entity.UserEntity; import com.cy.store.service.UserService; import com.cy.store.service.ex.InsertException; import com.cy.store.service.ex.UserDuplicatedException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController {
@Autowired private UserService userService; / * 用户注册 * @param user java实体类对象的形式传参 * @return */ //@PostMapping("/reg") //public JsonResult<Void> reg(@RequestBody UserEntity user){
// // try {
// userService.register(user); // return JsonResult.ok(null, "用户注册成功"); // } catch (UserDuplicatedException e) {
// return JsonResult.fail(e.getMessage()); // }catch (InsertException e){
// return JsonResult.fail(e.getMessage()); // } //} / * 封装了 异常统一处理类后的写法 * 如果请求发生了异常,会去调用异常处理类,处理异常并返回给前端,没有异常就直接返回处理成功的结果。 * @param user * @return */ @PostMapping("/reg") public JsonResult<Void> reg(@RequestBody UserEntity user) {
userService.register(user); return JsonResult.ok(null, "用户注册成功"); } }
创建系统业务异常的统一处理全局类 StoreExceptionHandler
package com.cy.store.common; import com.cy.store.service.ex.InsertException; import com.cy.store.service.ex.UserDuplicatedException; import com.cy.store.service.ex.UserNameNotNullException; import com.cy.store.service.ex.UserNotFoundException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; / * StoreExceptionHandler 统一对请求中的异常做处理, * 系统·抛出异常后才会调用这个类。 * 通过捕获异常的类型,判断属于哪个异常,然后返回给前端。 */ @RestControllerAdvice @Slf4j public class StoreExceptionHandler {
@ExceptionHandler(ServiceException.class) public JsonResult<Void> handlerException(Throwable e) {
log.info("Exception:==>" + e.getMessage()); if (e instanceof UserDuplicatedException) {
return JsonResult.fail(e.getMessage()); } else if (e instanceof InsertException) {
return JsonResult.fail(e.getMessage()); } else if (e instanceof UserNotFoundException) {
return JsonResult.fail(e.getMessage()); } else if (e instanceof UserNameNotNullException) {
return JsonResult.fail(e.getMessage()); } else {
return JsonResult.fail(e.getMessage()); } } }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/130272.html