5.登录功能的开发

news2024/9/28 3:24:50

登录功能的开发

  • 一、前端
    • 1.1首页跳转到登录页面
    • 1.2登录界面处理
  • 二、后端
    • 2.1创建User实体类
    • 2.2创建UserDto类
    • 2.3创建UserServlet类
  • 三、效果演示
  • 四、轻提示组件

一、前端

1.1首页跳转到登录页面

登录页面是一个单独的页面,我们需要从项目的首页跳转到登录页面。具体实现非常简单,在首页的登录按钮添加点击事件就可以。

    <button id="loginBtn" class="btn btn-danger" type="button" onclick="location.href='user-login.html'"
            style="display: block;">
        登录
    </button>

在登录的标签中添加点击事件,其中location.href是 window.location 对象的一个属性。为它赋值可以使浏览器导航到指定的 URL 地址,在这里点击登录后,让浏览器导航到我们的登录界面。

1.2登录界面处理

在登录页面主要包含用户名和密码,以及登录按钮,其余皆为次要不需要设计。在这里我们需要对输入的登录信息进行处理,主要是点击登录后,将数据返回给后端进行处理,根据相应判断登录成功与否。
为登录按钮添加点击事件响应:

       <div class="mb-3 row px-5">
            <label class="col-2 col-form-label"></label>
            <div class="col-10">
                <button onclick="login()" type="button" class="form-control btn btn-danger btn-lg">登录</button>
            </div>
        </div>

点击按钮,调用login函数进行数据的处理。
下一步实现login函数:

       const login = async () => {
        const u_id = document.querySelector("#u_id").value;
        const u_pwd = document.querySelector("#u_pwd").value;
        if (u_id === "" || u_pwd === "") {
            
            console.log("错误", "账号或密码 不能为空!");
            return;
        }
        const loginObj={
            u_id:u_id,
            u_pwd:u_pwd
        }
        const url = "./user/login";
        //发送POST请求
        const req = await fetch(url, {
            method: "POST",
            headers: {'Content-Type': 'application/json'},//内容类型
            body: JSON.stringify(loginObj)//发送的请求体是json格式的字符串
        });
        if (req.ok) {
            const result = await req.json();
            console.log(result);
            if(result.success){
                
                console.log('成功',"登录成功");
                //延迟执行函数
                setTimeout(()=>{
                    location.href=`index.html`;
                },1200);
            }else{
                console.log('失败',result.message);
            }
        } else {
            console.log(`响应错误!错误代码:${req.status}`);
        }
    }

async说明这是一个有异步操作的函数,之前的内容有提到,这里不再复述。
定义两个变量用来存我们网页输入的登录信息,并进行判空处理,控制台打印输出信息,方便我们后期进行调试,
创建一个对象,用来将两个数据存入对象中,用来向后端发送。
创建变量用来存储路径,存储发送POST请求的路径
使用fetch函数向后端发起请求,可能你们会注意到这里的fetch函数的写法和之前的不同,在这里fetch函数我们定义了请求体.
method: "POST" 表示这是一个 POST 请求方法,是 POST类型,所以在这里我们向后端发送的是POST请求,而之前的我们没有定义请求体,它默认的是GET请求。
headers: {'Content-Type': 'application/json'} 设置了请求头中的 Content-Type 为 application/json,表明请求体的数据格式为 JSON 。
body: JSON.stringify(loginObj) 将一个名为 loginObj 的对象转换为 JSON 格式的字符串,并作为请求体发送。

返回响应的处理:
if (req.ok):检查响应是否成功(一般状态码在是200)。
const result = await req.json();:将响应体解析为 JSON 格式,并将结果存储在 result 变量中。
如果 result.success 为真,表示登录成功,会在 1200 毫秒后跳回到 index.html 页面。
如果 result.success 为假,会在控制台输出登录失败的消息 result.message 。
如果响应不成功(req.ok 为假),会在控制台输出响应错误的代码 req.status 。

到这里,关于前端的开发基本就完成了,接下来要实现后端的功能逻辑,来支持前端。

二、后端

2.1创建User实体类

创建User实体类,用来存放从数据库中查询回来的数据结果,用于返送给前端作为数据显示。
包含信息:用户名和昵称。
代码:

public class User {
    private String u_id;
    private String u_nickname;


    public String getU_id() {
        return u_id;
    }

    public void setU_id(String u_id) {
        this.u_id = u_id;
    }

    public String getU_nickname() {
        return u_nickname;
    }

    public void setU_nickname(String u_nickname) {
        this.u_nickname = u_nickname;
    }

}

一个简单的实体类,不多叙述。

2.2创建UserDto类

