网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(二)前后端实现用户的登录和注册功能【用户模块】

网页版Java五子棋项目(二)前后端实现用户的登录和注册功能【用户模块】

  • 在用户模块我们要清楚要完成的任务
  • 一、MyBatis后端操作数据库
    • 1. 需要在数据库创建用户数据库
        • 1. 用户id
        • 2. 用户名
        • 3. 密码
        • 4. 天梯积分
        • 5. 总场数
        • 6. 获胜场数
    • 2. 创建用户类User
        • 和数据库的数据一一对应
    • 3. 用MyBatis操作数据库
      • 1. 连接数据库(application.yml连接数据库)
        • 这个可以直接赋值代码
      • 2. 创建UserMapper的Java接口(interface UserMapper)
        • 创建接口,在UserMapper.xml实现
        • 在model中创建
        • 需要实现@Mapper注释
      • 3. 创建UserMapper.xml 实现数据库操作
        • 实现具体数据库操作
        • 利用标签
        • mapper标签地址要对应好
        • 不同操作 标签不同
  • 二、约定前后端接口
    • 1. 登录接口
        • 前端发送post请求,具体内容是直接对应的
        • 所以后端的参数也是对应的,然后后端返回一个用户类
          • 1. 后端通过前端传的用户名,查询数据库
          • 2. 如果数据库为空,返回一个新的 用户类
          • 3. 否则,把Session置为true
          • 4. 然后返回用户类
    • 2. 注册接口
        • 前端POST请求,参数是一一对应
        • 后端参数接受一个一一对应
          • 1. 创建一个User类
          • 2. 调用userMapper插入
          • 如果创建重复 则抛出异常 返回一个新的User
    • 3. 从服务器获取当前登录的信息
        • 前端GET请求
        • 后端
          • 1. 判断用户是否Session中
          • 2. 查询数据库 返回对应类
          • 如果没有在则返回一个新的user
    • 4. UserAPI
  • 三、实现前端页面
    • 1. 登录页面
    • 2. 注册页面

在用户模块我们要清楚要完成的任务

一、MyBatis后端操作数据库

1. 需要在数据库创建用户数据库

1. 用户id

2. 用户名

3. 密码

4. 天梯积分

5. 总场数

6. 获胜场数

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);

2. 创建用户类User

和数据库的数据一一对应

package com.example.java_gobang.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. 用MyBatis操作数据库

1. 连接数据库(application.yml连接数据库)

这个可以直接赋值代码

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/java_gobang?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

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

logging:
  pattern:
    console: "[%-5level] - %msg%n"

2. 创建UserMapper的Java接口(interface UserMapper)

创建接口,在UserMapper.xml实现

在model中创建

需要实现@Mapper注释

package com.example.java_gobang.model;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper {
    // 往数据库里插入一个用户. 用于注册功能.
    void insert(User user);

    // 根据用户名, 来查询用户的详细信息. 用于登录功能
    User selectByName(String username);

    // 总比赛场数 + 1, 获胜场数 + 1, 天梯分数 + 30
    void userWin(int userId);

    // 总比赛场数 + 1, 获胜场数 不变, 天梯分数 - 30
    void userLose(int userId);
}

3. 创建UserMapper.xml 实现数据库操作

实现具体数据库操作

利用标签

mapper标签地址要对应好

不同操作 标签不同

<?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.example.java_gobang.model.UserMapper">
    <insert id="insert">
        insert into user values(null, #{username}, #{password}, 1000, 0, 0);
    </insert>

    <select id="selectByName" resultType="com.example.java_gobang.model.User">
        select * from user where username = #{username};
    </select>
    
    <update id="userWin">
        update user set totalCount = totalCount + 1, winCount = winCount + 1, score = score + 30
        where userId = #{userId}
    </update>
    
    <update id="userLose">
        update user set totalCount = totalCount + 1, score = score - 30
        where userId = #{userId}
    </update>
</mapper>

二、约定前后端接口

1. 登录接口

在这里插入图片描述

前端发送post请求,具体内容是直接对应的

所以后端的参数也是对应的,然后后端返回一个用户类

1. 后端通过前端传的用户名,查询数据库
2. 如果数据库为空,返回一个新的 用户类
3. 否则,把Session置为true
4. 然后返回用户类
@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;
}

2. 注册接口

在这里插入图片描述

前端POST请求,参数是一一对应

后端参数接受一个一一对应

1. 创建一个User类
2. 调用userMapper插入
如果创建重复 则抛出异常 返回一个新的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;
        }
    }

3. 从服务器获取当前登录的信息

在这里插入图片描述

前端GET请求

后端

1. 判断用户是否Session中
2. 查询数据库 返回对应类
如果没有在则返回一个新的user
@GetMapping("/userInfo")
@ResponseBody
public Object getUserInfo(HttpServletRequest req) {
    try {
        HttpSession httpSession = req.getSession(false);
        User user = (User) httpSession.getAttribute("user");
        // 拿着这个 user 对象, 去数据库中找, 找到最新的数据
        User newUser = userMapper.selectByName(user.getUsername());
        return newUser;
    } catch (NullPointerException e) {
        return new User();
    }
}

