【SpringBoot】实现登录功能

news2025/3/14 15:31:26

在上一篇博客中,我们讲解了注册页面的实现。在此基础上会跳转到登录页面,今天给大家带来的是使用 SpringBoot,MyBatis,Html,CSS,JavaScript,前后端交互实现一个登录功能。

目录

一、效果

二、源码

2.1 前端

2.2 后端


一、效果

用户名和密码栏输入空或没有值时,提示错误。

在数据库中有以下信息,任意挑选一条信息进行登录操作。

输入用户 lisi123 后登陆成功 

跳转到个人列表。


二、源码

2.1 前端

前端登陆页面 html 代码,login.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登陆页面</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/login.css">
    <script src="js/jquery.min.js"></script>
</head>

<body>
    <!-- 导航栏 -->
    <div class="nav">
        <img src="img/touxiang.png" alt="">
        <span class="title">随心日记系统</span>
        <!-- 用来占据中间位置 -->
        <span class="spacer"></span>
        <a href="blog_list.html">主页</a>
        <a href="blog_edit.html">写日记</a>
        <a href="login.html">注册</a>
        <!-- <a href="#">注销</a> -->
    </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" onclick="doLogin()">提交</button>
            </div>
        </div>
    </div>
    <script>
        // 登录功能
        function doLogin() {
            // 1.非空校验
            var username = jQuery("#username");
            var password = jQuery("#password");
            if(username.val().trim() == "") {
                alert("请先输入用户名!")
                username.focus();
                return false;
            }
            if(password.val().trim() == "") {
                alert("请输入密码!")
                password.focus();
                return false;
            }
            // 2.将数据提交到后端
            jQuery.ajax({
                url:"/user/login",
                type:"GET",
                data:{
                    "username":username.val(),
                    "password":password.val()
                },
                success:function(ret) {
                    //3.将结果展示给用户
                    if (ret.code == 200 && ret.data == 1 ) {
                        alert("登录成功!");
                        location.href = "myblog_list.html";
                    } else {
                        alert("登录失败!"+ret.msg);
                    }
                }
            });
        }
    </script>
</body>

</html>

登陆页面的样式,login.css

