目录
需求
登录需求
用户输入邮箱密码后点击登录即可像服务器发送请求,服务端将处理结果发送给客户端,客户端在登录按钮下面显示提示信息
注册需求
用户输入用户名、邮箱、验证码、密码后发送注册请求
目前实现需求
登录注册模块全部完成,可能部分细节没有注意到,且没用js进行实时验证判断,而是在提交请求后服务端进行判断并返回JSON格式信息,首页仅仅实现页面部分布局,使用bootstrap框架
项目依赖技术
Maven:项目管理
SpringBoot:项目框架
MybaitsPlus:数据库操作框架
BootStrap:前端模板框架
项目目录
代码实现
控制器
页面访问请求模块控制器
package com.pstar.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/11 19:20
*/
@Controller
public class SystemController {
//只做系统中页面的访问请求、
/**
* 登录注册页面
* @return
*/
@GetMapping("/login")
public String login() {
return "login";
}
/**
* 忘记密码页面
* @return
*/
@GetMapping("/forgetPassword")
public String forgetPassword() {
return "forgetPassword";
}
/**
* 首页
* @return
*/
@GetMapping("/index")
public String index() {
return "index";
}
/**
* 上传文件案例
* @return
*/
@GetMapping("/upload")
public String upload() {
return "file-upload";
}
}
登录注册请求模块控制器
package com.pstar.controller;
import com.pstar.service.UserServiceImp;
import com.pstar.utils.MailSenderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/8 22:24
*/
@Controller
public class LoginController {
private final UserServiceImp userService;
@Autowired
public LoginController(UserServiceImp userService) {
this.userService = userService;
}
@Autowired
private MailSenderUtil mailSenderUtil;
/**
* 登录请求
* @param email
* @param password
* @param session
* @return
*/
@PostMapping ("doLogin")
@ResponseBody
public Map<String, Object> doLogin(String email, String password, HttpSession session) {
//调用服务层
return userService.login(email, password, session);
}
/**
* 注册请求
* @param username
* @param logon_email
* @param checkCode
* @param logon_password
* @return
*/
@PostMapping("/doRegister")
@ResponseBody
public Map<String, Object> doRegister(String username, String logon_email, String checkCode, String logon_password) {
//调用服务层
return userService.register(logon_email, logon_password, username, checkCode, mailSenderUtil);
}
/**
* 邮箱验证码请求
* @param email
* @return
*/
@PostMapping("/sendCode")
@ResponseBody
public String sendCode(String email) {
if (mailSenderUtil.sendEmailCheckCode(email)) {
return "success";
}
return "fail";
}
@PostMapping("/forgetPassword")
@ResponseBody
public Map<String, Object> forgetPassword(String forget_email, String forget_password, String forget_password_again, String checkCode) {
return userService.forgetPassword(forget_email, forget_password, forget_password_again, checkCode, mailSenderUtil);
}
}
服务层
接口
package com.pstar.service;
import com.pstar.utils.MailSenderUtil;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/9 19:47
*/
@Service
public interface UserService {
/**
* 登录
* @param email
* @param password
* @param session
* @return
*/
Map<String, Object> login(String email, String password, HttpSession session);
/**
* 注册
* @param email
* @param password
* @param username
* @param code
* @return
*/
Map<String, Object> register(String email, String password, String username, String code, MailSenderUtil mailSenderUtil);
/**
* 忘记密码业务
* @param email
* @param firstPassword
* @param secondPassword
* @param code
* @param mailSenderUtil
* @return
*/
Map<String, Object> forgetPassword(String email, String firstPassword, String secondPassword, String code, MailSenderUtil mailSenderUtil);
/**
* 获取登录用户的信息
* @param session
* @return
*/
Map<String, Object> getUserInfo(HttpSession session);
}
实现类
package com.pstar.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pstar.entity.LoginResultEnum;
import com.pstar.entity.User;
import com.pstar.dao.UserMapper;
import com.pstar.entity.UserInfo;
import com.pstar.utils.MailSenderUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/9 19:38
*/
@Service
@RequiredArgsConstructor
public class UserServiceImp extends ServiceImpl<UserMapper, User> implements UserService {
private UserMapper mapper;
@Autowired
public UserServiceImp(UserMapper mapper) {
this.mapper = mapper;
}
/**
* 登录
* @param email
* @param password
* @param session
* @return
*/
@Override
public Map<String, Object> login(String email, String password, HttpSession session) {
Map<String, Object> resultMap = new HashMap<>();
List<User> userList = mapper.selectByEmail(email);
//先判断是否有该用户
if (userList.size() > 0) {
//该用户存在,再看密码是否对
if (userList.get(0).getPassword().equals(password)) {
//如果密码也对,则登录成功
resultMap.put("code", 200);
resultMap.put("message", "登录成功");
session.setAttribute("user", userList.get(0));
} else {
//密码错误
resultMap.put("code", 400);
resultMap.put("message", "用户名或密码错误");
}
} else {
resultMap.put("code", 400);
resultMap.put("message", "该用户未注册");
}
return resultMap;
}
/**
* 忘记密码
* @param email
* @param firstPassword
* @param secondPassword
* @param code
* @return
*/
@Override
public Map<String, Object> forgetPassword(String email, String firstPassword, String secondPassword, String code, MailSenderUtil mailSenderUtil) {
Map<String, Object> resultMap = new HashMap<>();
//是否有空输入
if (email == null || firstPassword == null || secondPassword == null || code == null) {
resultMap.put("code", 400);
resultMap.put("message", "空输入");
return resultMap;
}
//两次密码是否一致
if (!firstPassword.equals(secondPassword)) {
resultMap.put("code", 400);
resultMap.put("message", "两次密码不一致");
return resultMap;
}
//验证码是否正确
if (!mailSenderUtil.getCheckCode().equals(code)) {
resultMap.put("code", 400);
resultMap.put("message", "验证码错误");
return resultMap;
}
//密码是否和之前的重合
if (mapper.selectByEmail(email).get(0).getPassword().equals(firstPassword)) {
resultMap.put("code", 400);
resultMap.put("message", "密码与旧密码重合,请更换密码或前往登录");
return resultMap;
}
//都正确后进行修改
if (mapper.updatePassword(email, firstPassword) > 0) {
resultMap.put("code", 200);
resultMap.put("message", "修改成功");
} else {
resultMap.put("code", 400);
resultMap.put("message", "数据库连接错误,请联系管理员");
}
return resultMap;
}
/**
* 注册
* @param email
* @param password
* @param username
* @return
*/
@Override
public Map<String, Object> register(String email, String password, String username, String code, MailSenderUtil mailSenderUtil) {
Map<String, Object> resultMap = new HashMap<>();
//是否有空输入
if (email.equals("") || password.equals("") || username.equals("") || code.equals("")) {
resultMap.put("code", 400);
resultMap.put("message", "空输入");
}
//邮箱是否已经被注册
else if (mapper.selectByEmail(email).size() > 0) {
resultMap.put("code", 400);
resultMap.put("message", "该用户已注册");
}
//验证码是否正确
else if (!mailSenderUtil.getCheckCode().equals(code)) {
resultMap.put("code", 400);
resultMap.put("message", "验证码错误");
} else {
//都正确执行插入语句
//先插入用户表
//对密码进行加密后存储
// String encodePassword = new BCryptPasswordEncoder().encode(password);
mapper.insertUser(email, password, username);
//再插入用户信息表
//获取当前时间
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String createTime = now.format(formatter);
mapper.insertUserInfo(username, email, createTime);
//最后加上权限表
mapper.insertUserRole(mapper.selectByEmail(email).get(0).getId());
resultMap.put("code", 200);
resultMap.put("message", "注册成功,请登录");
}
return resultMap;
}
/**
* 获取用户信息
* @param session
* @return
*/
@Override
public Map<String, Object> getUserInfo(HttpSession session) {
Map<String, Object> resultMap = new HashMap<>();
// 从session中获取登录用户信息
User user = (User) session.getAttribute("user");
if (user == null) {
resultMap.put("code", 400);
resultMap.put("message", "用户未登录");
} else {
//查询用户
UserInfo userInfo = mapper.selectAllByEmail(user.getEmail());
System.out.println(userInfo);
resultMap.put("code", 200);
resultMap.put("message", "获取用户信息成功");
resultMap.put("userInfo", userInfo);
}
return resultMap;
}
}
配置层
拦截器配置
package com.pstar.config;
import com.pstar.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/15 9:32
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加自定义拦截器,设置拦截路径
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/register");
}
}
MyBaits Plus配置
package com.pstar.config;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/11 15:10
*/
@Configuration
@MapperScan("com.pstar.dao")
public class MyBatisPlusConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("com.pstar.dao");
return configurer;
}
}
数据层
Mapper类
package com.pstar.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pstar.entity.User;
import com.pstar.entity.UserInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/9 19:36
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 查询用户信息
* @param email
* @return
*/
@Select("SELECT * FROM user_info WHERE uemail=#{email}")
UserInfo selectAllByEmail(@Param("email")String email);
/**
* 使用用户名和密码查询
* @param email
* @param password
* @return user
*/
@Select("SELECT * FROM user WHERE email=#{email} AND password=#{password}")
User selectByEmailAndPassword(@Param("email") String email, @Param("password") String password);
/**
* 使用email查询
* @param email
* @return user
*/
@Select("SELECT * FROM user WHERE email=#{email}")
List<User> selectByEmail(@Param("email") String email);
/**
* 使用邮箱查询用户id
* @param email
* @return
*/
@Select("SELECT id FROM user WHERE email=#{email}")
List<User> selectIdByEmail(@Param("email") String email);
/**
* 插入用户表
*
* @param email
* @param password
* @param username
*/
@Insert("INSERT INTO user(email,password,username) VALUES(#{email},#{password},#{username})")
void insertUser(@Param("email")String email, @Param("password")String password, @Param("username")String username);
/**
* 插入用户信息表
* @param username
* @param email
*/
@Insert("INSERT INTO user_info(user_id,uname,uemail,create_time) VALUES((SELECT id FROM user WHERE email=#{email}),#{username},#{email}),#{create_time}")
void insertUserInfo(@Param("username")String username, @Param("email")String email, @Param("create_time")String create_time);
/**
* 插入用户角色表
* @param uid
*/
@Insert("INSERT INTO user_role(uid, rid) VALUES(#{uid} ,2)")
void insertUserRole(@Param("uid")int uid);
@Insert("UPDATE user SET password=#{password} WHERE email=#{email}")
int updatePassword(@Param("email")String email, @Param("password")String password);
}
数据库设计
user:登录用户信息
user_info:用户信息
role:用户权限信息
user_role:用户权限中间表
permission:权限范围信息,每个权限所拥有的的权限范围
role_permission:权限范围中间表
image:图片信息表
comment:评论信息表
column:专栏信息表
activity:活动信息表
album:影集信息表
实体类(展示部分)
User类
package com.pstar.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField("email")
private String email;
@TableField("password")
private String password;
@TableField("username")
private String username;
// getter 和 setter
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", email='" + email + '\'' +
", password='" + password + '\'' +
", username='" + username + '\'' +
'}';
}
}
UserInfo类
package com.pstar.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import javax.persistence.*;
/**
* @author star
* @version 1.0
* @DateTime 2023/5/9 19:11
*/
@Entity
@Table(name = "user_info")
@SuppressWarnings("all")
public class UserInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@TableId(value = "user_id", type = IdType.AUTO)
private Integer userId;
@TableField(value = "uname")
private String uName;
@TableField(value = "uemail")
private String uEmail;
@TableField(value = "uavatar")
private String uAvatar;
@TableField(value = "ugender")
private char uGender;
@TableField(value = "ubirthday")
private String uBirthday;
@TableField(value = "uaddress")
private String uAddress;
@TableField(value = "uphone")
private String uPhone;
@TableField(value = "create_time")
private String uCreateTime;
// getter and setter methods
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getuEmail() {
return uEmail;
}
public void setuEmail(String uEmail) {
this.uEmail = uEmail;
}
public String getuAvatar() {
return uAvatar;
}
public void setuAvatar(String uAvatar) {
this.uAvatar = uAvatar;
}
public char getuGender() {
return uGender;
}
public void setuGender(char uGender) {
this.uGender = uGender;
}
public String getuBirthday() {
return uBirthday;
}
public void setuBirthday(String uBirthday) {
this.uBirthday = uBirthday;
}
public String getuAddress() {
return uAddress;
}
public void setuAddress(String uAddress) {
this.uAddress = uAddress;
}
public String getuPhone() {
return uPhone;
}
public void setuPhone(String uPhone) {
this.uPhone = uPhone;
}
public String getuCreateTime() {
return uCreateTime;
}
public void setuCreateTime(String uCreateTime) {
this.uCreateTime = uCreateTime;
}
@Override
public String toString() {
return "UserInfo{" +
"userId=" + userId +
", uName='" + uName + '\'' +
", uEmail='" + uEmail + '\'' +
", uAvatar='" + uAvatar + '\'' +
", uGender=" + uGender +
", uBirthday='" + uBirthday + '\'' +
", uAddress='" + uAddress + '\'' +
", uPhone='" + uPhone + '\'' +
", uCreateTime='" + uCreateTime + '\'' +
'}';
}
}
UserRole类
package com.pstar.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import javax.persistence.*;
@TableName("user_role")
public class UserRole {
@ManyToOne
@JoinColumn(name = "uid")
private User user;
@ManyToOne
@JoinColumn(name = "rid")
private Role role;
// getters and setters
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
前端代码
备注:登录注册页面是用的B站一个博主发的,忘了是谁,反正不是自己写的,首页是自己写的
登录注册页面
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册登录界面</title>
<link rel="icon" href="/image/ico.png" sizes="32x32" type="image/png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link rel="stylesheet" href="css/login.css">
</head>
<body>
<div class="container right-panel-active">
<!-- 注册 -->
<div class="container_form container--signup">
<form method="post" action="/doRegister" class="form" id="form1" onsubmit="return false;">
<h2 class="form_title">注册</h2>
<input type="text" name="username" id="logon-username" placeholder="用户名" class="input" />
<input type="email" name="logon_email" id="logon-email" placeholder="邮箱" class="input" />
<div class="checkCodeBox">
<div class="checkCodeInputBox">
<input type="text" id="CheckCodeInput" name="checkCode" placeholder=" 验证码" class="checkCodeInput">
</div>
<div class="checkCodeButtonBox">
<input type="button" id="CheckCodeBtn" class="checkCodeBtn" value="获取验证码"></input>
</div>
</div>
<input type="password" name="logon_password" id="logon-password" placeholder="密码" class="input" />
<input class="btn" type="submit" id="logon-button" value="注册">
</form>
</div>
<!-- 登录 -->
<div class="container_form container--signin">
<form method="post" action="/doLogin" class="form" id="form2" onsubmit="return false;">
<h2 class="form_title">登录</h2>
<input type="email" name="email" placeholder="邮箱" class="input" id="login-email" />
<input type="password" name="password" placeholder="密码" class="input" id="login-password"/>
<a href="/forgetPassword" class="link">忘记密码?</a>
<label for="remember"><input type="checkbox" name="remember" id="remember"/>记住我</label>
<input type="submit" class="btn" id="login-button" value="登录">
<p id="errorMsg" style="color: red"></p>
</form>
</div>
<!-- 浮层 -->
<div class="container_overlay">
<div class="overlay">
<div class="overlay_panel overlay--left">
<button class="btn" id="signIn">已有账号,去登录</button>
</div>
<div class="overlay_panel overlay--right">
<button class="btn" id="signUp">没有账号,去注册</button>
</div>
</div>
</div>
</div>
<!-- 背景 -->
<div class="slidershow">
<div class="slidershow--image" style="background-image: url('/image/bg1.jpg')"></div>
<div class="slidershow--image" style="background-image: url('/image/bg2.jpg')"></div>
<div class="slidershow--image" style="background-image: url('/image/bg3.jpg')"></div>
<div class="slidershow--image" style="background-image: url('/image/bg4.jpg')"></div>
</div>
<!-- partial -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="js/login.js"></script>
<script src="js/checkCode.js"></script>
</body>
</html>
CSS
:root {
/* 颜色 */
--white: #e9e9e9;
--gray: #333;
--blue: #095c91;
--blue-r: #315a7491;
--lightblue: #0393a3;
/* 圆角 */
--button-radius: 0.7rem;
/* 大小 */
--max-width: 758px;
--max-height: 420px;
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
body {
align-items: center;
background-color: var(--white);
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
display: grid;
height: 100vh;
place-items: center;
}
.form_title {
font-weight: 300;
margin: 0;
margin-bottom: 1.25rem;
}
.link {
color: var(--gray);
font-size: 0.9rem;
margin: 1.5rem 0;
text-decoration: none;
}
.container {
background-color: var(--white);
border-radius: var(--button-radius);
box-shadow: 0 0.9rem 1.7rem rgba(0, 0, 0, 0.25),
0 0.7rem 0.7rem rgba(0, 0, 0, 0.22);
height: var(--max-height);
max-width: var(--max-width);
overflow: hidden;
position: relative;
width: 100%;
}
.container_form {
height: 100%;
position: absolute;
top: 0;
transition: all 0.6s ease-in-out;
}
.container--signin {
left: 0;
width: 50%;
z-index: 5;
}
.container.right-panel-active .container--signin {
transform: translateX(100%);
}
.container--signup {
left: 0;
opacity: 0;
width: 50%;
z-index: 4;
}
.container.right-panel-active .container--signup {
-webkit-animation: show 0.6s;
animation: show 0.6s;
opacity: 1;
transform: translateX(100%);
z-index: 8;
}
.container_overlay {
height: 100%;
left: 50%;
overflow: hidden;
position: absolute;
top: 0;
transition: transform 0.6s ease-in-out;
width: 50%;
z-index: 100;
}
.container.right-panel-active .container_overlay {
transform: translateX(-100%);
}
.overlay {
background-color: rgba(255, 255, 255, 0.25);
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
left: -100%;
position: relative;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
width: 200%;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay_panel {
align-items: center;
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
position: absolute;
text-align: center;
top: 0;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
width: 50%;
}
.overlay--left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay--left {
transform: translateX(0);
}
.overlay--right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay--right {
transform: translateX(20%);
}
.btn {
background-color: var(--blue);
background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);
border-radius: 20px;
border: 0.2px solid var(--blue-r);
color: var(--white);
cursor: pointer;
font-size: 0.8rem;
font-weight: bold;
letter-spacing: 0.1rem;
padding: 0.9rem 4rem;
text-transform: uppercase;
transition: transform 80ms ease-in;
}
.form > .btn {
margin-top: 1.5rem;
}
.btn:active {
transform: scale(0.95);
}
.btn:focus {
outline: none;
}
.form {
background-color: var(--white);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 3rem;
height: 100%;
text-align: center;
}
.input {
background-color: #fff;
border: none;
padding: 0.9rem 0.9rem;
margin: 0.5rem 0;
width: 100%;
}
/* 注册验证码部分 */
.checkCodeBox {
display: flex;
align-items: center;
width: 313px;
justify-content: space-between;
margin: 10px auto 10px -13px ;
}
.checkCodeInput {
width: 170px;
height: 43px;
background-color: #fff;
border: none;
vertical-align: middle;
font-size: 16px;
}
.checkCodeButtonBox {
margin-right: 0px;
}
.checkCodeBtn {
height: 43px;
background-color: #fff;
border-width: 2px;
border-style: solid;
border-image: linear-gradient(to right, #4ec2cf, #c53032) 1;
color: rgb(117, 117, 117);
transition: all 1s ease-in-out;
}
.checkCodeBtn:hover {
background: linear-gradient(to bottom right, #4ec2cf, #c53032);
color: #fff;
}
@-webkit-keyframes show {
0%,
49.99% {
opacity: 0;
z-index: 4;
}
50%,
100% {
opacity: 1;
z-index: 8;
}
}
@keyframes show {
0%,
49.99% {
opacity: 0;
z-index: 4;
}
50%,
100% {
opacity: 1;
z-index: 8;
}
}
.slidershow {
position: absolute;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.slidershow--image {
position: absolute;
width: 100%;
height: 100%;
background: no-repeat 50% 50%;
background-size: cover;
-webkit-animation-name: kenburns;
animation-name: kenburns;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-duration: 16s;
animation-duration: 16s;
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
.slidershow--image:nth-child(1) {
-webkit-animation-name: kenburns-1;
animation-name: kenburns-1;
z-index: 3;
}
.slidershow--image:nth-child(2) {
-webkit-animation-name: kenburns-2;
animation-name: kenburns-2;
z-index: 2;
}
.slidershow--image:nth-child(3) {
-webkit-animation-name: kenburns-3;
animation-name: kenburns-3;
z-index: 1;
}
.slidershow--image:nth-child(4) {
-webkit-animation-name: kenburns-4;
animation-name: kenburns-4;
z-index: 0;
}
@-webkit-keyframes kenburns-1 {
0% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
1.5625% {
opacity: 1;
}
23.4375% {
opacity: 1;
}
26.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
98.4375% {
opacity: 0;
-webkit-transform: scale(1.21176);
transform: scale(1.21176);
}
100% {
opacity: 1;
}
}
@keyframes kenburns-1 {
0% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
1.5625% {
opacity: 1;
}
23.4375% {
opacity: 1;
}
26.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
98.4375% {
opacity: 0;
-webkit-transform: scale(1.21176);
transform: scale(1.21176);
}
100% {
opacity: 1;
}
}
@-webkit-keyframes kenburns-2 {
23.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
26.5625% {
opacity: 1;
}
48.4375% {
opacity: 1;
}
51.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
}
@keyframes kenburns-2 {
23.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
26.5625% {
opacity: 1;
}
48.4375% {
opacity: 1;
}
51.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
}
@-webkit-keyframes kenburns-3 {
48.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
51.5625% {
opacity: 1;
}
73.4375% {
opacity: 1;
}
76.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
}
@keyframes kenburns-3 {
48.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
51.5625% {
opacity: 1;
}
73.4375% {
opacity: 1;
}
76.5625% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
100% {
opacity: 0;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
}
@-webkit-keyframes kenburns-4 {
73.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
76.5625% {
opacity: 1;
}
98.4375% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
}
@keyframes kenburns-4 {
73.4375% {
opacity: 1;
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
76.5625% {
opacity: 1;
}
98.4375% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
}
/**
注册验证码样式
*/
.verification {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
display: none;
width: 200px;
height: 100px;
background-color: white;
border: 1px solid gray;
}
JS
const signInBtn = document.getElementById("signIn");
const signUpBtn = document.getElementById("signUp");
const firstForm = document.getElementById("form1");
const secondForm = document.getElementById("form2");
const container = document.querySelector(".container");
signInBtn.addEventListener("click", () => {
container.classList.remove("right-panel-active");
});
signUpBtn.addEventListener("click", () => {
container.classList.add("right-panel-active");
});
firstForm.addEventListener("submit", (e) => e.preventDefault());
secondForm.addEventListener("submit", (e) => e.preventDefault());
/**
* 记住我功能
*/
$(document).ready(function() {
// 获取表单元素
const loginForm = document.getElementById("form2");
// 获取 checkbox 元素
const checkbox = document.getElementById("remember");
// 获取登录邮箱和密码输入框元素
const loginEmail = document.getElementById("login-email");
const loginPassword = document.getElementById("login-password");
// 检查是否存在 cookie
if (document.cookie.includes("login-email") && document.cookie.includes("login-password")) {
// 解码 cookie 值,避免特殊字符影响值的获取
const email = decodeURIComponent(getCookie("login-email"));
const password = decodeURIComponent(getCookie("login-password"));
// 将 cookie 值填充到表单中
loginEmail.value = email;
loginPassword.value = password;
// 将 checkbox 标记为选中状态
checkbox.checked = true;
}
// 更新 cookie 值
loginForm.addEventListener('submit', function () {
if (checkbox.checked) {
// 获取邮箱和密码的值,编码后设置为 cookie
const email = encodeURIComponent(loginEmail.value);
const password = encodeURIComponent(loginPassword.value);
// 设置 cookie,包括 SameSite 属性以保护 cookie 免受 CSRF 攻击的影响
setCookie("login-email", email, 5, "strict");
setCookie("login-password", password, 5, "strict");
} else {
// 删除 cookie,包括 SameSite 和 secure 属性以确保删除的是正确的 cookie
deleteCookie("login-email", "strict", true);
deleteCookie("login-password", "strict", true);
}
})
// 设置 cookie
function setCookie(name, value, days, samesite = "none", secure = true) {
// 计算 cookie 过期时间
const expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
// 构造 cookie 字符串,包括过期时间、路径和 SameSite 属性
let cookieString = `${name}=${value};expires=${expires};path=/;samesite=${samesite};`;
// 如果是 https 协议,则添加 secure 属性
if (secure) {
cookieString += "secure;";
}
// 设置 cookie
document.cookie = cookieString;
}
// 获取 cookie
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) {
return parts.pop().split(";").shift();
}
}
// 删除 cookie
function deleteCookie(name, samesite = "lax", secure = false) {
// 设置 cookie 的过期时间为过去的一个时间戳,以删除 cookie
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; samesite=${samesite}; ${
secure ? "secure;" : ""
}`;
}
});
/**
* 注册业务逻辑处理
*/
$(document).ready(function() {
// 注册按钮点击事件
$("#logon-button").click(function(e) {
e.preventDefault();//阻止表单默认提交行为
const email = $("#logon-email").val();
const password = $("#logon-password").val();
const username = $("#logon-username").val();
const checkCode = $("#CheckCodeInput").val();
$.ajax({
url: "doRegister",
type: "POST",
data: {
username: username,
logon_email: email,
checkCode: checkCode,
logon_password: password
},
dataType: "json",
success: function(result) {
if (result.code === 200) { // 注册成功
alert(result.message);
window.location.href = "/login";
} else { // 注册错误提醒
alert(result.message);
}
},
error: function (result) {
alert(result.message);
}
});
});
});
/**
* 登录业务逻辑处理
*/
$(document).ready(function() {
// 登录按钮点击事件
$("#login-button").click(function(e) {
e.preventDefault();//阻止表单默认提交行为
const email = $("#login-email").val();
const password = $("#login-password").val();
$.ajax({
url: "doLogin",
type: "POST",
data: {
email: email,
password: password
},
dataType: "json",
success: function(result) {
if (result.code === 200) { // 登录成功
$("#errorMsg").hide();
window.location.href = "/index";
} else { // 登录失败
$("#errorMsg").text(result.message);
}
},
error: function (result) {
$("#errorMsg").text("登录失败,请稍后再试");
}
});
});
});
首页和忘记密码部分的就不放了,不然篇幅太长
配置文件
# MyBaits plus
spring.datasource.url=jdbc:mysql://localhost:3306/pstar?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=fanxing0203
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis-Plus??
mybatis-plus.mapper-locations=com.pstar.dao/*.xml
mybatis-plus.type-aliases-package=com.pstar.dao
#qq授权码 qqgrpuzmnmbddejg
#email check code
# SMTP 邮件发送协议
spring.mail.protocol=smtp
# SMTP 邮件发送服务器主机名或 IP
spring.mail.host=smtp.qq.com
# SMTP 邮件发送服务器端口号
spring.mail.port=587
# 邮件发送人账户
spring.mail.username=pstar03@qq.com
# 邮件发送人密码,生成的授权码
spring.mail.password=qqgrpuzmnmbddejg
#编码方式
spring.mail.default-encoding=utf-8
# 开启 SMTP 认证
spring.mail.properties.mail.smtp.auth=true
# 开启 STARTTLS 加密
spring.mail.properties.mail.smtp.starttls.enable=true
## SMTP 连接超时时间
#spring.mail.properties.mail.smtp.connectiontimeout=5000
## SMTP 超时时间
#spring.mail.properties.mail.smtp.timeout=5000
## SMTP 响应超时时间
#spring.mail.properties.mail.smtp.writetimeout=5000
#Redis
spring.redis.database=3
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.poolmax-active=8
spring.redis.jedis.poolmax-wait=-1
spring.redis.jedis.poolmax-idle=8
spring.redis.jedis.poolmin-idle=0
spring.redis.timeout=60s
有些是课上的时候跟老师写案例用的,实际项目没有用到
依赖配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>PStar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>PStar</name>
<description>PStar</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.data</groupId>-->
<!-- <artifactId>spring-data-jpa</artifactId>-->
<!-- <version>2.5.3</version> <!– 修改版本号 –>-->
<!-- </dependency>-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 邮箱验证依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<!-- 随机验证码依赖-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- 日志文件依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
界面截图
总结
这学期学习了MVC框架课,学习之后自己做的一个小案例,做的不好,希望大家多多包涵。
从中了解到了Maven + springboot项目的创建和开发流程,增加了自己对于项目开发的经验,也发现了很多不足,希望自己能够更快的熟悉这些流行框架和开发流程