创建UserDto类,用来存放从前端发送过来的登录信息,用来从数据库中进行信息的查询。
包含对应的登录信息:用户名和密码
代码:

public class UserDto {
    private String u_id;
    private String u_pwd;

    public String getU_id() {
        return u_id;
    }

    public void setU_id(String u_id) {
        this.u_id = u_id;
    }

    public String getU_pwd() {
        return u_pwd;
    }

    public void setU_pwd(String u_pwd) {
        this.u_pwd = u_pwd;
    }
}

同理不多叙述。
接下来是核心的数据处理。

2.3创建UserServlet类

创建UserServlet类,用来处理前端返回的数据,查询数据发送往前端。
使用注解定义路径:

@WebServlet({
        "/user/login"
})

同理这个类一样继承了HttpServlet,重写doGet和doPost方法:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String path = req.getServletPath();
        System.out.println("Content-Type:" + req.getContentType());
        switch (path) {
            case "/user/login":
                userLogin(req, resp);
                break;
        }
    }

可能有些人是和我写的是相反的,是在doPost方法里面调用doGet方法,最后代码一样能跑,可能会有疑问(其实是我一开始没想明白,哈哈哈)。
其实这个地方都是对前端发起请求的处理,无论那种写法,最后都会运行核心的数据处理代码,无非是一个直接处理请求调用数据处理方法,另一个处理请求在调用另一位请求处理的方法在调用数据处理的方法。可能我说的有点抽象。试着举一个列子就容易理解了。
通过请求处理最终会进行路径的判断,根据req.getServletPath()获取的不同路径执行不同的方法,当然目前这里只有一个路径。最后调用userLogin方法。
所以下一步:
创建userLogin方法,实现数据的处理。

private void userLogin(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        UserDto loginUser = MyWeb.getBeanFromRequest4Json(UserDto.class, req);
        String sql = "select * from t_user where u_id = ? and u_pwd = ?";
        User user = DaoCreater.currentDao().queryUniqueBean(User.class, sql, loginUser.getU_id(), loginUser.getU_pwd());
        if (user != null) {
            //将查询的用户信息放入Session中(每一个用户浏览器对应在服务器中的唯一容器)
            //用于判断用户是否已登录
            req.getSession().setAttribute("CurrUser", user);
            MyWeb.printJson(resp, R.OK());
        } else {
            MyWeb.printJson(resp, R.err("账号或密码错误!"));
        }
    }
}

MyWeb.getBeanFromRequest4Json(UserDto.class, req)从前端发来的请求中获取以 JSON 格式提交的用户数据,并将其转换为 UserDto 类型的对象 loginUser。这样从前端输入的登录信息就获取到了。
定义SQL语句,用来从数据库中查询数据。
DaoCreater.currentDao().queryUniqueBean(User.class, sql, loginUser.getU_id(), loginUser.getU_pwd())会执行sql语句,查询唯一匹配的记录,返回在user对象中。
如果对象不为空,说明用户存在,那么将用户数据存在Session中,以便后续判断用户是否已登录以及其他功能的实现。
MyWeb.printJson(resp, R.OK())将一个表示成功的响应(R.OK())以 JSON 格式输出到给定的 HttpServletResponse 对象 resp 中,用于前端从中获取响应的状态判断是否登录成功。

到这里前后端若没有问题,那么基本上实现了登录的开发。启动项目进行测试。

三、效果演示

,启动项目,点击登录,在跳转后的登录页面我们什么也不做直接点登录,此时用户名和密码皆为空,我们可以在开发人员工具的控制台看到打印出的信息:
在这里插入图片描述
输入错误的信息:
在这里插入图片描述在控制台同样打印输出了相关信息。
最后我们输入正确的登录信息:实际上也打印了登录成功的信息,后面又很快跳转回首页,就没有截图了
至此,登录功能基本实现完成。但是这样的信息提示在控制台,我们要让它在页面上进行提示,所以下一步引入轻提示组件:

四、轻提示组件

<div class="toast-container position-fixed top-0 start-50 translate-middle-x mt
1">
    <div id="toast" class="toast opacity-100 bg-white" >
        <div class="toast-header">
            <strong class="me-auto"></strong>
            <button type="button" class="btn-close"  data-bs-dismiss="toast" >
            </button>
        </div>
        <div class="toast-body"></div>
    </div>
</div>

这是一个组件,我们要转变成变量对象才可以使用。
创建对象和函数:

   const toastObj = new bootstrap.Toast(document.querySelector("#toast"),{delay:2600});
    const toast =(title ="提示",msg="")=>{
        document.querySelector("#toast .me-auto").innerHTML=title;
        document.querySelector("#toast .toast-body").innerHTML=msg;
        toastObj.show();
    }