4. UserAPI

package com.example.java_gobang.api;

import com.example.java_gobang.model.User;
import com.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;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@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");
            // 拿着这个 user 对象, 去数据库中找, 找到最新的数据
            User newUser = userMapper.selectByName(user.getUsername());
            return newUser;
        } catch (NullPointerException e) {
            return new User();
        }
    }
}

三、实现前端页面

1. 登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>

    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
    <div class="nav">
        五子棋对战
    </div>
    <div class="login-container">
        <!-- 登录界面的对话框 -->
        <div class="login-dialog">
            <!-- 提示信息 -->
            <h3>登录</h3>
            <!-- 这个表示一行 -->
            <div class="row">
                <span>用户名</span>
                <input type="text" id="username">
            </div>
            <!-- 这是另一行 -->
            <div class="row">
                <span>密码</span>
                <input type="password" id="password">
            </div>
            <!-- 提交按钮 -->
            <div class="row">
                <button id="submit">提交</button>
            </div>
        </div>

    </div>

    <script src="./js/jquery.min.js"></script>
    <script>
        let usernameInput = document.querySelector('#username');
        let passwordInput = document.querySelector('#password');
        let submitButton = document.querySelector('#submit');
        submitButton.onclick = function() {
            $.ajax({
                type: 'post',
                url: '/login',
                data: {
                    username: usernameInput.value,
                    password: passwordInput.value,
                },
                success: function(body) {
                    // 请求执行成功之后的回调函数
                    // 判定当前是否登录成功~
                    // 如果登录成功, 服务器会返回当前的 User 对象. 
                    // 如果登录失败, 服务器会返回一个空的 User 对象. 
                    if (body && body.userId > 0) {
                        // 登录成功
                        alert("登录成功!");
                        // 重定向跳转到 "游戏大厅页面".
                        location.assign('/game_hall.html');
                    } else {
                        alert("登录失败!");
                    }
                },
                error: function() {
                    // 请求执行失败之后的回调函数
                    alert("登录失败!");
                }
            });
        }
    </script>
</body>
</html>

2. 注册页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
    <div class="nav">
        五子棋对战
    </div>
    <div class="login-container">
        <!-- 登录界面的对话框 -->
        <div class="login-dialog">
            <!-- 提示信息 -->
            <h3>注册</h3>
            <!-- 这个表示一行 -->
            <div class="row">
                <span>用户名</span>
                <input type="text" id="username">
            </div>
            <!-- 这是另一行 -->
            <div class="row">
                <span>密码</span>
                <input type="password" id="password">
            </div>
            <!-- 提交按钮 -->
            <div class="row">
                <button id="submit">提交</button>
            </div>
        </div>
    </div> 

    <script src="js/jquery.min.js"></script>
    <script>
        let usernameInput = document.querySelector('#username');
        let passwordInput = document.querySelector('#password');
        let submitButton = document.querySelector('#submit');
        submitButton.onclick = function() {
            $.ajax({
                type: 'post',
                url: '/register',
                data: {
                    username: usernameInput.value,
                    password: passwordInput.value,
                },
                success: function(body) {
                    // 如果注册成功, 就会返回一个新注册好的用户对象. 
                    if (body && body.username) {
                        // 注册成功!
                        alert("注册成功!")
                        location.assign('/login.html');
                    } else {
                        alert("注册失败!");
                    }
                }, 
                error: function() {
                    alert("注册失败!");
                }
            });
        }

    </script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61223.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue2-vue项目中你是如何解决跨域的?

1、跨域是什么&#xff1f; 跨域本质是浏览器基于同源策略的一种安全手段。 同源策略&#xff08;sameoriginpolicy&#xff09;&#xff0c;是一种约定&#xff0c;它是浏览器最核心也是最基本的安全功能。 所谓同源&#xff08;即指在同一个域&#xff09;具有以下三个相同点…

【分布式系统】聊聊服务调度

什么是服务治理 对于程序员来说的话&#xff0c;把功能按照一定的设计进行开发上线之后&#xff0c;其实并不够&#xff0c;在未来的时间内&#xff0c;其实还需要做好功能的维护工作&#xff0c;而维护项目的成本远远高于开发出一个软件的成本。 对于功能开发起来期来说&am…

2021-03-03 Multisim 14.0 电池充电防止反接保护

R2R3当作充电线电阻看,也可设置这2个电阻导线电阻,电阻取值依据充电电流范围确定,由于电池存在电压因此可以用光耦检测,发光二极管当作继电器看,可采用继电器自锁,当下次再次反接的话另一个继电器同样,2个继电器相互控制.本电路可验证极性变化时2路检测的变化,图中S1为模拟电池…

聊聊混合动力汽车和纯电骑车的优势和劣势

混合动力汽车和纯电动骑车是两种不同的交通工具&#xff0c;它们都有各自的优势和劣势。本文将分别探讨混合动力汽车和纯电动骑车的优势和劣势&#xff0c;并为文章提供三个备选的好听的标题。 混合动力汽车是一种结合了内燃机和电动机的汽车&#xff0c;它可以同时利用燃油和电…

