[网页五子棋][用户模块]数据库设计和配置(MyBatis)、约定前后端交互接口、服务器开发

文章目录

数据库

数据库设计

完成注册登录以及用户分数管理

  • 使用数据库来保存上述用户信息

创建 java_gobang 数据库, user 表,表示用户信息和分数信息

sql 复制代码
create database if not exists java_gobang;  
  
use java_gobang;  
  
drop table if exists user;  
create table user (  
    userId int primary key auto_increment,  
    username varchar(50) unique,  
    password varchar(50),  
    score int,         -- 天梯积分  
    totalCount int,    -- 比赛总场数  
    winCount int       -- 获胜场数  
);  
  
insert into user values (null, 'zhangsan', '123', 1000, 0, 0);  
insert into user values (null, 'lisi', '123', 1000, 0, 0);  
insert into user values (null, 'wangwu', '123', 1000, 0, 0);

配置 MyBatis

使用 MyBatis 来连接并操作我们的数据库

1. Spring 配置

修改 Spring 的配置文件,使用数据库可以被连接上

xml 复制代码
spring:  
  application:  
    name: java_gobang  
  
  datasource:  
    url: jdbc:mysql://127.0.0.1:3306/java_gobang?characterEncoding=utf8&useSSL=false  
    username: root  
    password: 20230153018  
    driver-class-name: com.mysql.cj.jdbc.Driver  
  
mybatis:  
  mapper-locations: classpath:mapper/**Mapper.xml
  • 如果 driver-class-name 报错,可能是没有引入 Maven 依赖的原因

2. 创建实体类

创建一个实体类:用户

java 复制代码
package org.example.model;  
  
public class User {  
    private int userId;  
    private String username;  
    private String password;  
    private int score;  
    private int totalCount;  
    private int winCount;  
  
    public int getUserId() {  
        return userId;  
    }  
  
    public void setUserId(int userId) {  
        this.userId = userId;  
    }  
  
    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 int getScore() {  
        return score;  
    }  
  
    public void setScore(int score) {  
        this.score = score;  
    }  
  
    public int getTotalCount() {  
        return totalCount;  
    }  
  
    public void setTotalCount(int totalCount) {  
        this.totalCount = totalCount;  
    }  
  
    public int getWinCount() {  
        return winCount;  
    }  
  
    public void setWinCount(int winCount) {  
        this.winCount = winCount;  
    }  
}

3. 创建 Mapper 接口

java 复制代码
package org.example.model;  
  
/**  
 * 接口里面创建一些典型的方法  
 */  
public interface UserMapper {  
    // 往数据库中插入一个用户,用于注册功能  
    void insert(User user);  
  
    // 根据用户名,来查询用户的详细信息,用于登录功能  
    User selectByName(String userName);  
}

4. 使用 MyBatis

实现 MyBatis 的相关 xml 配置文件,来自动实现数据库操作

