1 创建数据表

1.选中数据表

use store 

 2.创建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;

2.创建用户的实体类

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

implements Serializable的作用

一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的。

a)当你想把的内存中的 对象状态(这四个字划重点) 保存到一个文件中或者数据库中时候;

b)当你想用套接字(socket)在网络上传送对象的时候;

c)当你想通过RMI(远程调用方法,说白了就是在一台服务器运行的代码里面调用只存在于另一台服务器上某个对象的方法)传输对象的时候;

package com.cy.store.entity;

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

/** 作为实体类的基类*/

public class BaseEntity implements Serializable {
    private String createdUser;
    private Date createdTime;
    private String modifiedUser;
    private Date modifiedTime;

    public String getCreatedUser() {
        return createdUser;
    }

    public void setCreatedUser(String createdUser) {
        this.createdUser = createdUser;
    }

    public Date getCreatedTime() {
        return createdTime;
    }

    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }

    public String getModifiedUser() {
        return modifiedUser;
    }

    public void setModifiedUser(String modifiedUser) {
        this.modifiedUser = modifiedUser;
    }

    public Date getModifiedTime() {
        return modifiedTime;
    }

    public void setModifiedTime(Date modifiedTime) {
        this.modifiedTime = modifiedTime;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BaseEntity)) return false;

        BaseEntity that = (BaseEntity) o;

        if (getCreatedUser() != null ? !getCreatedUser().equals(that.getCreatedUser()) : that.getCreatedUser() != null)
            return false;
        if (getCreatedTime() != null ? !getCreatedTime().equals(that.getCreatedTime()) : that.getCreatedTime() != null)
            return false;
        if (getModifiedUser() != null ? !getModifiedUser().equals(that.getModifiedUser()) : that.getModifiedUser() != null)
            return false;
        return getModifiedTime() != null ? getModifiedTime().equals(that.getModifiedTime()) : that.getModifiedTime() == null;
    }

    @Override
    public int hashCode() {
        int result = getCreatedUser() != null ? getCreatedUser().hashCode() : 0;
        result = 31 * result + (getCreatedTime() != null ? getCreatedTime().hashCode() : 0);
        result = 31 * result + (getModifiedUser() != null ? getModifiedUser().hashCode() : 0);
        result = 31 * result + (getModifiedTime() != null ? getModifiedTime().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "BaseEntity{" +
                "createdUser='" + createdUser + '\'' +
                ", createdTime=" + createdTime +
                ", modifiedUser='" + modifiedUser + '\'' +
                ", modifiedTime=" + modifiedTime +
                '}';
    }
}

2.创建用户的实体类,需要继承BaseEntiry基类

建议使用包装类(Integer):提供有相关api,以后方便调用api进行判断。

package com.cy.store.entity;

import java.io.Serializable;
/**  用户的实体类:Springboot约定大于配置*/
public class User extends BaseEntity implements Serializable {
    private Integer uid ;
    private String username;
    private String password;
    private String salt;
    private String phone;
    private String email;
    private Integer ender;
    private String avatar; //头像
    private Integer isDelete; //是否被删除
    // get和set方法、equals和hashCode()方法、toString方法

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getEnder() {
        return ender;
    }