【rust/入门】windows安装rust gnu环境(折腾)

说在前面 首先说明&#xff0c;我是rust入门选手&#xff0c;之前都是在wsl写rust&#xff0c;突然想在windows下装下rust。windows版本&#xff1a;windows11 22H2原文换源 心路历程 看到教程我陷入了沉默&#xff0c;(官方推荐) 打开Microsoft C Build Tools我开始不解&…

【RabbitMQ】golang客户端教程3——发布订阅(使用fanout交换器)

发布订阅 在上一个教程中&#xff0c;我们创建了一个工作队列。工作队列背后的假设是每个任务只传递给一个工人。在这一部分中&#xff0c;我们将做一些完全不同的事情——我们将向多个消费者传递一个消息。这就是所谓的“订阅/发布模式”。 为了说明这种模式&#xff0c;我们…

06 Ubuntu22.04上的miniconda3安装、深度学习常用环境配置

下载脚本 我依然是在清华镜像当中寻找的脚本。这里找脚本真的十分方便&#xff0c;我十分推荐。 wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh 下载十分快速&#xff0c;10秒解决问题 运行miniconda3安装脚本 赋予执…

项目一:基于stm32的阿里云智慧消防监控系统

若该文为原创文章&#xff0c;转载请注明原文出处。 Hi&#xff0c;大家好&#xff0c;我是忆枫&#xff0c;今天向大家介绍一个单片机项目。 一、简介 智慧消防监控系统&#xff0c;是用于检测火灾&#xff0c;温度&#xff0c;烟雾的监控系统。以 stm32单片机为核心外加 MQ…

掌握Memory Profiler技巧:识别内存问题

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、如何使用四、页面说明4.1 Java 和 Kotlin 分配…

LeetCode 热题 100 JavaScript--102. 二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 示例 2&#xff1a; 输入&#xff1a;root [1…

il汇编整数相加

在这里尝试了IL汇编字符串连接&#xff1b; IL汇编字符串连接_bcbobo21cn的博客-CSDN博客 下面来看一下IL汇编整数相加&#xff1b; 大概的看一下一些资料&#xff0c;下面语句&#xff0c; ldc.i4 20 ldc.i4 30 add 看上去像是&#xff0c;装载整数20到一个类似于…

【C++学习手札】一文带你初识构造函数和拷贝构造函数、析构函数

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f340;本文前置知识&#xff1a; C类 ♈️今日夜电波&#xff1a; アイネクライネ —米津玄師 1:11 ━━━━━━️&#x1f49f;──────── 4:50 …

vue el-input 使用 回车键会刷新页面的问题

场景&#xff1a; vue项目中 在输入框输入字符并按下回车键搜索时&#xff0c;不会进行搜索&#xff0c; 而是会刷新页面 原因&#xff1a; 当form表单中只有一个input时&#xff0c;按下回车建会自动触发页面的提交功能&#xff0c; 产生刷新页面的行为 解决&#xff1a; 在…

《Java-SE-第二十九章》之Synchronized原理与JUC常用类

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水平很有限&…

【ChatGPT 指令大全】怎么利用ChatGPT写报告

目录 选定切入角度 报告开头 大纲生成 草稿撰写 研究报告 提出反对观点 报告总结 研究来源 总结 随着人工智能技术的快速发展&#xff0c;自然语言处理技术在各个领域的应用越来越广泛。其中&#xff0c;ChatGPT作为目前最先进的自然语言处理模型之一&#xff0c;其强…

助力618-Y的混沌实践之路 | 京东云技术团队

一、写在前面 1、混沌是什么&#xff1f; 混沌工程&#xff08;Chaos Engineering&#xff09;的概念由 Netflix 在 2010 年提出&#xff0c;通过主动向系统中引入异常状态&#xff0c;并根据系统在各种压力下的行为表现确定优化策略&#xff0c;是保障系统稳定性的新型手段。…

Go语言time库,时间和日期相关的操作方法

time库 用于处理时间、日期和时区的核心库。在实际开发中&#xff0c;常常需要与时间打交道&#xff0c;例如记录日志、处理时间差、计算时间间隔等等。因此&#xff0c;掌握time库的使用方法对于Go开发者来说非常重要。 在Go语言中&#xff0c;时间表示为time.Time类型&…

基于 yolov8 的人体姿态评估

写在前面 工作中遇到&#xff0c;简单整理博文内容为使用预训练模型的一个预测 Demo测试图片来源与网络,如有侵权请告知理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停…

嵌入式开发学习(STC51-15-红外遥控)

内容 使用外部中断功能&#xff0c;使按下红外遥控器&#xff0c;将对应键值编码数据解码后通过数码管显示 红外遥控介绍 红外线简介 人的眼睛能看到的可见光按波长从长到短排列&#xff0c;依次为红、橙、黄、绿、青、蓝、紫&#xff1b; 其中红光的波长范围为 0.62&…