.login-container {
    width: 100%;
    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 {
    padding: 50px 0;
    text-align: center;
}

.login-dialog .row {
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.login-dialog .row span {
    display: block;
    width: 100px;
    font-weight: 700;
}

.login-dialog .row input {
    width: 200px;
    height: 40px;
    line-height: 40px;
    font-size: 24px;
    border-radius: 10px;
    border: none;
    outline: none;
    text-indent: 10px;
}

.login-dialog button {
    width: 300px;
    height: 50px;
    color: white;
    background-color: green;
    border: none;
    border-radius: 10px;
}

.login-dialog button:active {
    background-color: #666;
}

公共样式(注册或登录页面),common.css:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 设置整体页面高度 */
html, body {
    height: 100%;
    background-image: url(../img/cat2.png);
    background-position: center center;
    background-size: cover;
    background-repeat: no-repeat;
}

/* 上方导航栏 */
.nav {
    width: 100%;
    height: 50px;
    background-color: rgba(51, 51, 51, 0.4);
    color: #fff;

    display: flex;
    justify-content: left;
    align-items: center;
}

/* 导航栏中的图标 */
.nav img {
    width: 40px;
    height: 40px;
    margin-left: 30px;
    margin-right: 10px;
    border-radius: 50%;
}

/* 导航栏中的占位器 */
.nav .spacer {
    width: 70%;
}

/* 导航栏中的按钮 */
.nav a {
    color: #fff;
    text-decoration: none;
    padding: 0 10px;
}

/* 页面内容容器, 版心 */
.container {
    /* 使用 calc 计算高度 */
    height: calc(100% - 50px);
    /* 设置版心宽度 */
    width: 1000px;
    /* 水平居中 */
    margin: 0 auto;
    /* 使用弹性布局 */
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* 左侧部分, 用来放置用户信息 */
.container-left {
    height: 100%;
    width: 200px;
}

/* 右侧部分, 用来放置正文 */
.container-right {
    height: 100%;
    /* 和左侧部分中间留出 5px 间隙 */
    width: 795px;
    /* 如果内容溢出就自动加上滚动条 */
    overflow: auto;
    background-color: rgba(255, 255, 255, 0.8);
    border-radius: 10px;
}

/* 展示用户信息的卡片 */
.card {
    background-color: rgba(255, 255, 255, 0.8);
    border-radius: 10px;
    padding: 30px;
}

/* 用户头像 */
.card img {
    width: 140px;
    height: 140px;
    border-radius: 50%;
}

/* 用户名 */
.card h3 {
    text-align: center;
    padding: 10px;
}

/* 用户 github 链接 */
.card a {
    display: block;
    text-align: center;
    color: #999;
    text-decoration: none;
    padding: 10px;
}

/* 展示文章数目的面板 */
.card .counter {
    padding: 5px;
    display: flex;
    justify-content: space-around;
}

2.2 后端

统一返回格式,ResultAjax 类:

/**
 * 统一的返回格式
 */
@Data
public class ResultAjax {
    private int code;
    private String msg;
    private Object data;

    // 成功
    public static ResultAjax success(Object data) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(200);
        resultAjax.setMsg("");
        resultAjax.setData(data);
        return resultAjax;
    }
    public static ResultAjax success(int code, String msg, Object data) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(code);
        resultAjax.setMsg(msg);
        resultAjax.setData(data);
        return resultAjax;
    }

    // 失败
    public static ResultAjax fail(int code, String msg) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(code);
        resultAjax.setMsg(msg);
        return resultAjax;
    }

    public static ResultAjax fail(int code, String msg, Object data) {
        ResultAjax resultAjax = new ResultAjax();
        resultAjax.setCode(code);
        resultAjax.setMsg(msg);
        resultAjax.setData(data);
        return resultAjax;
    }
}

UserMapper 接口:

@Mapper
public interface UserMapper {
    //登录功能
    @Select("select * from userinfo where username=#{username}")
    Userinfo getUserinfoByName(@Param("username") String username);
}

UserService 类:

@Service
public class UserService {

    //注册接口注入进来
    @Autowired
    private UserMapper userMapper;

    //登录功能
    public Userinfo getUserByName(String username) {
        return userMapper.getUserinfoByName(username);
    }
}

UserControler 类:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService; 

   /**
     * 登录接口
     * @param userinfoVO
     * @return
     */
    @RequestMapping("/login")
    public ResultAjax login(UserinfoVO userinfoVO, HttpServletRequest request) {
        // 1.参数校验
        if (userinfoVO == null || !StringUtils.hasLength(userinfoVO.getUsername())
                || !StringUtils.hasLength(userinfoVO.getPassword())) {
            // 非法登录
            return ResultAjax.fail(-1,"非法登录!");
        }
        // 2.根据用户名查询对象,判断用户名是否错误
        Userinfo userinfo = userService.getUserByName(userinfoVO.getUsername());
        if (userinfo == null && userinfo.getId() == 0) {
            return ResultAjax.fail(-2,"账号或密码错误!");
        }
        // 3.使用对象中的密码和输入的密码进行对比,判断密码是否错误
        if (!userinfoVO.getPassword().equals(userinfo.getPassword())) {
            return ResultAjax.fail(-2,"账号或密码错误!");
        }
        // 4.成功后将对象存储到 session 中
        HttpSession session = request.getSession();
        session.setAttribute(ApplicationVariable.SESSION_USERINFO_KEY,userinfo);
        // 5.结果返回给用户
        return ResultAjax.success(1);
    }
}

上述为整个登录功能的核心代码,其中需要注意的是前端需自行映入 jQuery 依赖、在 application.properties 文件中连接数据库、创建对应的数据库。连接数据库,数据库的创建代码在上篇博客中已讲解。