    public void setEnder(Integer ender) {
        this.ender = ender;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public Integer getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(Integer isDelete) {
        this.isDelete = isDelete;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        if (!super.equals(o)) return false;

        User user = (User) o;

        if (getUid() != null ? !getUid().equals(user.getUid()) : user.getUid() != null) return false;
        if (getUsername() != null ? !getUsername().equals(user.getUsername()) : user.getUsername() != null)
            return false;
        if (getPassword() != null ? !getPassword().equals(user.getPassword()) : user.getPassword() != null)
            return false;
        if (getSalt() != null ? !getSalt().equals(user.getSalt()) : user.getSalt() != null) return false;
        if (getPhone() != null ? !getPhone().equals(user.getPhone()) : user.getPhone() != null) return false;
        if (getEmail() != null ? !getEmail().equals(user.getEmail()) : user.getEmail() != null) return false;
        if (getEnder() != null ? !getEnder().equals(user.getEnder()) : user.getEnder() != null) return false;
        if (getAvatar() != null ? !getAvatar().equals(user.getAvatar()) : user.getAvatar() != null) return false;
        return getIsDelete() != null ? getIsDelete().equals(user.getIsDelete()) : user.getIsDelete() == null;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + (getUid() != null ? getUid().hashCode() : 0);
        result = 31 * result + (getUsername() != null ? getUsername().hashCode() : 0);
        result = 31 * result + (getPassword() != null ? getPassword().hashCode() : 0);
        result = 31 * result + (getSalt() != null ? getSalt().hashCode() : 0);
        result = 31 * result + (getPhone() != null ? getPhone().hashCode() : 0);
        result = 31 * result + (getEmail() != null ? getEmail().hashCode() : 0);
        result = 31 * result + (getEnder() != null ? getEnder().hashCode() : 0);
        result = 31 * result + (getAvatar() != null ? getAvatar().hashCode() : 0);
        result = 31 * result + (getIsDelete() != null ? getIsDelete().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", salt='" + salt + '\'' +
                ", phone='" + phone + '\'' +
                ", email='" + email + '\'' +
                ", ender=" + ender +
                ", avatar='" + avatar + '\'' +
                ", isDelete=" + isDelete +
                '}';
    }
}

3 注册-持久层

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

3.1 规划需要执行的SQL语句

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

insert into t_user (username,password) values(值列表)

 2.在用户的注册时首先要去查询当前的用户名是否存在,如果存在则不能注册,相当于查询语句。

select * from t_user where username=?

3.2 设计接口和抽象方法

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

package com.cy.store.mapper;

import com.cy.store.entity.User;
import org.apache.ibatis.annotations.Mapper;

/** 用户模块的持久层接口*/
@Mapper
public interface UserMapper {
    /**
     * 插入用户的数据
     * @param user 用户的数据
     * @return  受影响的行数(增删改查,都受影响的行数作为返回值,可以判断是否成功)
     */
    Integer insert(User user);

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

2.在启动类配置mapper接口文件的位置

//不建议使用@Mapper注解,原因:一个包底下太多,麻烦

// MapperScan注解指定当前项目中的Mapper接口路径的位置,在项目启动时会自动加载所有的接口文件 @MapperScan("com.cy.store.mapper")

3.3编写映射

 1.定义xml映射文件,与对应的接口进行关联。所有的映射文件需要放在resours目录下,在这个目录下创建一个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.cy.store.mapper.UserMapper">
   
</mapper>

3.配置接口中的方法对应上SQL语句上。需要借助标签来完成。进行增删改查操作。

<!-- 自定义映射规则:resultMap标签来完成映射规则的定义-->
    <!--
        id属性:表示给这个映射负责分配一个唯一的id值,对应的就是resultMap id属性的值的取值
        type属性:取值是一个类,表示的是数据库中的查询结果与Java中哪个实体类进行结果集的映射
    -->
    <resultMap id="UserEntityMap" type="com.cy.store.entity.User">
        <!-- 将表的字段和类不一致的字段进行匹配指定,名称一致的字段可以省略不屑-->
        <!--
        配合完成不一样的映射:
            column属性:表示表中的字段名称
            property属性:表示类中的属性名
        -->
        <!--在定义映射规则时主键不可以省略-->
        <id column="uid" property="uid"></id>
        <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>
    <!-- id属性:表示映射的接口中方法的名称,直接再标签的内容部来编写SQL语句-->
    <!--
       useGeneratedKey属性,表示开启某个字段的值递增(主键设置为递增)
       keyProperty属性:表示将表中的哪个字段作为主键进行递增
    -->
    <insert id="insert" useGeneratedKeys="true" keyProperty="uid">
        insert into t_user (username, password, salt, phone, email, gende, avatar, is_delet,
                            created_user, created_time, modified_user, modified_time)
        VALUES (
                #{username}, #{password}, #{salt}, #{phone}, #{email}, #{gende}, #{avatar}, #{isDelet},
                #{createdYser}, #{createdTime}, #{modifiedUser}, #{modifiedTime}
                )
    </insert>
    <!--  select语句在执行的时候,查询的结果是一个对象,多个对象
        result type:表示查询的结果集类型,只需要指定对应映射类的类型,并且包含完整接口
        resultMap:标签当表的字段和类的对象属性字段不一致时,来定义查询结果集的映射规则
    -->
    <select id="findByUsername" resultMap="UserEntityMap">
        select * from  t_user where username=#{username}
    </select>

3.将mapper文件的位置注册到properties对应的配置文件下

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

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

package com.cy.store.mapper;

import com.cy.store.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

//@SpringBootTest:表示标注当前的类i是一个测试类,不会随打包发送
@SpringBootTest
//@RunWith:表示启动这个单元测试类(是不能够运行的),需要传递一个参数,必须时SpringRunner的实例类型
@RunWith(SpringRunner.class)
public class UserMapperTests {
    // idea有检测的功能,接口时不能直接创建Bean的(动态代理技术来解决)
    @Autowired
    //因为要使用,所以申明出来,并用@Autowired完成初始化
    private UserMapper userMapper;
    /**
     * 单元测试方法:单独的独立运行,不用启动整个项目,可以做单元测试,提升了代码的测试效率
     * 1.必须被@Test注解修饰
     * 2.返回值类型必须时void
     * 3.方法的参数列表不指定任何类型
     * 4.方法的访问必须是public
     */
    @Test
    public void insert(){

        User user=new User();
        user.setUsername("tim");
        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);
    }

}

4 注册-业务层

4.1规划异常

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

package com.cy.store.service.ex;
/**业务层异常的基类:throw new ServiceException()  */
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);
    }
}