toastObj是一个 bootstrap.Toast 实例,创建来初始化页面中 id 为 “toast” 的元素。
然后toast函数,先查找 id 为 “toast” 的元素内部的两个子元素,一个是 .me-auto 类的元素,用于设置标题;另一个是 .toast-body 类的元素,用于设置消息内容,会把接收的参数也就是标题和信息赋值给对应元素。在调用显示方法。

最后修改前端的login函数,将信息不在控制台打印,通过组件来显示:
console.log('成功',"登录成功");修改为toast('成功',"登录成功");,这样就可以了。
代码:

    const login = async () => {
        const u_id = document.querySelector("#u_id").value;
        const u_pwd = document.querySelector("#u_pwd").value;
        if (u_id === "" || u_pwd === "") {
            toast("错误", "账号或密码 不能为空!");
            return;
        }
        const loginObj={
            u_id:u_id,
            u_pwd:u_pwd
        }
        const url = "./user/login";
        //发送POST请求
        const req = await fetch(url, {
            method: "POST",
            headers: {'Content-Type': 'application/json'},//内容类型
            body: JSON.stringify(loginObj)//发送的请求体是json格式的字符串
        });
        if (req.ok) {
            const result = await req.json();
            console.log(result);
            if(result.success){
                toast('成功',"登录成功");
                //延迟执行函数
                setTimeout(()=>{
                    location.href=`index.html`;
                },1200);
            }else{
                toast('失败',result.message);
            }
        } else {
            toast(`响应错误!错误代码:${req.status}`);
        }
    }

最终效果:
在这里插入图片描述

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

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

相关文章

OpenAI Whisper Cannot Import Numpy

题意&#xff1a;“OpenAI Whisper 无法导入 Numpy” 问题背景&#xff1a; I am trying to run the OpenAI Whisper model but running into the following error when trying to run my script: “我正在尝试运行 OpenAI Whisper 模型&#xff0c;但在运行脚本时遇到了以下…

【全网行为管理解决方案】上网行为系统有哪些?

全网行为管理系统是一种用于监控、管理和优化企业内部网络中所有用户活动及网络流量的技术解决方案。 这类系统可以帮助企业提高网络安全、优化网络性能&#xff0c;并确保网络使用符合公司政策及法规要求。以下是几种常用的上网行为管理系统&#xff1a; 一、安企神 特点&am…

防范小程序隐私合规风险,筑牢用户信任防线

随着国内APP软件生态的成熟&#xff0c;依托于头部APP的小程序逐渐成为零售、娱乐、出行等行业必选的获客渠道之一。较低的开发成本和成熟的用户营销功能&#xff0c;令小程序的数量在过去几年呈指数级增长。截止2023年&#xff0c;头部APP内集成的小程序总量已超千万。然而&am…

【业余玩儿AI】【文档问答】实操记录0822

电梯 前文回顾继续踩坑实录从头来过,docker部署Ollama我一定是被偷听了,大数据之神把我拉出泥潭时间回到白天,模型初窥时间回到开心的链接上Ollama那一刻 按捺住乱撞的小鹿,我去准备下文的剧情了 前文回顾 这里书接上文,上文说到: 目标是文档问答,先是本地部署了Marker,然后又…

计算机二级题--指针 章节

1.概念 1.函数名代表函数的入口地址 2.交换地址 1.*s,说明s是一个指针变量 2.s&k;说明让s指向k地址 3.所以*sk实际上与上面那句是等价的,因此m一直都没有什么变化依然是3 4.k是全局变量所以是5 3&#xff0c;7&#xff1b;改变s指向之后&#xff0c;又将值赋给了s指向的…

WS2812B硬件电路设计总结

一、WS2812b的电压是多少&#xff1f; WS2812B的电压通常在3.5到5.3V之间。 WS2812B是一种流行的可编程LED&#xff0c;也称为NeoPixel。它集成了RGB LED和控制电路&#xff0c;可以通过单个数据线进行串联连接。这种LED的输入电源电压范围为3.5到5.3V&#xff0c;这意味着它…

WPF中的XAML是如何转换成对象的?

起因 最近有遇到有小伙伴在实现TreeView不同层级使用不同数据模板时&#xff0c;遇到了一些问题。 经过查阅资料&#xff0c;我提供了两种解决方案。 第一种是使用TemplateSelector&#xff0c;这种方式可以根据ViewModel设置不同的数据模板。 第二种是根据数据动态创建数据…

中兴 随身WIFI 5产品参数

产品参数 无线参数无线速率2.4GHz, 300Mbps天线类型内置Wi-Fi天线软件功能手机App中兴ZTE Link APP Pro更多功能移动网络&#xff08;4G/3G&#xff09;接入、Wi-Fi接入、Wi-Fi加密认证、WebUI、PIN保护、FOTA升级等硬件规格接口Micro USB/标准SIM卡&#xff08;2FF&#xff0…