本篇博客到这里就结束了,感谢各位的观看。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图论part3|101.孤岛的总面积、沉没孤岛、417. 太平洋大西洋水流问题

101. 孤岛的总面积 &#x1f517;&#xff1a;101. 孤岛的总面积思路&#xff1a;和昨天的岛的区别是&#xff1a;是否有挨着边的岛屿 所以可以先遍历四条边挨着的岛屿&#xff0c;把他们标记为非孤岛再计算其他岛屿当中的最大面积 代码&#xff1a;&#xff08;深度搜索&…

江科大51单片机笔记【12】AT24C02(I2C总线)

写在前言 此为博主自学江科大51单片机&#xff08;B站&#xff09;的笔记&#xff0c;方便后续重温知识 在后面的章节中&#xff0c;为了防止篇幅过长和易于查找&#xff0c;我把一个小节分成两部分来发&#xff0c;上章节主要是关于本节课的硬件介绍、电路图、原理图等理论知识…

网络安全防护架构有哪些 网络安全防护措施包括

网络安全预防措施 网安措施 计算机网络安全措施主要包括保护网络安全、保护应用服务安全和保护系统安全三个方面&#xff0c;各个方面都要结合考虑安全防护的物理安全、防火墙、信息安全、Web安全、媒体安全等等。 (一)保护网络安全。 网络安全是为保护商务各方网络端系统之…

大模型架构记录5-向量数据库

一 倒排索引、KNN、PQ 1.1 基础版本 query -> requery 对问题做处理&#xff0c;处理上下文 对query 做 refined query 1.2 向量数据库 二 搜索逻辑 2.1 knn 2.2 近似KNN 先和N个空间的均值比较再和空间内部的所有点比较&#xff0c;计算最近值。 优化一&#xff1a; …

Linux:基本指令与内涵理解

1.文件操作指令 1.1 ls ls指令用于查看指定层级文件夹下的文件或文件夹 基本格式&#xff1a;ls (选项) (查看层级&#xff09; 其中选项处不写就默认是显示文件名&#xff0c;查看层级默认是当前层级 选项1&#xff1a; -l 作用&#xff1a;将查找文件的详细信息显示出来 我们…

使用DeepSeek完成一个简单嵌入式开发

开启DeepSeek对话 请帮我使用Altium Designer设计原理图、PCB&#xff0c;使用keil完成代码编写&#xff1b;要求&#xff1a;使用stm32F103RCT6为主控芯片&#xff0c;控制3个流水灯的原理图 这里需要注意&#xff0c;每次DeepSeek的回答都不太一样。 DeepSeek回答 以下是使…

关于我和快速幂的事()