根据业务层不同的业务功能来详细定义具体的异常的类型,统一的去继承ServiceException异常类。 

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

package com.cy.store.service.ex;
/**用户名被占用的异常*/
public class UsernameDuplicatedException extends ServiceException{
    public UsernameDuplicatedException() {
        super();
    }

    public UsernameDuplicatedException(String message) {
        super(message);
    }

    public UsernameDuplicatedException(String message, Throwable cause) {
        super(message, cause);
    }

    public UsernameDuplicatedException(Throwable cause) {
        super(cause);
    }

    protected UsernameDuplicatedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}

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

package com.cy.store.service.ex;

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 设计接口和抽象方法

在service包下创建一个IUserService接口。

/** 用户模块业务层接口*/
public interface IUserService {
    /**
     * 用户注册方法
     * @param user 用户的数据对象
     */
    void reg(User user);

}

2.创建一个实现类UserServiceImpl,需要实现这个接口,并且实现 抽象方法。

package com.cy.store.service.impl;

import com.cy.store.entity.User;
import com.cy.store.mapper.UserMapper;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.Locale;
import java.util.UUID;

@Service //@Service注解:将当前类的对象交给Spring来管理,自动创建对象以及对象的维护
/** 用户模块业务层的实现类*/
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public void reg(User user) {
        //通过user参数来获取传递过来的username
        String username= user.getUsername();
        //调用findByUsername(username)判断用户是否被注册过
        User result = userMapper.findByUsername(username);
        //判断结果集是否不为null则抛出用户名被占用异常
        if(result !=null){
            //抛出异常
            throw new UsernameDuplicatedException("用户名被占用");
        }
        //密码加密处理的实现:md5算法的形式
        // 串+password+串----MD5算法进行加密,连续加载三次
        // 盐值+password+盐值 ---盐值就是一个随机的字符串
        String oldPassword =user.getPassword();
        //获取盐值(随机生成一个盐值)
        String salt = UUID.randomUUID().toString().toUpperCase();
        //补全数据,盐值的记录
        user.setSalt(salt);
        //将密码与盐值作为一个整体进行加密处理,忽略原有密码强度,提升了数据的安全性
        String md5Password=getMD5Password(oldPassword,salt);
        //将加密之后的密码重新补全设置到User中
        user.setPassword(md5Password);

        //补全数据:is_delete设置为0(未删除)
        user.setIsDelete(0);
        //补全数据:4个字段信息
        user.setCreatedUser(user.getUsername());
        user.setModifiedUser(user.getUsername());
        Date date=new Date();
        user.setCreatedTime(date);
        user.setModifiedTime(date);

        //执行注册业务逻辑功能的实现(rows=1)
        Integer rows = userMapper.insert(user);
        if(rows !=1){
            throw new InsertException("在用户注册过程中产生未知异常");
        }


    }
    /** 定义一个md5算法的加密处理*/
    private String getMD5Password(String password,String salt){
        //md5加密算法的调用(进行三次加密)
        for (int i = 0; i < 3; i++) {
            password = DigestUtils.md5DigestAsHex((salt+password+salt).getBytes()).toUpperCase();
        }
        //返回加密后的密码
        return password;

    }
}

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