软件测试 缺陷报告处理流程

系统软件 操作系统 软件缺陷 缺陷报告 当测试人员发现了一个缺陷&#xff0c;需要填写一份 缺陷报告 来记录这个缺陷&#xff0c;并通过这个缺陷报告告知开发人员所发生的问题————缺陷报告是测试人员和开发人员交流沟通的重要工具。 缺陷报告的组成 1、缺陷ID 缺陷编号&…

JuiceFS 在多云架构中加速大模型推理

在大模型的开发与应用中&#xff0c;数据预处理、模型开发、训练和推理构成四个关键环节。本文将重点探讨推理环节。在之前的博客中&#xff0c;社区用户 BentoML 和贝壳的案例提到了使用 JuiceFS 社区版来提高模型加载的效率。本文将结合我们的实际经验&#xff0c;详细介绍企…

Linux——网络(2)

一、通信 --- 不同主机上进程间的通信 1、IP和端口号 IP&#xff1a;标识网络中的一台主机 本质上 32位的整型数据 端口号: 标识某个进程 本质上 16位的整型数据 2、udp和tcp udp的特点: 1.无连接 2.不可靠 tcp的特点&#xff1a; 1.面…

【赵渝强老师】执行Oracle的冷备份与冷恢复

冷备份与冷恢复是指发生在数据库已经正常关闭的情况下进行的备份和恢复。由于此时数据库已经关闭&#xff0c;通过冷备份可以将数据库的关键性文件拷贝到另外存储位置。冷备份因为只是拷贝文件&#xff0c;因此备份的速度非常快。在执行恢复时&#xff0c;只需将文件再拷贝回去…

命令模式:如何利用命令模式实现手游后端架构?

成长路上不孤单&#x1f60a;【14后boy&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;接上篇博文&#xf…

拍抖音在哪里去水印,三招教你快速掌握去水印技巧

在抖音上&#xff0c;我们经常会看到一些精彩的内容&#xff0c;想要保存下来&#xff0c;但往往视频上会有水印。本文将分享五个免费且高效的去除抖音视频水印的技巧&#xff0c;帮助你轻松保存无水印的视频。 技巧一&#xff1a;奈斯水印助手(小程序) 奈斯水印助手是一款专…

为技术博客添加评论功能:Gitalk 教程与实战

为技术博客添加评论功能&#xff1a;Gitalk 教程与实战 简介安装使用创建 Github Application方式1方式2 主页传送门&#xff1a;&#x1f4c0; 传送 简介 Gitalk是一个基于 GitHub Issue 和 Preact 开发的评论插件。   Gitalk是一个现代、无后端、基于GitHub Issue的评论系…

基于单片机的程控电源显示控制电路设计

摘要 : 介绍了基于单片机程控电源显示控制电路的硬件设计和软件实现 &#xff0c; 该设计可以实现程控电源的输出显示和手动控制功能。 实践验证 &#xff0c; 该设计具有很好的使用效果和工程价值 。 关键词 : 程控电源 ; 显示控制 ; 单片机 0 引言 程控电源广泛地应用在…

python怎么写乘法表

代码如下&#xff1a; 代码详解&#xff08;为了让自己理解&#xff09;&#xff1a; for i in range(1,10):# print(i,end )for j in range(1,i1):print(%s*%s%s %(i,j,i*j),end )print() 1. for i in range(1,10) 这是一个for循环语句&#xff0c;range&#xff08;&…

无线数传模块是啥东西?

一 、 产品概述 无线数传模块是用来替代传统数据采集、通讯、控制布线的占用工业级模块。 无线数传模块一款工作在免费频段、5000m传输距离模块发射功率158mW、具有高稳定性、低功耗、高性价比、工业级特点。 模块具有多种传输距离规格可供选择&#xff0c;根据应用场景需要&am…

【python】基础一

目录 数据类型数据类型转换-整数/浮点数/字符串标识符运算符字符串扩展字符串拼接字符串格式化字符串精度字符串格式化-快速写法对表达式进行格式化字面量变量数据输入 数据类型 查看数据类型&#xff1a;type(数据) #输出结果&#xff1a;classint> print(type(10))数据类型…

自动生成依赖清单:pipreqs,Python项目的救星

文章目录 **自动生成依赖清单&#xff1a;pipreqs&#xff0c;Python项目的救星**背景&#xff1a;为何选择pipreqs&#xff1f;pipreqs是什么&#xff1f;如何安装pipreqs&#xff1f;库函数使用方法场景应用场景一&#xff1a;新项目初始化场景二&#xff1a;更新现有项目依赖…