我之前只会这样的(dfs&#xff09;&#xff1a; 不懂下面这种写法的具体逻辑&#xff1a; 看完下面的推理&#xff0c;再转转我聪明的小老戴&#xff1a; 法一中&#xff1a;把2^11看成(2^5)^2 法二中&#xff1a;把2^11看成(2^2)^5

【鸿蒙开发】Hi3861学习笔记- GPIO之直流电机

00. 目录 文章目录 00. 目录01. GPIO概述02. 直流电机概述03. ULN2003模块概述04. 硬件设计05. 软件设计06. 实验现象07. 附录 01. GPIO概述 GPIO&#xff08;General-purpose input/output&#xff09;即通用型输入输出。通常&#xff0c;GPIO控制器通过分组的方式管理所有GP…

mapbox高阶,结合threejs(threebox)添加extrusion挤出几何体,并添加侧面窗户贴图和楼顶贴图,同时添加真实光照投影

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️threebox extrusion挤出几何体1.3 ☘️…

python-leetcode-叶子相似的树

872. 叶子相似的树 - 力扣&#xff08;LeetCode&#xff09; 下面是一个完整的 Python 函数&#xff0c;接收两个二叉树的根节点 root1 和 root2&#xff0c;返回它们是否叶相似。 代码实现 class TreeNode:def __init__(self, val0, leftNone, rightNone):self.val valself…

<03.13>八股文补充知识

import java.lang.reflect.*; public class Main {public static void main(String[] args) throws Exception {// 获取 Class 对象//1. 通过类字面量Class<?> clazz Person.class;//2 通过对象实例化String str "Hello";Class<?> clazz_str str.ge…

2025探索短剧行业新可能报告40+份汇总解读|附PDF下载

原文链接&#xff1a;https://tecdat.cn/?p41043 近年来&#xff0c;短剧以其紧凑的剧情、碎片化的观看体验&#xff0c;迅速吸引了大量用户。百度作为互联网巨头&#xff0c;在短剧领域积极布局。从早期建立行业专属模型冷启动&#xff0c;到如今构建完整的商业生态&#xf…

STM32 内置的通讯协议

数据是以帧为单位发的 USART和UART的区别就是有没有同步功能 同步是两端设备有时钟连接&#xff0c;异步是没时钟连接&#xff0c;靠约定号的频率&#xff08;波特率&#xff09;接收发送数据 RTS和CTS是用来给外界发送已“可接收”或“可发送”信号的&#xff0c;一般用不到…

信息安全访问控制、抗攻击技术、安全体系和评估(高软42)

系列文章目录 信息安全访问控制、抗攻击技术、安全体系和评估 文章目录 系列文章目录前言一、信息安全技术1.访问控制2.抗攻击技术 二、欺骗技术1.ARP欺骗2.DNS欺骗3.IP欺骗 三、抗攻击技术1.端口扫描2.强化TCP/IP堆栈 四、保证体系和评估1.保证体系2.安全风险管理 五、真题在…

晋升系列4:学习方法

每一个成功的人&#xff0c;都是从底层开始打怪&#xff0c;不断的总结经验&#xff0c;一步一步打上来的。在这个过程中需要坚持、总结方法论。 对一件事情长久坚持的人其实比较少&#xff0c;在坚持的人中&#xff0c;不断的总结优化的更少&#xff0c;所以最终达到高级别的…

脑电波控制设备:基于典型相关分析(CCA)的脑机接口频率精准解码方法

文章目录 前言一、CCA的用途二、频率求解思路三、输入数据结构四、判断方法五、matlab实践1.数据集获取及处理2.matlab代码3.运行及结果 六、参考文献 前言 在脑机接口(BCI)领域&#xff0c;有SSVEP方向&#xff0c;中文叫做稳态视觉诱发电位&#xff0c;当人观看闪烁的视觉刺激…

Android Spinner总结

文章目录 Android Spinner总结概述简单使用自定义布局自定义Adapter添加分割线源码下载 Android Spinner总结 概述 在 Android 中&#xff0c;Spinner 是一个下拉选择框。 简单使用 xml布局&#xff1a; <Spinnerandroid:id"id/spinner1"android:layout_width&…

element-ui layout 组件源码分享

layout 布局组件源码分享&#xff0c;主要从以下两个方面&#xff1a; 1、row 组件属性。 2、col 组件属性。 一、row 组件属性。 1.1 gutter 栅栏间隔&#xff0c;类型为 number&#xff0c;默认 0。 1.2 type 布局模式&#xff0c;可选 flex&#xff0c;现代浏览器下有效…

OBJ文件生成PCD文件(python 实现)

代码实现 将 .obj 文件转换为 .pcd&#xff08;点云数据&#xff09; 代码文件。 import open3d as o3d# 加载 .obj 文件 mesh o3d.io.read_triangle_mesh("bunny.obj")# 检查是否成功加载 if not mesh.has_vertices():print("无法加载 .obj 文件&#xff0c…

c++介绍智能指针 十二(1)

普通指针&#xff1a;指向内存区域的地址变量。使用普通指针容易出现一些程序错误。 如果一个指针所指向的内存区域是动态分配的&#xff0c;那么这个指针变量离开了所在的作用域&#xff0c;这块内存也不会自动销毁。动态内存不进行释放就会导致内存泄露。如果一个指针指向已…