package com.cy.store.service;

import com.cy.store.entity.User;
import com.cy.store.mapper.UserMapper;
import com.cy.store.service.ex.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

//@SpringBootTest:表示标注当前的类i是一个测试类,不会随打包发送
@SpringBootTest
//@RunWith:表示启动这个单元测试类(是不能够运行的),需要传递一个参数,必须时SpringRunner的实例类型
@RunWith(SpringRunner.class)
public class UserServiceTests {
    // idea有检测的功能,接口时不能直接创建Bean的(动态代理技术来解决)
    @Autowired
    //因为要使用,所以申明出来,并用@Autowired完成初始化
    private IUserService userService;
    /**
     * 单元测试方法:单独的独立运行,不用启动整个项目,可以做单元测试,提升了代码的测试效率
     * 1.必须被@Test注解修饰
     * 2.返回值类型必须时void
     * 3.方法的参数列表不指定任何类型
     * 4.方法的访问必须是public
     */
    @Test
    public void reg(){
        try {
            User user=new User();
            user.setUsername("lhh");
            user.setPassword("123");
            userService.reg(user);
            System.out.println("OK");
        } catch (ServiceException e) {
            //获取类的对象,再获取类的名称
            System.out.println(e.getClass().getSimpleName());
            //获取异常的具体描述信息
            System.out.println(e.getMessage());
        }
    }


}

5 注册-控制层

5.1创建响应

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

package com.cy.store.util;

import java.io.Serializable;

/**
 * Json格式的数据进行响应
 */
public class JsonResult<E> implements Serializable {
    /**状态码*/
    private Integer state;
    /**描述信息*/
    private String message;
    /** 数据*/
    private E data;

    public JsonResult() {
    }

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

    public JsonResult(Throwable e) {
        this.message=e.getMessage();
    }

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

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }
}

5.2 设计请求

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

请求路径:/user/reg

请求参数:User user

请求类型:POST

响应结果:JsonResult<void>

5.3 处理请求

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

package com.cy.store.controller;

import com.cy.store.entity.User;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

//@Controller
@RestController//@Controller +@ResponseBody
@RequestMapping("users")
public class UserController {
    @Autowired
    private IUserService userService;
    @RequestMapping("reg")
//    @ResponseBody//表示此方法的响应结果以json格式进行数据的响应给前端
    public JsonResult<Void> reg(User user){
        //创建响应结果对象
        JsonResult<Void> result =new JsonResult<>();
        try {
            userService.reg(user);
            result.setState(200);
            result.setMessage("用户注册成功");
        } catch (UsernameDuplicatedException e) {
            result.setState(4000);
            result.setMessage("用户名被占用");
        } catch (InsertException e){
            result.setState(5000);
            result.setMessage("注册时产生未知的异常");
        }
        return result;
    }
}

 5.4 控制层优化设计

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

