Jquery+Servlet+JDBC实现登录注册功能

news2025/1/18 20:21:54

前端部分

HTML+CSS部分

引入JQuery包和JQuery.cookie包,前者封装了DOM操作的一些方法,后者封装了对cookie的操作

我们使用cookie主要是为了做登录后页面的跳转时,能存下来这个用户是谁,这样后面可以对单一用户进行操作,比如根据用户id查询等

代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
<link rel="stylesheet" href="css/login.css">
<script src="js/dependency/jquery-3.7.1.min.js" defer></script>
<script src="js/dependency/jquery.cookie.js" defer></script>
<script src="js/login.js" defer></script>
</head>
<body>
	<div class="login">
		<div class="inputArea">
			<ul>
				<li>用户名:<input type="text" class="username" id="userName"></input></li>
				<li>密码:<input type="password" class="password" id="passWord"></input></li>
			</ul>
		</div>
		<div class="clickArea">
			<input type="button" value="登录" id="loginBtn" /> 
			<input type="button" value="注册" id="registerBtn" />
		</div>
	</div>
	<div class="register">
		<div class="registerInput">
			<ul>
				<li>用户名:<input type="text" class="username" id="regiestUserName"></input></li>
				<li>密码:<input type="password" class="password" id="resistPassWord"></input></li>
				<li>确认密码:<input type="password" class="password" id="confirmPassWord"></input></li>
			</ul>
		</div>
		<div class="registerArea">
			<input type="button" value="注册" id="doRegister" /> 
			<input type="button" value="取消" id="cancleRegister" />
		</div>
	</div>
</body>
</html>
body{
	margin:0;
	padding:0;
}
/*登录样式*/
.login{
	height: 30vh;
	width: 20vw;
	/*background: red;*/
	margin-top: 10vh;
	margin-left: auto;
	margin-right: auto;
	border: 3px solid red;
	border-radius: 30px;

}
.login .inputArea ul{

	display: flex;
	flex-direction: column;
	margin: 12vh 0 0 0;
	justify-content: center;
	align-items: center;
	
}

.inputArea ul li{
	margin: 0 auto;
	display: flex;
	line-style-type:none;
}
.clickArea{
	display: flex;
	margin: 30px auto;
	justify-content: center;
    align-items: center;
}

/*注册弹框样式*/
.register{
	height: 30vh;
	width: 20vw;
	/*background: red;*/
	margin: 50px auto;
	border: 3px solid blue;
	border-radius: 30px;
	
	display:none;
}
.registerInput ul{
	display: flex;
	flex-direction: column;
	margin: 12vh 0 0 0;
	justify-content: center;
	align-items: center;
}

.registerInput ul li{
	margin: 0 auto;
	display: flex;
	line-style-type:none;
}
.registerArea{
	display: flex;
	margin: 30px auto;
	justify-content: center;
    align-items: center;
}
代码要点
  1. 这里使用的是无序列表,但是实际使用发现很难对齐文字和输入框,就像这样
    在这里插入图片描述

推荐修改为两个无边框表格,会好很多

  1. 注册部分(蓝色边框部分),要设置为display:none,用户点击注册按钮的时候弹出
  2. 弹性盒子模型,我们希望输入框竖着排列,按钮横着排列,注意设置

JS代码部分

代码

let checkInputAndTrim = function(param,value){
	if(!value||value==""){
		alert(param + "为空!");
		return -1;
	}
	return value.trim();
}

// 单击登录按钮的单击事件触发
$("#loginBtn").on("click", function(){
	// trim + 校验用户输入非空
	let username = checkInputAndTrim("用户名", $("#userName").val());
	let password = checkInputAndTrim("密码", $("#passWord").val());

	if(username!=-1 || password!=-1){
		$.ajax({
	        url: "login",
	        type: "post",
	        data:{username, password},
	        success: function (value) {
	        	console.log(value);
				let code = value.code;
				console.log(code);
				if(code!=0){
					let msg = value.msg;
					alert(msg);
				}else{
					alert("登录成功!");
					let userId = value.data[0].id;
					// 获取当前时间
					let expirationTime = new Date();   
					// 在当前时间的基础上增加2小时
					expirationTime.setTime(expirationTime.getTime() + 120 * 60 * 1000);
					$.cookie("userId",userId,{expires: expirationTime, path: "/CommodityManage" });
					// 跳转其他页面
					self.location.href='CommodityManage.html';
				}
	        },
	        error: function () {
	        	alert("登录失败!");
	        }
	    })
	}
	
})

// 单击注册按钮的单击事件触发
$("#registerBtn").on("click", function(){
	
	$(".register").css("display","block");
	
})

