文章目录

  • 数据库
    • 数据库设计
    • 配置 MyBatis
      • 1. Spring 配置
      • 2. 创建实体类
      • 3. 创建 Mapper 接口
      • 4. 使用 MyBatis
  • 约定前后端交互接口
    • 登录接口
    • 注册接口
    • 获取用户信息
  • 服务器开发
    • login
    • register
    • getUserInfo
    • 完整代码

数据库

数据库设计

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

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

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

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 的配置文件,使用数据库可以被连接上

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. 创建实体类

创建一个实体类:用户

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 接口

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

4. 使用 MyBatis

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

实现 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">  
<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 匹配
    • 匹配:登陆成功
    • 不匹配:登录失败
@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

@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

@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();  }  
}

完整代码

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/84691.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/84691.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/84691.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt/C++学习系列之列表使用记录

Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件&#xff0c;同步使用QTableWidgetItem进行单元格的设置&#xff0c;最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…

防火墙通常可以分为哪些类型?

防火墙是目前保护网络安全的重要设备&#xff0c;能够通过监控、过滤和控制进出网络的数据流量&#xff0c;来保护内部网络不会受到未经授权的IP地址进行访问和恶意的网络威胁&#xff0c;设置防火墙能够帮助企业确保网络的安全性&#xff0c;同时防火墙也会根据不同的功能来划…

基于GeoTools的道路相交多个点容差冗余计算实战

目录 前言 一、关于道路相交 1、相交四个点 2、点更多的情况 二、基于距离的相交点去重 1、冗余距离计算 2、调用过程 3、去重后的结果 三、总结 前言 在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;道路网络数据的处理与分析一直是关键课题。随着城市化进…

android:foregroundServiceType详解

在 Android 中&#xff0c;foregroundServiceType 是用于声明前台服务类型的属性&#xff0c;主要从 Android 10&#xff08;API 29&#xff09;开始引入&#xff0c;并在 Android 11&#xff08;API 30&#xff09;及更高版本 中进一步细化。以下是所有可用的 foregroundServi…

React+Taro 微信小程序做一个页面,背景图需贴手机屏幕最上边覆盖展示

