1 项目实现
1.1 HTML页面(基于bootstrap)
1.1.1 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<script src="js/jquery-1.11.1.js"></script>
<script src="js/bootstrap.js"></script>
<link rel="stylesheet" href="css/bootstrap.css" />
<link rel="stylesheet" href="css/bootstrap-theme.css" />
<script>
$(function(){
$("#myForm").submit(function(){
var flag = validateUserName() && validatePassword();
if(!flag){
alert("有字段未完成!");
return false;
}else {
return true;
}
});
$("#userName").blur(function(){
validateUserName();
});
$("#userPass").blur(function(){
validatePassword();
});
});
function validateNull(value) {
return !(value == null || value === "");
}
//用户名验证规则:必须是超过6位数,仅允许数字、大写字母、小写字母、下划线,不能以下划线开头
function validateUserName() {
var userName = $("#userName").val();
var regex = /[A-Za-z0-9]\w+/;
var msg = $("#userNameMsg");
if(regex.test(userName)) {
msg.css("color", "green");
msg.html("用户名合法");
return true;
} else {
if(!validateNull(userName)) {
msg.html("输入不为空!");
} else if(userName.match(/_\w*/)) {
msg.html("第一个字符不允许为下划线!");
} else if(userName.length < 2) {
msg.html("用户名必须至少2位");
} else {
msg.html("包含非法字符!仅允许数字、字母、下划线");
}
msg.css("color", "red");
return false;
}
}
//密码验证规则:必须是超过6位数,包含数字、大写字母、小写字母
function validatePassword() {
var password = $("#userPass").val();
var regex1 = /[0-9]+[a-z]+[A-Z]+/;
var regex2 = /[a-z]+[0-9]+[A-Z]+/;
var regex3 = /[0-9]+[A-Z]+[a-z]+/;
var regex4 = /[a-z]+[A-Z]+[0-9]+/;
var regex5 = /[A-Z]+[0-9]+[a-z]+/;
var regex6 = /[A-Z]+[a-z]+[0-9]+/;
var msg = $("#passwordMsg");
if(password.length < 6) {
msg.html("长度不足6位!");
msg.css("color", "red");
return false;
}
if(regex1.test(password) || regex2.test(password) || regex3.test(password) || regex4.test(password) || regex5.test(password) || regex6.test(password)) {
msg.html("密码有效");
msg.css("color", "green");
return true;
} else {
if(!validateNull(password)) {
msg.html("输入为空!");
} else {
msg.html("密码无效,必须包含数字、大小写字母!");
}
msg.css("color", "red");
return false;
}
}
</script>
</head>
<body>
<div class="container">
<h2 class="text-center">用户登录</h2>
<form id="myForm" role="form" class="form-horizontal" action="test" method="post">
<div class="form-group">
<label class="control-label col-sm-1" for="userName">用户名:</label>
<div class="col-sm-5">
<input class="form-control" type="text" name="name" id="userName"/>
</div>
<div class="col-sm-6">
<label id="userNameMsg" class="control-label text-info">仅允许数字、大小写字母、下划线,第一个字符不能为下划线</label>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-1" for="userPass">密码:</label>
<div class="col-sm-5">
<input type="password" class="form-control" name="pass" id="userPass"/>
</div>
<div class="col-sm-6">
<label id="passwordMsg" class="control-label text-info text-left">密码至少6位,需要包含大小写字母和数字</label>
</div>
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-info col-sm-3 col-sm-offset-3">登录</button>
<button type="reset" class="btn btn-normal col-sm-3">重置</button>
</div>
</form>
</div>
</body>
</html>
1.1.2 success.html、failure.html
略。前者是登录成功的界面,后者是登录失败的界面。随意编写即可。
1.1.3 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>a1</servlet-name>
<servlet-class>com.kkb.xzk.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>a1</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
</web-app>
1.2 数据库连接与验证类
package com.kkb.xzk.validation;
import java.sql.*;
/**
* @Author: HanDing
* @Description:
* @Date Created in 2021-07-22 19:13
* @Modified By:
*/
public class DatabaseValidation {
private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/mydb6?serverTimeZone=UTC";
private static final String USER_NAME = "root";
private static final String PASSWORD = "123456";
private Connection connection;
private PreparedStatement preparedStatement;
public DatabaseValidation() throws ClassNotFoundException, SQLException {
Class.forName(DRIVER_NAME);
connection = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
}
public boolean validate(String userName, String password){
if(userName==null || "".equals(userName) || "".equals(password)){
return false;
}
String sql = "select userpass from user where username=?";
ResultSet resultSet = null;
try{
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, userName);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
String userpass = resultSet.getString(1);
if (userpass == null || "".equals(userpass)) {
return false;
} else if (password.equals(userpass)) {
return true;
} else {
return false;
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(preparedStatement != null){
try {
preparedStatement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return false;
}
}
1.3 MyServlet
package com.kkb.xzk.servlet;
import com.kkb.xzk.validation.DatabaseValidation;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
/**
* @Author: HanDing
* @Description:
* @Date Created in 2021-07-22 18:59
* @Modified By:
*/
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String userName = req.getParameter("name");
String userPass = req.getParameter("pass");
try {
boolean f = new DatabaseValidation().validate(userName, userPass);
if(f){
resp.sendRedirect("/success.html");
}else{
resp.sendRedirect("/failure.html");
}
} catch (ClassNotFoundException|SQLException e) {
e.printStackTrace();
}
}
}
1.4 其他配置
- 导入相关jar包(在web文件夹下创建lib文件夹,jar包拷贝到lib)并且建立项目依赖。
1.5 项目结构图
2 踩坑点
2.1 ClassNotFoundException
2.1.1 问题背景
使用数据库验证时,在Class.forName()处报错:ClassNotFoundException。但是实际已经导入了这个jar包。
2.1.2 产生原因
lib文件夹建在了工程根目录下。正确的做法是建在web目录下。
2.1.3 解决方法
- 在web目录下建立lib文件夹(推荐)
- 或者直接在tomcat的lib文件夹下导入包(不推荐)
2.2 名为xx和xx的servlet不能映射为一个url模式(url-pattern) [/xxx]
2.2.1 问题背景
最初写了一个servlet类,名为Validation。后来变更它的名字为MyServlet。然后每次重启服务器都会报此错误。
2.2.2 产生原因
每次重启服务器后,并没有把java文件一同编译。换句话说,每次重启只是更新了web文件夹下的内容,对src文件夹下的java文件没有重新编译。
2.2.3 解决方法
- 把out文件夹清空后重试(所有缓存类问题都可以这样解决)
- 或者点击运行后选择update classes and resources
2.3 表单数据post之后服务器接收不到
2.3.1 问题背景
定义如下的form表单,在其他配置都正确的情况下,表单提交后servlet无法接收到对应name的数据。
<form id="myForm" role="form" class="form-horizontal" action="test" method="post" enctype="multipart/form-data">
...
</form>
2.3.2 产生原因
form属性enctype表示数据的编码格式。通常分为以下三种:
- application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的(默认的)编码格式。
- multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。
- text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
当设置enctype为multipart/form-data后,由于form表单提交的数据变为一条消息,因此无法直接通过HttpServletRequest直接获取,从而无法找到相关input的name。
2.3.3 解决方法
- 如果表单中不包含文件,则直接去掉enctype属性选择默认的即可。
- 如果包含文件数据,则必须使用post方式提交并且设置enctype=multipart/form-data。此时如果想要得到文字信息,可以使用SmartUpload类的相关方法:
smartUpload.getRequest().getParameter(name)
。