实现 UserMapper.xml

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="org.example.java_gobang.model.UserMapper">  
    <insert id="insert">  
        insert into user values(null, #{username}, #{password}, 1000, 0, 0);  
    </insert>  
  
    <select id="selectByName" resultType="org.example.java_gobang.model.User">  
        select * from user where username = #{username};  
    </select>  
</mapper>

约定前后端交互接口

登录接口

请求:

  • POST /login HTTP/1.1
  • Content-Type: application/x-222-form-urlencoded
  • username=zhangsan&password=123

响应:

  • HTTP/1.1 200 OK
  • Content-Type: application/json
    {
    userId: 1,
    username: 'zhangsan',
    score: 1000,
    totalCount: 0,
    winCount: 0
    }
  • 如果登录失败,就返回一个无效的 user 对象
    • 比如,这里的每个属性都是空着的,像 userId => 0

注册接口

请求:

  • POST /register HTTP/1.1
  • Content-Type: application/x-www-form-urlencoded
  • username=zhangsan&password=123

响应:

  • HTTP/1.1 200 OK
  • Content-Type: application/json
    {
    userId: 1,
    username: 'zhangsan',
    score: 1000,
    totalCount: 0,
    winCount: 0
    }

前后端交互的接口,在约定的时候,是有很多种交互方式的

  • 这里约定好了之后,后续的后端/前端代码,都要严格地遵守这个约定来写代码

获取用户信息

从服务器获取到当前登录用户的信息

  • 程序运行过程中,用户登录了之后,让客户端随时通过这个接口,来访问服务器,获取到自身的信息

请求:

  • GET /userInfo HTTP/1.1

响应:

  • HTTP/1.1 200 OK
  • COntent-Type: application/json
    {
    userId: 1,
    username: 'zhangsan',
    score: 1000,
    totalCount: 0,
    winCount: 0
    }

服务器开发

创建 api.UserAPI 类,主要实现三个方法:

  • login:用来实现登录逻辑
  • register:用来实现注册逻辑
  • getUserInfo:用来实现登录成功后显示用户分数的信息

login

在登录的时候,我们要做的关键操作就是:

  • 根据用户传进来的 username,去数据库里面查一下,看查到的结果能不能和传入进来的 password 匹配
    • 匹配:登陆成功
    • 不匹配:登录失败
java 复制代码
@PostMapping("/login")  
@ResponseBody  
public Object login(String username, String password, HttpServletRequest req) {  
    // 关键操作,就是根据 username 去数据库中进行查找,  
    // 如果能找到匹配的用户,并且密码也一直,就认为登录成功  
    User user = userMapper.selectByName(username); 
    System.out.println("[login] username=" + username);  
    if (user == null || !user.getPassword().equals(password)) {  
        // 登录失败  
        System.out.println("登录失败!");  
        return new User();  
    }  
    HttpSession httpSession = req.getSession(true);  
    httpSession.setAttribute("user", user);  
    return user;  
}
  • HttpServletRequest:可以通过这个对象获取或创建 Session,以及访问其他 HTTP 属性
  • getSession(true)
    • 如果当前请求中没有带上已有的 Session ID,或者 Session 已过期,就会创建一个新的 HttpSession 对象
    • 如果存在有效的 Session,会返回当前 Session
  • getSession(false)
    • 如果当前请求没有有效的 Session,会返回 null,不会创建新的 Session
  • httpSession.setAttribute("user", user)
    • Session 保存一项属性,键是 "user",值是当前登录的用户对象
    • 保存后,在接下来的任何请求中,只要该用户带着同一个 Session ID(通常通过 cookie 自动携带),就能取出这个对象

register

java 复制代码
@PostMapping("/register")  
@ResponseBody  
public Object register(String username, String password) {  
    try {  
        User user = new User();  
        user.setUsername(username);  
        user.setPassword(password);  
        userMapper.insert(user);  
        return user;  
    }catch (org.springframework.dao.DuplicateKeyException e) {  
        User user = new User();  
        return user;  
    }  
}
  • } catch (org.springframework.dao.DuplicateKeyException e) {
    • 如果数据库表中设置了 username 为唯一索引(UNIQUE),当插入一个已存在的用户名时会抛出此异常
    • 这个异常来自 SpringDataAccessException 系列,专门处理数据库层的错误

getUserInfo

java 复制代码
@GetMapping("/userInfo")  
@ResponseBody  
public Object getUserInfo(HttpServletRequest req) {  
    try {  
        HttpSession httpSession = req.getSession(false);  
        User user = (User) httpSession.getAttribute("user");  
        return user;  
    }catch (NullPointerException e) {  
        return new User();  
    }  
}

完整代码

java 复制代码
package org.example.java_gobang.api;  
  
import jakarta.annotation.Resource;  
import jakarta.servlet.http.HttpServletRequest;  
import jakarta.servlet.http.HttpSession;  
import org.example.java_gobang.model.User;  
import org.example.java_gobang.model.UserMapper;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.ResponseBody;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class UserAPI{  
  
    @Resource  
    private UserMapper userMapper;  
  
    @PostMapping("/login")  
    @ResponseBody  
    public Object login(String username, String password, HttpServletRequest req) {  
        // 关键操作,就是根据 username 去数据库中进行查找,  
        // 如果能找到匹配的用户,并且密码也一直,就认为登录成功  
        User user = userMapper.selectByName(username);  
        System.out.println("[login] username=" + username);  
        if (user == null || !user.getPassword().equals(password)) {  
            // 登录失败  
            System.out.println("登录失败!");  
            return new User();  
        }  
        HttpSession httpSession = req.getSession(true);  
        httpSession.setAttribute("user", user);  
        return user;  
    }  
  
    @PostMapping("/register")  
    @ResponseBody  
    public Object register(String username, String password) {  
        try {  
            User user = new User();  
            user.setUsername(username);  
            user.setPassword(password);  
            userMapper.insert(user);  
            return user;  
        }catch (org.springframework.dao.DuplicateKeyException e) {  
            User user = new User();  
            return user;  
        }  
    }  
  
    @GetMapping("/userInfo")  
    @ResponseBody  
    public Object getUserInfo(HttpServletRequest req) {  
        try {  
            HttpSession httpSession = req.getSession(false);  
            User user = (User) httpSession.getAttribute("user");  
            return user;  
        }catch (NullPointerException e) {  
            return new User();  
        }  
    }  
}
相关推荐
奈斯ing32 分钟前
【prometheus+Grafana篇】基于Prometheus+Grafana实现MySQL数据库的监控与可视化
linux·运维·数据库·mysql·grafana·prometheus
hqxstudying2 小时前
Redis击穿,穿透和雪崩详解以及解决方案
java·数据库·redis·缓存
sensen_kiss3 小时前
CPT208 Human-Centric Computing 人机交互 Pt.7 交互和交互界面
学习·人机交互·交互
檀越剑指大厂3 小时前
【数据库系列】bulk_save_objects 与 bulk_insert_mappings 对比
运维·服务器·数据库
Z.Virgil4 小时前
【案例94】笛卡尔积导致报“临时表空间不足”
java·运维·服务器·开发语言·数据库·sql
铃木隼.4 小时前
MySQL数据库(一)
数据库·mysql·oracle
kgcc4 小时前
MySQL数据库操作
运维·数据库·mysql
not coder5 小时前
Pytest 是什么
数据库·pytest
User_芊芊君子5 小时前
C语言循环结构实战:while和for到底用哪个?
android·c语言·数据库
哈哈的二哈5 小时前
MySql--explain的用法
数据库·mysql