springboot + mybaits plus + js实现简单登录注册首页页面

目录

需求

登录需求

注册需求

目前实现需求

项目依赖技术

项目目录

代码实现

控制器

页面访问请求模块控制器

登录注册请求模块控制器

服务层

接口

实现类

配置层

拦截器配置

MyBaits Plus配置

数据层

Mapper类

数据库设计

 实体类(展示部分)

前端代码

登录注册页面

配置文件

依赖配置文件

界面截图

 总结


需求

登录需求

用户输入邮箱密码后点击登录即可像服务器发送请求,服务端将处理结果发送给客户端,客户端在登录按钮下面显示提示信息

注册需求

用户输入用户名、邮箱、验证码、密码后发送注册请求

目前实现需求

登录注册模块全部完成,可能部分细节没有注意到,且没用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> &lt;!&ndash; 修改版本号 &ndash;&gt;-->
<!--        </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项目的创建和开发流程,增加了自己对于项目开发的经验,也发现了很多不足,希望自己能够更快的熟悉这些流行框架和开发流程

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

决心学java的星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值