package com.cy.store.controller;

import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.ServiceException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import com.cy.store.util.JsonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;

/** 控制层类的基类*/
public class BaseController {
    /**操作成功的状态码*/
    public static final int OK=200;
    //请求处理方法,这个方法的返回值就是需要传递给前端的数据
    //自动将异常对象传递给此方法的参数列表中
    //当项目中产生了异常,被统一拦截到此方法中了,这个方法此时就充当请求处理方法,方法的返回值给到前端
    @ExceptionHandler(ServiceException.class) //用于统一处理抛出的异常
    public JsonResult<Void> handleException(Throwable e){
        JsonResult<Void> result=new JsonResult<>(e);
        if(e instanceof UsernameDuplicatedException){
            result.setState(4000);
            result.setMessage("用户名已经被占用");
        } else if (e instanceof InsertException) {
            result.setState(5000);
            result.setMessage("注册时产生的异常");
        }
        return result;

    }

}

 重新构建了reg()方法

@RequestMapping("reg")
    public JsonResult<Void> reg(User user){
        userService.reg(user);
        return new JsonResult<>(OK);
    }
}

6 注册-前端页面

1.在registe页面中编写发送请求的方法,点击事件来完成。先选中对应的按钮($("选择器")),再去添加点击的事件,$.ajax()函数发送异步请求。

2.JQuery封装了一个函数,称之为$.ajax函数,通过对象调用ajax()函数,可以异步加载相关的请求。依靠的时Javascript提供的一个对象XHR(XmlHttpResponse),封装了这个对象。

3.ajax()使用方式。需要传递一个方法体作为方法的参数来使用,一对大括号称为方法体。ajax接收多个参数,参数与参数之间要求使用”,” 进行分割,每一组参数之间使用:进行分割,参数的组成部分一个是参数的名称(不能随意的定义),是参数的值,参数的值要求使用字符串来标识。参数的声明顺序没有要求。语法结构:

$.ajax({

        url:" "

        type:" "

        data:" " 

        dataType:" "

        success:function(){


},

        error:function(){


}

});



4.ajax()参数的含义:

参数

功能描述

url

表示请求的地址(url地址),不能包含参数列表部分的内容。例如:url:“localhost:8080/users/reg”

type

请求类型(GET和POST请求的类型)。例如:type:”POST“

data

向指定的请求url地址提交的数据。例如:data:”username=tom&pwd=123“

dataType

提交的数据类型。数据类型一般指定为json类型。dataType:”json“

success

当服务器正常响应客户端时,会自动调用success参数的方法,并且将服务器返回的数据以参数的形式传递给这个方法的参数下。

error

当服务器未正常响应客户端时,会自动调用success参数的方法,并且将服务器返回的数据以参数的形式传递给这个方法的参数下。

 5.js代码可以独立存放再一个js的文件里或者声明在一个script标签中。

id选择器以#开头,例如:

$("#btn-reg")

<script type="text/javascript">
		//1.监听注册按钮是否被点击,如果被点击,可以执行一个方法
		$("#btn-reg").click(function () {
			//动态获取表单中的数据
			// let username= $("#username").val()
			// let pwd= $("#password").val()
			console.log($("#form-reg").serialize())
			//2.发送ajax()的异步请求来完成用户的注册功能
			$.ajax({
				url:"/users/reg",
				type:"POST",
				//username=TON&password=123
				data:$("#form-reg").serialize(),
				dataType:"JSON",
				success:function (json) {
					if(json.state ==200){
						alert("注册成功")
					}else{
						alert("注册失败")
					}
				},
				error:function (xhr) {
					alert("注册时产生未知的错误!"+xhr.status)
				}
			})

其中

$("#form-reg").serialize()

输出为:username=test01&password=123


6.js代码无法正常被服务器解析,体现在点击页面中的按钮没有任何的响应,解决方案:

·在项目的maven下clear清理项目-install重新部署

·在项目的file选项下-cash清理缓存

·重新的去构建项目:build选项下-rebuild选项