// 确认注册
$("#doRegister").on("click", function(){
	
	// trim + 校验用户输入非空
	let username = checkInputAndTrim("用户名", $("#regiestUserName").val());
	let password1 = checkInputAndTrim("密码", $("#resistPassWord").val());
	let password2 = checkInputAndTrim("确认密码", $("#confirmPassWord").val());
	
	if(username!=-1||password1!=-1||password2!=-1){
		if(password1!=password2){
			alert("两次输入的密码不一致!");
			return;
		}
		$.ajax({
	        url: "register",
	        type: "post",
	        data:{username, password1,password2},
	        success: function (value) {
	        	console.log(value);
				let code = value.code;
				console.log(code);
				if(code!=0){
					let msg = value.msg;
					alert(msg);
				}else{
					alert("注册成功!");
					// 清空输入的数值
					$(".registerInput ul li input").val("");
					// 隐藏注册框
					$(".register").css("display","none");
				}
	        },
	        error: function () {
	        	alert("注册失败!");
	        }
	    })
	}

})
// 取消注册
$("#cancleRegister").on("click", function(){
	// 清空输入的数值
	$(".registerInput ul li input").val("");
	// 隐藏注册框
	$(".register").css("display","none");
});

代码要点
  1. 经常需要用到的代码块可以用函数单独拿出来,代码复用可以使代码的逻辑更清晰
// 校验非空+去除用户输入的字符串的前后空格,重复使用,所以提出来
let checkInputAndTrim = function(param,value){
	if(!value||value==""){
		alert(param + "为空!");
		return -1;
	}
	return value.trim();
}
  1. 这里的cookie是后端传给前端的用户id
    cookie最好设置过期时间,并设置保存路径,否则可能会导致无关页面修改/删除本页面的cookie
expirationTime.setTime(expirationTime.getTime() + 120 * 60 * 1000);
$.cookie("userId",userId,{expires: expirationTime, path: "/CommodityManage" });

后端部分

Java代码

这里关于JDBC的部分是经过封装的,不过是无侵入的封装,不改变原有的JDBC,所以具体使用起来没什么特别大的差异,读者可以原地修改为JDBC

登录Servlet部分

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.qcby.db.MysqlUtil;

public class LoginServlet extends HttpServlet {

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		String userName = req.getParameter("username");
		String passWord = req.getParameter("password");
		String[] queryParams = { "id", "user_name", "password" };
		String loginSql = "select id, user_name, password from t_entity_user where user_name= \"" + userName + "\"";

		ArrayList<String[]> userList = MysqlUtil.showUtil(loginSql, queryParams);
		for (String[] user : userList) {
			System.out.println("=============查询用户的结果:" + Arrays.toString(user));
		}
		resp.setContentType("application/json;charset=UTF-8");
		PrintWriter pw = resp.getWriter();

		if (userList.size() == 0) {
			pw.write(MysqlUtil.listToFreedomJson("-1", "未找到用户名为" + userName + "的用户!", null, null));
			return;
		} else if (!passWord.equals(userList.get(0)[2])) {
			pw.write(MysqlUtil.listToFreedomJson("-2", "密码错误", null, null));
			return;
		}
		ArrayList<String[]> resultList = new ArrayList<>();
		resultList.add(new String[] { userList.get(0)[0] });
		String[] resultParams = { "id" };
		pw.write(MysqlUtil.listToFreedomJson("0", "success", resultList, resultParams));
	}
}

如果不使用@WebServlet注解的话,就需要在WEB-INF文件夹下的web.xml当中注册Servlet,并配置访问路径
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1" metadata-complete="true">
	<display-name>MyFirstServlet</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<!--登录 -->
	<servlet>
		<servlet-name>login</servlet-name>
		<servlet-class>com.qcby.servlet.LoginServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>login</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>
	
	<!--注册 -->
	<servlet>
		<servlet-name>register</servlet-name>
		<servlet-class>com.qcby.servlet.RegisterServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>register</servlet-name>
		<url-pattern>/register</url-pattern>
	</servlet-mapping>
</web-app>
登录要点
  1. 首先校验是否存在用户名对应的用户,然后再判断是否密码错误
  2. 自己封装的错误信息尽量完整
  3. String用equals判断相等时,应该将一定不为null的放在equals的前面,防止出现空指针异常

在这里,用户输入的password经过了前端的非空检验,所以一定不是null,而从数据库中查出来的密码,可能为null

if (!passWord.equals(userList.get(0)[2])) {
		pw.write(MysqlUtil.listToFreedomJson("-2", "密码错误", null, null));
		return;
	}