话不多说 直接上图 第一步 import { getSystemInfoSync } from tarojs/taro;第二步 render() {const cardBanner getImageUrlByGlobal(member-merge-bg.png);const { safeArea, statusBarHeight } getSystemInfoSync();const NAV_BAR_HEIGHT 44;const navBarHeight NAV…

从零开始的云计算生活——番外,实战脚本。

目录 题目一&#xff1a;系统信息收集脚本 题目二&#xff1a;用户管理配置脚本 题目三&#xff1a;磁盘空间管理脚本 题目四&#xff1a;网络配置检查脚本 题目五&#xff1a;系统日志分析脚本 题目一&#xff1a;系统信息收集脚本 编写一个脚本名为 collect_system_info…

MySQL基础知识(DDL、DML)

什么是数据库&#xff1f; 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 注释&#xff1a; 单行注释&#xff1a;-- 注释内容 或 # 注释内容(MySQL特有)多行注释&#xff1a; /* 注释内容 */ 分类 SQL语句根据其功能被分为…

用volatile修饰数组代表什么意思,Java

文章目录 volatile 修饰数组引用的含义volatile 对数组元素无效总结 如何让数组元素也具有 volatile 特性&#xff1f; 当用 volatile 关键字修饰一个数组时&#xff0c;它只保证数组引用的可见性和部分原子性&#xff0c;而不保证数组元素的可见性和原子性。 换句话说&#x…

Ubuntu 24.04 LTS 长期支持版发布:对服务器用户意味着什么?新特性、升级建议与性能影响初探

更多云服务器知识&#xff0c;尽在hostol.com 在服务器运维的广阔世界里&#xff0c;每一次主流操作系统长期支持&#xff08;LTS&#xff09;版本的发布&#xff0c;都无异于一次重要的“时代交替”。它不仅带来了一系列令人瞩目的技术革新&#xff0c;更重要的是&#xff0c…

题目 3241: 蓝桥杯2024年第十五届省赛真题-挖矿

题目 3241: 蓝桥杯2024年第十五届省赛真题-挖矿 时间限制: 3s 内存限制: 512MB 提交: 1267 解决: 224 题目描述 小蓝正在数轴上挖矿&#xff0c;数轴上一共有 n 个矿洞&#xff0c;第 i 个矿洞的坐标为 ai 。小蓝从 0 出发&#xff0c;每次可以向左或向右移动 1 的距离&#xf…

vue3+ts+vite创建的后台管理系统笔记

Vue3+ Vite + Element-Plus + TypeScript 从0到1搭建企业级后台管理系统(前后端开源):参考有来科技学习搭建项目 创建项目bug汇总,知识点src 路径别名配置和tsconfig.json文件报错【这个不配置好,会引起其他页面引用时报错:见--整合 Pinia】:整合 Pinia 【参考-- src 路径…

指针01 day13

十三&#xff1a;指针变量 一&#xff1a;数据类型 ​ 指针类型---------对应处理的数据是指针 (地址)这种数据 ​ 整型类型---------对应处理的数据是整数这种类型 二&#xff1a;定义指针类型的变量 ​ 语法&#xff1a; 基类型&#xff08;1&#xff09; *&#xff08;…

基于深度学习的智能文本生成:从模型到应用

前言 随着人工智能技术的飞速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域取得了显著的进展。其中&#xff0c;智能文本生成技术尤其引人注目。从聊天机器人到内容创作&#xff0c;智能文本生成不仅能够提高效率&#xff0c;还能创造出令人惊叹的内容。本文将…

Oracle业务用户的存储过程个数及行数统计

Oracle业务用户的存储过程个数及行数统计 统计所有业务用户存储过程的个数独立定义的存储过程定义在包里的存储过程统计所有业务用户存储过程的总行数独立定义的存储过程定义在包里的存储过程通过DBA_SOURCE统计类型个数和代码行数📖 对存储过程进行统计主要用到以下三个系统…

多线程安全:核心解决方案全解析

在多线程环境下保证共享变量的线程安全,需解决原子性、可见性、有序性三大问题。以下是核心解决方案及适用场景: 一、同步锁机制(互斥访问) synchronized 关键字 原理:通过 JVM 监视器锁(Monitor)确保同一时间仅一个线程访问临界区。示例:public class Counter {privat…

2025-06-01-Hive 技术及应用介绍

Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具&#xff0c;它为海量结构化数据提供类 SQL 的查询能力&#xf…

Python爬虫(52)Scrapy-Redis分布式爬虫架构实战:IP代理池深度集成与跨地域数据采集

目录 一、引言&#xff1a;当爬虫遭遇"地域封锁"二、背景解析&#xff1a;分布式爬虫的两大技术挑战1. 传统Scrapy架构的局限性2. 地域限制的三种典型表现 三、架构设计&#xff1a;Scrapy-Redis 代理池的协同机制1. 分布式架构拓扑图2. 核心组件协同流程 四、技术实…

HashMap真面目

背景 今天数据采集项目碰到一个性能问题&#xff0c;3000多个采集点&#xff0c;每一个采集点每秒送一个数据&#xff0c;接收到数据之后首先需要内存中做缓存&#xff0c;之后有一系列的业务分析处理&#xff0c;所以&#xff0c;对系统性能要求比较高。 最近几天发现服务器…

STM32CubeMX-H7-19-ESP8266通信(中)--单片机控制ESP8266实现TCP地址通信

前言 上篇文章我们已经能够使用串口助手实现esp8266的几种通信&#xff0c;接下来我们使用单片机控制实现。这篇文章会附带教程&#xff0c;增加.c和,.h&#xff0c;把串口和定时器放到对应的编号&#xff0c;然后调用初始化就可以使用了。 先讲解&#xff0c;然后末尾再放源码…

欧盟RED网络安全标准EN 18031-2的要求

欧盟RED网络安全标准EN 18031-2的要求 欧盟RED网络安全标准EN 18031-2的要求 ​ 适用产品范围&#xff1a; 能够处理个人隐私数据的可联网无线电设备。 不具备联网能力的三类无线电设备&#xff1a;玩具、儿童护理类设备、可穿戴类设备。 主要测试与评估内容&#xff1a; EN…