商城项目01-用户注册

项目结构

image-20220315142400952

创建数据表

  1. 选中数据表

use store
  1. 创建t_user表

CREATE TABLE t_user (
uid INT AUTO_INCREMENT COMMENT '用户id',
username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
password CHAR(32) NOT NULL COMMENT '密码',
salt CHAR(36) COMMENT '盐值',
phone VARCHAR(20) COMMENT '电话号码',
email VARCHAR(30) COMMENT '电子邮箱',
gender INT COMMENT '性别:0-女,1-男',
avatar VARCHAR(50) COMMENT '头像',
is_delete INT COMMENT '是否删除:0-未删除,1-已删除',
created_user VARCHAR(20) COMMENT '日志-创建人',
created_time DATETIME COMMENT '日志-创建时间',
modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',
modified_time DATETIME COMMENT '日志-最后修改时间',
PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建用户实体类

  1. 通过表的结构提取出表的公共字段,放在一个实体类的基类中,叫BaseEntity基类中

  2. 创建用户的实体类。需要继承BaseEntity基类

@Data
public class User extends BaseEntity{
   private Integer uid;
   private String username;
   private String password;
   private String salt;
   private String phone;
   private String email;
   private Integer gender;
   private String avatar;
   private Integer isDelete;
}

注册-持久层

通过MyBatis来操作数据库。在做mybatis开发的流程

1. 规划需要执行的SQL语句

  1. 用户的注册功能, 相当于数据的插入操作

insert into t_user(username, password) values(值列表)
  1. 在用户的注册时首先要去查询当前的用户名是否存在,如果存在则不能进行注册。当当与一条查询语句

select * from t_user where username=?

 

2. 设计接口和抽象方法

定义Mapper接口。在项目的目录结构下首先创建一个mapper包,在这个包下再根据不同的功能模块来创建mapper接口。创建一个UserMapper的接口。要在接口中定义这两个SQL语句抽象方法。

public interface UserMapper {
   /**
    * 插入用户的数据
    * @param user 用户的数据
    * @return 受影响的行数(增、删、改都受影响的行数作为返回值,可以根据返回值来判断是否执行成功)
    */
   Integer insert(User user);

   /**
    *
    * @param username 用户名
    * @return 如果找到对应的用户则返回这个用户的数据,如果没有找到则返回null值
    */
   User findByUsername(String username);

}

 

3. 编写映射

  1. 定义XML映射文件,与对应的接口进行关联。所有的映射文件需要放置resources目录下,在这个目录下创建一个mapper文件夹,然后再这个文件夹存放mapper 的映射文件

  2. 创建接口对应的映射文件,遵循和接口名称保持一致即可。创建一个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">
<!--namespace属性:用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径接口-->
<mapper namespace="com.xj.store.mapper.UserMapper">

</mapper>
  1. 配置接口中的方法对应上SQL语句。需要借助标签来完成,insert、update、delete、select,对应的是SQL语句的增删改查操作。

<?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">
<!--namespace属性:用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径接口
useGeneratedKey:开启某个字段的值递增(逐渐设置为递增)
keyProperty:标签将表中的哪个字段作为主键进行递增

-->
<mapper namespace="com.xj.store.mapper.UserMapper">
<!--   自定义映射规则:resultMap标签来完成映射规则的定义-->
<!--
   id:给这个映射规则分配一个唯一的id值,对应的就是resultMap=”id属性的值“属性的取值
   type:取值是一个类,表示数据库中的查询结果与java中的哪个实体类进行结果映射
-->
   <resultMap id="UserEntityMap" type="com.xj.store.entity.User">
<!--       将表的字段与类的苏醒不一致的字段进行陪陪指定,名称一致的字段可以省略不写
   column:表中的属性名称
   property:类中的属性名称
   主键不可省略
-->
       <result column="uid" property="uid"></result>
       <result column="is_delete" property="isDelete"></result>
       <result column="created_user" property="createdUser"></result>
       <result column="created_time" property="createdTime"></result>
       <result column="modified_user" property="modifiedUser"></result>
       <result column="modified_time" property="modifiedTime"></result>
   </resultMap>
   <insert id="insert" useGeneratedKeys="true" keyProperty="uid">
      INSERT INTO user (
          username,password,salt,phone,email,gender,
          avatar,is_delete,created_user,created_time,
          modified_user,modified_time
      )VALUES {
          #{username},${password},#{salt},#{phone},#{email},#{gender},
          #{avatar},#{isDelete},#{createdUser},#{createdTime},
          #{modifiedUser},#{modifiedTime}
          }
   </insert>
<!--   select再执行的时候,查询的结果是一个对象,多个对象。-->
<!--   resultType:表示查询的结果集类型, 只需要指定对应映射类的类型,并且包含完整包接口
       resultMap:标签当表的资源和类的对象属性的字段名称不一致时,来自定义查询结果集的映射规则
-->
   <select id="findByUsername" resultMap="UserEntityMap">
      SELECT * FROM t_user WHERE username = #{username}
   </select>
</mapper>
  1. 将mapper文件的位置注册到properties对应的配置文件中。

    mybatis.mapper-locations=classpath:mappers/*.xml

     

  2. 单元测试:每个独立的层白那些完毕后需要编写单元测试方法,来测试当前的功能。再test包结构下创建一个mapper包,在这个包下再创建持久层的功能测试。

@SpringBootTest
public class UserMapperTests {

@Autowired
private UserMapper userMapper;
/**
* 可以单独运行
* 1. 必须被Test注解修饰
* 2. 返回值必须是void
* 3. 方法的参数列表不知道任何类型
* 4. 方法的访问修饰符必须是public
*/
@Test
public void insert(){
User user = new User();
user.setUsername("tim2");
user.setPassword("123");
Integer rows = userMapper.insert(user);
System.out.println(rows);
}
@Test
public void findByUsername(){
User user = userMapper.findByUsername("tim");
System.out.println(user);
}
}