注册Servlet部分

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.qcby.db.MysqlUtil;

public class RegisterServlet extends HttpServlet {

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		String userName = req.getParameter("username");
		String passWord1 = req.getParameter("password1");
		String passWord2 = req.getParameter("password2");

		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
		String remark = formatter.format(Calendar.getInstance().getTime());
		resp.setContentType("application/json;charset=UTF-8");
		PrintWriter pw = resp.getWriter();
		if (passWord1 != null && !passWord1.equals(passWord2)) {
			pw.write(MysqlUtil.listToFreedomJson("-3", "两次密码输入不一致", null, null));
			return;
		}
		String insertSql = "insert into t_entity_user(user_name, password, remark) value(\"" + userName + "\",\""
				+ passWord1 + "\",\"" + remark + "\")";

		System.out.println(insertSql);
		try {
			int result = MysqlUtil.add(insertSql);
			System.out.println("注册用户插入的行数" + result);
		} catch (Exception e) {
			pw.write(MysqlUtil.listToFreedomJson("-4", e.getMessage(), null, null));
			return;
		}
		pw.write(MysqlUtil.listToFreedomJson("0", "注册成功", null, null));
	}
}

注册要点
  1. 前端已经校验了两个密码是否相等了,后端为什么还要再校验一次?这是因为用户有可能是用postman或者swagger等接口测试工具发的请求,所以需要重新校验一次

至于为什么非空没校验,是因为懒,所以没写

但是真实企业场景下,除非做一些请求来源的验证,否则前端有的校验,后端有;前端没有的校验,后端一样有!后端负责整个项目的兜底

  1. sql的字符串一定要注意转移引号,否则sql会执行出错
  2. 这里在数据库的user表中,给user_name字段加了一个唯一索引(UNIQUE),防止重复。所以后端的注册没有判断用户名重复

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

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

相关文章

嵌入式学习-PWM输出比较

简介 PWM技术 输出比较框图介绍 定时器部分 比较器控制部分 输出控制部分 相关寄存器

使用screen窗口在Autodl服务器训练网络

无法使用鼠标滚轮来查看历史输出的消息 vim ~/.screenrc 按i插入 termcapinfo xterm* ti:te 按esc :wq 保存screen创建的会话中&#xff0c;无法使用鼠标滚轮来查看历史输出的消息 解决方法_screen查看历史输出-CSDN博客无法使用鼠标滚轮查看screen会话历史&#xff0c;解决方…

证件照尺寸标准大小及用途介绍

在日常生活中&#xff0c;证件照是我们不可或缺的一部分&#xff0c;无论是办理身份证、驾驶证&#xff0c;还是参加考试、求职&#xff0c;都需要用到不同尺寸和底色的证件照。本文将为您详细介绍证件照的尺寸标准、用途以及底色的选择。 一、证件照的尺寸标准证件照的尺寸通…

【错题集-编程题】小红的ABC(字符串 + 找规律)

牛客对应题目链接&#xff1a;小红的ABC (nowcoder.com) 一、分析题目 算法思路&#xff1a;由于题目要找的是最短的回文子串&#xff0c;并且只有三个字母&#xff1a;a、b、c&#xff0c;因此最短的回文子串的长度要么是 2&#xff0c;要么是 3。因此&#xff0c;我们仅需枚举…

如何重启Windows系统上的Mysql服务

很久很久之前&#xff0c;我想把我的一台windows笔记本当比服务使用&#xff0c;当时还没有搞wsl, 试了vmware在局域网内总是断连。然后就直接在 windows系统上装了一个 windows版本的Mysql81。 有一天需要修改最大连接数&#xff0c; 费了挺大的劲终于找到了配置文件 my.ini…

“碳”索不止

2023年&#xff0c;欧盟宣布将在未来实施CBAM&#xff08;碳边境调节机制&#xff09;&#xff0c;也称为碳关税&#xff0c;是一种针对进口货物的碳排放定价政策工具。该机制要求在欧盟境内的进口商对其进口产品支付相应的碳排放费用&#xff0c;以弥补其生产过程中产生的碳排…

K8S认证 | CKA题库 + 答案 | 查看Pod CPU资源使用量

2、查看集群中运行Pod CPU资源使用量 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node k8s …

6.概率论

概率论在深度学习中也有着广泛的应用。由于深度学习模型通常包含大量的参数和复杂的结构&#xff0c;因此在实际应用中很难直接找到最优解。此时&#xff0c;我们可以利用概率论中的相关概念和方法&#xff0c;如贝叶斯推断、最大似然估计等&#xff0c;来估计模型的参数或评估…

