用户模块
完成注册登录,以及用户分数管理~使用数据库来保存上述用户信息.
使用 MyBatis来连接并操作数据库了
主要步骤:
1.修改 Spring的配置文件,使数据库可以被连接上.
2.创建实体类,用户, User
3.创建Mapper接口~
4.实现MyBatis 的相关xml配置文件,来自动的实现数据库操作
修改Spring的配置文件
将application.properties重命名为application.yml, 粘贴代码
yml代码:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/java_gobang?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: 密码
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
logging:
pattern:
console: "[%-5level] - %msg%n"
创建数据库
创建数据库并且插入数据
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, '张雨潇', '123', 1000, 0, 0);
insert into user values (null, '李明', 'password1', 1200, 10, 6);
insert into user values (null, '王芳', 'password2', 1100, 8, 4);
insert into user values (null, '刘强', 'password3', 950, 12, 5);
insert into user values (null, '赵静', 'password4', 980, 7, 3);
insert into user values (null, '孙鹏', 'password5', 1050, 11, 7);
insert into user values (null, '周丽', 'password6', 1020, 9, 4);
insert into user values (null, '郑凯', 'password7', 1150, 15, 8);
insert into user values (null, '何敏', 'password8', 990, 10, 5);
insert into user values (null, '吴昊', 'password9', 1080, 13, 6);
insert into user values (null, '陈晓', 'password10', 930, 8, 3);
insert into user values (null, '杨洋', 'password11', 1120, 14, 9);
insert into user values (null, '林静', 'password12', 1040, 11, 6);
insert into user values (null, '张伟', 'password13', 950, 7, 2);
insert into user values (null, '刘畅', 'password14', 1070, 12, 7);
insert into user values (null, '宋雨', 'password15', 990, 9, 4);
insert into user values (null, '唐鹏', 'password16', 1010, 10, 5);
insert into user values (null, '许娟', 'password17', 920, 6, 2);
insert into user values (null, '高飞', 'password18', 960, 8, 3);
insert into user values (null, '钟丽', 'password19', 980, 7, 3);
insert into user values (null, '魏强', 'password20', 1100, 10, 5);
命令行运行即可
约定前后端交互接口
登录接口:
- 请求:
POST /login 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 }
如果登录失败,返回一个无效的用户对象,每个属性为空或为默认值,例如
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 }
编写用户实体
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;
}
}
创建Mapper接口
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="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>
</mapper>
UserMapper
package com.example.java_gobang.model;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
//插入一个用户, 用于注册功能
void insert(User user);
//根据用户名, 来查询用户的详细信息, 用于登录
User selectByName(String username);
}
UserAPI
package com.example.java_gobang.api;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
public class UserAPI {
@Autowired
private UserMapper userMapper;
@PostMapping("/login")
@ResponseBody
public Object login(String username, String password, HttpServletRequest request) {
//关键操作: 根据username去数据库查询
// 如果能找到匹配的用户并且密码一致, 就确认为登陆成功
User user = userMapper.selectByName(username);
if (user == null || !user.getPassword().equals(password)) {
return new User(); //这是空对象 说明登录失败
}
//这里的true表示如果会话存在, 那么返回session, 不存在创建一个新的会话返回
HttpSession httpSession = request.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);
//天梯分数新手默认1200
user.setScore(1200);
user.setWinCount(0);
user.setTotalCount(0);
userMapper.insert(user);
return user;
} catch (org.springframework.dao.DuplicateKeyException e) {
//key重复异常
User user = new User();
return user;
}
}
@PostMapping("/userInfo")
@ResponseBody
public Object getUserInfo(HttpServletRequest request) {
try {
HttpSession httpSession = request.getSession(false);
User user = (User) httpSession.getAttribute("user");
return user;
} catch (NullPointerException e) {
return new User();
}
}
}
其中有登录, 注册, 查询用户信息的方法
其中
@PostMapping("/register")
:映射HTTP POST请求到/register
路径。
会话机制讲解
request.getSession(true)
- 功能:
getSession(true)
方法会检查当前请求是否已经有一个会话。如果有,会返回这个会话。如果没有,它会创建一个新的会话并返回。- 参数
true
:表示如果没有现有的会话,创建一个新的会话。
HttpSession
- 会话对象:
HttpSession
是一个接口,提供了一种在多个请求中标识用户的方法,并且能够存储用户会话期间的信息。典型的用法包括存储用户的登录状态、购物车内容等。
httpSession.setAttribute("user", user)
- 设置属性:
setAttribute
方法用于在会话中存储一个键值对。这里的键是"user"
,值是用户对象user
。- 作用:将当前登录的用户信息存储到会话中,以便在后续的请求中可以方便地获取到用户信息。
登录注册的前端页面
登录的html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</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>
<!-- 提交按钮 -->
<button id="submit">提交</button>
</div>
</div>
</body>
</html>
common.css和login.css
/* 公共的样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 设置图片能够覆盖全部窗口 */
html, body {
height: 100%;
background-image: url(../image/background.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.nav {
height: 50px;
background-color: rgb(50, 50, 50);
color: aliceblue;
line-height: 50px;
padding-left: 20px;
}
login.css
.login-container {
height: calc(100% - 50px);
display: flex;
justify-content: center;
align-items: center;
}
.login-dialog {
width: 400px;
height: 400px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 10px;
}
/* 标题 */
.login-dialog h3 {
text-align: center;
padding: 50px 0;
}
/* 针对一行设置样式 */
.login-dialog .row {
width: 100%;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.login-dialog .row span {
width: 100px;
font-weight: 700;
}
#username, #password {
width: 200px;
height: 40px;
font-size: 20px;
line-height: 40px;
padding-left: 10px;
border: none;
outline: none;
border-radius: 10px;
}
.button-container {
display: flex;
justify-content: center;
}
#submit {
width: 300px;
height: 50px;
background-color: rgb(0, 128, 0);
color: white;
border: none;
outline: none;
border-radius: 10px;
margin-top: 20px;
}
#submit:active {
background-color: #666;
}
/* 公共的样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 设置图片能够覆盖全部窗口 */
html, body {
height: 100%;
background-image: url(../image/background.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.nav {
height: 50px;
background-color: rgb(50, 50, 50);
color: aliceblue;
line-height: 50px;
padding-left: 20px;
}
引入jQuery
百度搜索 jQuery cdn
比如使用字节的
https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/1.7.2/jquery.min.js
全选保存
引入:
<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() {
// 禁用提交按钮,避免重复提交
submitButton.disabled = true;
$.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("登录失败!");
},
complete: function() {
//AJAX请求完成后重新启用按钮
submitButton.disabled = false;
}
});
}
</script>
验证登录页面
启动服务器
访问 http://127.0.0.1:8080/login.html
注册样式
与登录大差不差
<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代码
<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() {
// 禁用提交按钮,避免重复提交
submitButton.disabled = true;
$.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("注册失败!");
},
complete: function() {
//AJAX请求完成后重新启用按钮
submitButton.disabled = false;
}
});
}
</script>