bug处理:

  1. mybatis.mapper-locations=classpath:mapper/*.xml

  2. @MapperScan("com.xj.store.mapper"),扫描包名必须完全相同

  3. xml中id与mapper中方法名完全相同

注册-业务层

1. 规划异常

异常基类的建立:RuntimeException异常,作为这个异常的子类,然后再去定义具体类型来继承这个异常,业务层异常的基类,ServiceException异常。这个异常继承RuntimeException异常。

  1. 根据业务层不同的功能来详细定义具体的与i长的类型,统一的去继承ServiceException

  2. 用户再进行注册的时候可能会产生用户名被占用的错误,抛出一个异常: UsernameDuplicateException异常

  3. 正在执行数据插入操作的时候,服务器、数据库宕机。处于正在执行插入的过程中所产生的异常:InsertException异常

2. 设计接口和抽象方法

  1. 再service包下创建一个IUserService接口

    public interface IUserService {
       /**
        * 用户注册方法
        * @param user 用户的数据对象
        */
       void reg(User user);
    }
  2. 创建一个实现类UserServiceImpl

  3. 在单元测试包下创建一个UserServiceTest类,在这个类中添加单元测试的功能。

    @Test
    public void insert(){
       try {
           User user = new User();
           user.setUsername("tim4");
           user.setPassword("123");
           userService.reg(user);
           System.out.println("ok");
      } catch (ServiceException e) {
           System.out.println(e.getClass().getName());
           System.out.println(e.getMessage());
      }
    }

     

注册-控制层

1. 创建响应

状态码、状态描述信息、数据。这部分功能封装一个类中,将这个类作为方法返回值,返回给前端浏览器。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class JsonResult<E> implements Serializable {
// 状态码
private Integer state;
// 描述信息
private String message;
// 数据
private E data;

public JsonResult(Integer state) {
this.state = state;
}
}

2. 设计请求

依据当前的业务功能模块进行请求设计。基类

请求路径:/users/reg
请求参数:User user
请求类型:post
响应结果:JsonResult<void>

3. 处理请求

  1. 创建一个控制层对应的类UserControl类,依赖于业务层的接口。

//@Controller
@RestController //@Controller+@ResponseBody
@RequestMapping("users")
public class UserController extends BaseController{
@Autowired
private IUserService userService;
@RequestMapping("reg")
public JsonResult<Void> reg(User user) {
userService.reg(user);
return new JsonResult<>(OK);
}
}

4.控制层优化设计

在控制层抽离一个父类,在父类中统一的去处理冠以异常的相关操作。编写一个BaseController类,统一处理异常。

public class BaseController {
// 操作成功的状态码
public static final int OK = 200;
//请求处理方法,这个方法的放回置就是需要传递给前端的数据
//自动将异常对象传递给此方法的参数列表上
@ExceptionHandler(ServiceException.class) //用于统一处理抛出的异常
public JsonResult<Void> handleException(Throwable e){
JsonResult<Void> result = new JsonResult<>();
if (e instanceof UsernameDuplicatedException){
result.setState(4000);
result.setMessage("用户名重复");
}else if (e instanceof InsertException){
result.setState(5000);
result.setMessage("插入异常");
}
return result;
}
}

注册-前端页面

image-20220315104959534

ajax

  1. ajax语法

$.ajax({
url: "",
type: "",
data: "",
datatype: "",
success: function(){

},
error: function(){

}
});
  1. 个参数含义

参数功能描述
url 例如:url:"localhost:8080/users/reg"
type 请求类型(GET和POST)
data 向指定的请求url地址提交的数据。例如:data: "username=tim&pwd=123"
datatype 提交的数据的类型。一般指定为json。datatype: "json"
success 当服务器正常响应客户端时,会自动调用success参数的方法,并且将服务器返回的数据以参数的形式传递给这个方法的参数上
error 当服务器异常响应客户端时,会自动调用eoor参数的方法,并且将服务器返回的数据以参数的形式传递给这个方法的参数上
  1. js代码可以独立声明在一个js文件里或声明在script中

  2.  

posted @ 2022-03-15 14:28  鬼财神  阅读(51)  评论(0)    收藏  举报