【环境监测与分析】-环境检测过程案例

一.方案背景 空气质量检测&#xff0c;是指对空气质量的好坏进行检测。空气质量的好坏反映了空气中污染物浓度的高低。空气污染是一个复杂的现象&#xff0c;在特定时间和地点空气污染物浓度受到许多因素影响。来自固定和流动污染源的人为污染物排放大小是影响空气质量的最主要…

win11安装SQL Server 2012 企业版

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、硬件要求二、软件安装问题参考&#…

国外站群服务器如何提高seo排名

很多seo网站优化会选择国外站群服务器&#xff0c;那么国外站群服务器如何提高seo排名&#xff0c;具体方式有哪些?Rak部落小编为您整理发布国外站群服务器如何提高seo排名。 国外站群服务器可以通过以下几种方式提高网站在搜索引擎中的排名&#xff1a; - **内容分发与加速**…

持续拥抱鲲鹏生态 星辰天合深化信创存储能力

近日&#xff0c;鲲鹏昇腾开发者大会与广电五舟“2024 智算中国行”北京站陆续召开&#xff0c;星辰天合持续拥抱鲲鹏生态&#xff0c;以重要的合作伙伴身份受邀参加&#xff0c;并在鲲鹏昇腾开发者大会上荣获“甄选解决方案最佳应用软件奖”&#xff0c;在广电五舟“2024 智算…

USB2.0协议解读

一、说明 本文以Universal Serial Bus Specification Revision 2.0 April 27, 2000内容为准。 USB2.0支持三种速率&#xff0c;High speed&#xff08;480Mb/s500ppm&#xff09;、Full speed&#xff08;12Mb/s2500ppm&#xff09;以及Low speed&#xff08;1.5Mb/s1.5%&…

JUnit5测试用例

1.用Test注解表示为测试方法 2.使用DisplayName定义别名 3.使用Assertions类的断言方法 使用断言&#xff0c;可以判断方法的实际执行结果和预期结果是否一致 assertEqualsassertTureassertNotNullassertAllassertThrows 下图是预期与实际不同时报错图 4.使用BeforeEach注解&…

分析人工智能在智慧银行服务中的实际应用以及面临的挑战

一、引言 近年来,人工智能(AI)技术快速发展,其在金融领域,特别是智慧银行服务中的应用日益广泛。人工智能以其独特的数据处理能力、预测分析能力以及自动化决策能力,极大地提升了智慧银行的服务效率、降低了运营成本,并优化了客户体验。然而,人工智能在智慧银行服务中…

RocketMQ-Dashboard 控制台使用详解

1 安装部署 具体部署启动请参考&#xff1a;RocketMQ从安装、压测到运维一站式文档_rocketmq benchmark压测-CSDN博客 RocketMq的dashboard&#xff0c;有运维页面&#xff0c;驾驶舱&#xff0c;集群页面&#xff0c;主题页面&#xff0c;消费者页面&#xff0c;生产者页面&…

FileLink如何实现金融行业跨网文件传输

在金融行业&#xff0c;跨网文件传输一直是一个备受关注的问题。由于金融数据的敏感性和重要性&#xff0c;如何确保文件在传输过程中的安全性、稳定性和合规性成为了金融机构急需解决的难题。而FileLink作为一款跨网文件交换系统&#xff0c;凭借其强大的功能和优势&#xff0…

Leetcode - 130双周赛

目录 一&#xff0c;3142. 判断矩阵是否满足条件 二&#xff0c;3143. 正方形中的最多点数 三&#xff0c;3144. 分割字符频率相等的最少子字符串 四&#xff0c;3145. 大数组元素的乘积 一&#xff0c;3142. 判断矩阵是否满足条件 本题题意&#xff0c;满足每一列的数全部…

YOLOV8环境部署(GPU版本)

一、安装&#xff43;&#xff55;&#xff44;&#xff41;和&#xff43;&#xff55;&#xff44;&#xff4e;&#xff4e; 1、安装cuda之前先打开英伟达控制面板查看自己的显卡信息 2、“帮助”—>“系统信息”—>“组件”&#xff0c;然后看第三行的信息“Nvidia …

2024做安全测试必须要知道的几种方法!

前言 安全性测试(Security Testing)是指有关验证应用程序的安全等级和识别潜在安全性缺陷的过程&#xff0c;其主要目的是查找软件自身程序设计中存在的安全隐患&#xff0c;并检查应用程序对非法侵入的防范能力&#xff0c;安全指标不同&#xff0c;测试策略也不同。 但安全…