初次接触java web,在这之前只对java语法和数据结构略有接
触,在b站看了一个简单的用户登录和注册的网站实现,就很想
自己实现一下。以下是我对踩坑过程的部分回忆。
——2021.2.17
首先大致介绍一下我的过程:
1.在mysql官网(mysql.com)下载了8.0.22版本的mysql社区版。视频中使用的是oracle数据库,而oracle数据库在自己电脑上配置相对复杂,所以我就下载了mysql数据库。下载好免安装版解压,按照教程,在cmd中进行安装和设置修改,再配置环境变量。直到可以在cmd中正常使用mysql。在自己创建的一个mydatabase数据库中创建一个login表,填入部分信息。以下是简单满足要求的完成后的展示。
2.在idea中创建Java Enterprise工程,选择jdk,选择tomcat服务器,我首先使用的是xampp集成软件包中的tomcat7.0.103,后来又在tomcat官网上下载了tomcat10.0.2,这二者使用上有一些区别,后续会介绍。(我的idea版本是2020.2.3 x64版本,jdk版本是11.0.9 LTS,这些影响不大)。tomcat7.0.103要选择Java EE 8版本,而tomcat10.0.2则要选择Jakarta EE 9版本,这个问题很大,搞错了的话在tomcat上运行时,会出现能正常部署,但网站上找不到servlet文件的情况。(详细的区分本文就不一一叙述了)
3.接下来下载JDBC驱动(https://mvnrepository.com/artifact/mysql/mysql-connector-java),JDBC驱动程序是一个软件组件,使得Java应用程序可以与数据库进行交互。我下载的是mysql-connector-java-8.0.22.jar,打开File->Project Structure->Libraries,导入mysql-connector-java-8.0.22.jar。(不同的mysql版本对jdbc驱动的版本也有要求,具体不详细叙述)
4.编写代码。虽然整体来说不是很复杂的内容,但对于初入门的菜鸟,按照视频内容编写代码,然后不断解决遇到的奇奇怪怪的问题也是很头大的,不过这也是乐趣所在,如果完全照搬而且完全不出错,那就没意思了。看这个视频的最大体会,就是让我深刻感受到了学好英语的必要性,口语太差,英语水平太差,旁人听起来看起来是真的惨不忍睹。/doge(源代码见附录)
遇到的问题:
1.Exception in thread “main” java.lang.NullPointerException空指针异常。
这个错误表示空指针异常,我遇到这个错误时我的对象的引用是空的,因为我没有对sql语句执行,所以存放返回结果的对象指针是空的。然后我把这个空的对象引用去执行if(resultSet.next()){},然后就报错了,老老实实debug才找到,想了好久,哈哈哈。/doge
2.Loading class ‘com.mysql.jdbc.Driver’. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
这个问题和其他几个问题在一开始困扰了我挺久,毕竟我一开始也搞不清楚java连接mysql需要怎么做。升级后的mysql驱动类,Driver位置由com.mysql.jdbc.Driver变为com.mysql.cj.jdbc.Driver。简而言之,和教程中的不一样,就是因为mysql和jdbc驱动的版本太高了,升级改动了。
3.The server time zone value is unrecognized or represents more than one time zone.
这是由于数据库和系统时区差异所造成的,在JDBC连接的URL后面加上serverTimezone=GMT就可以解决问题,如果需要使用GMT+8时区,需要写成GMT%2B8,否则会被解析为空。另一个解决办法就是使用低版本的mysql jdbc驱动。
4.Can not issue data manipulation statements with executeQuery().
在与数据库交互时,DataBase类中编写了一个insert函数,使用prep.executeQuery()向表中插入新的内容,然后就出了这个问题。
在百度上有好心人写的博客说executeQurery()是一个查询方法,不能进行修改操作,如果想要执行insert、update这类需要修改的操作,可以把executeQuery()改为execute()或者executeUpdate()。
5.使用tomcat7.0.103的时候在网页界面总是无法连接到数据库。
在百度上找到一个好心老哥写的博客,把jdbc驱动mysql-connector-java-8.0.22.jar放到了tomcat文件目录下的lib目录下,然后就可以连接到数据库,在网站上可以注册成功和登录成功了。
6.选择Jakarta EE 9后,从javax.过渡到了jakarta.,所以import也要注意。
Eclipse 基金会发布了 Jakarta EE 9 Milestone 1,即 RC 前的第一个里程碑版本。Jakarta EE 9 版本标志着从 javax.* 命名空间到Eclipse的jakarta.的最终过渡,此版本将所有 API 更新为在包名称中使用 jakarta.。
Jakarta EE 9的第一里程碑召示着RC版将有重大进展,并为业界提供了尝试新名称空间,开始着手迁移其框架的新契机。
好吧,又是新版本的问题,不过现在遇到并了解下这个问题也是件好事。
至此,初步完成了一个基本功能的网站。虽然很多过程和原理都不明白,但路还很长,还需要一直保持努力。之后再继续完善,在这基础上进行一些外观和功能的扩充。
放出代码,方便感兴趣的小伙伴们。
附录:
DataBase.java
package com.example.myweb10;
import java.sql.*;
import java.util.ArrayList;
public class DataBase {
Connection connection = null;
public DataBase(String name, String password) throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
this.connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDatabase?serverTimezone=GMT",
name, password);
}
public void showConnect() {
System.out.println(connection);
}
public void insert(String name, String account, String password, String ImagePath) throws SQLException {
PreparedStatement prep = connection.prepareStatement("insert into login values (?,?,?,?)");
prep.setString(1, name);
prep.setString(2, account);
prep.setString(3, password);
prep.setString(4, ImagePath);
prep.execute();
//executeQuery()是一个查询方法,而不能进行修改操作(吐槽一句:……不都是让sql语句起作用嘛,干嘛还要设置多个方法)
//因此,如果你想要执行insert、update这类需要修改的操作,可以使用executeUpdate()、execute()方法
}
public void delete(String account) throws SQLException {
PreparedStatement prep = connection.prepareStatement("delete from login where account=?");
prep.setString(1, account);
prep.execute();
}
public UserData getUser(String account) throws SQLException {
PreparedStatement prep = connection.prepareStatement("select * from login where account=?");
prep.setString(1, account);
prep.execute();
ResultSet resultSet = prep.getResultSet();
if (resultSet.next()) {
String userName = resultSet.getString("name");
String userAccount = resultSet.getString("account");
String userPwd = resultSet.getString("password");
String userImgPath = resultSet.getString("ImagePath");
return new UserData(userName, userAccount, userPwd, userImgPath);
} else
return null;
}
public ArrayList<UserData> getAllUser() throws SQLException {
ArrayList<UserData> userList = new ArrayList<UserData>();
PreparedStatement prep = connection.prepareStatement("select * from login");
prep.execute();
ResultSet resultSet = prep.getResultSet();
while (resultSet.next()) {
String userName = resultSet.getString("name");
String userAccount = resultSet.getString("account");
String userPwd = resultSet.getString("password");
String userImgPath = resultSet.getString("ImagePath");
userList.add(new UserData(userName, userAccount, userPwd, userImgPath));
//return new UserData(userName, userAccount, userPwd, userImgPath);
}
return userList;
}
public void close() throws SQLException {
connection.close();
}
public UserData check(String userAccount, String userPwd) throws SQLException {
PreparedStatement prep = connection.prepareStatement("select login.password from login where account=?");
prep.setString(1, userAccount);
prep.execute();
ResultSet resultSet = prep.getResultSet();
if (resultSet.next()) {
String pwd = resultSet.getString("password");
if (userPwd.equals(pwd))
return getUser(userAccount);
else
return null;
} else
return null;
}
}
UserData.java
package com.example.myweb10;
public class UserData {
private String userName;
private String userAccount;
private String userPwd;
private String userImgPath;
public UserData(String name, String account, String pwd, String path) {
this.userName = name;
this.userAccount = account;
this.userPwd = pwd;
this.userImgPath = path;
}
public String getUserName() {
return userName;
}
public String getUserAccount() {
return userAccount;
}
public String getUserPwd() {
return userPwd;
}
public String getUserImgPath() {
return userImgPath;
}
}
LoginServlet.Java
package com.example.myweb10;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import jakarta.servlet.*;
//import javax.servlet.*;
//import javax.servlet.annotation.*;
//import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
@WebServlet(name = "LoginServlet", value = "/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=utf-8");
PrintWriter printWriter = response.getWriter();
String account = request.getParameter("userAccount");
String pwd = request.getParameter("userPwd");
try {
DataBase dataBase = new DataBase("root", "password"); //输入数据库的账号密码
UserData userdata = dataBase.check(account, pwd);
dataBase.close();
if (userdata == null) {
printWriter.write("账号不存在或密码错误,请重试!");
} else {
printWriter.println("欢迎使用," + userdata.getUserName());
}
} catch (SQLException | ClassNotFoundException throwables) {
throwables.printStackTrace();
printWriter.write("登录出错,请重试!");
}
}
}
RegisterServlet.java
package com.example.myweb10;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import jakarta.servlet.*;
//import javax.servlet.*;
//import javax.servlet.annotation.*;
//import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
@WebServlet(name = "RegisterServlet", value = "/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=utf-8");
PrintWriter printWriter = response.getWriter();
String name = request.getParameter("userName");
String account = request.getParameter("userAccount");
String pwd1 = request.getParameter("userPwd1");
String pwd2 = request.getParameter("userPwd2");
if (pwd1.equals(pwd2)) {
try {
DataBase database = new DataBase("root", "password"); //输入数据库的账号密码
database.insert(name, account, pwd1, "ABCDE");
database.close();
printWriter.write("注册成功!");
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
printWriter.write("注册失败,请重试!");
}
} else {
printWriter.write("两次输入密码不一致,请返回重试。");
}
}
}
接下来可以使用Test.java对java能否连接mysql以及对DataBase.java和UserData.java这两个类进行功能测试。
Test.java
package com.example.myweb10;
import java.sql.SQLException;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
DataBase database = new DataBase("root", "password"); //这里输入数据库账号密码
database.showConnect();
//database.insert("小张","20210006","123456","C:\\Users\\28421\\Pictures\\桌面壁纸\\沙滩.jpg");
//database.insert("老王","201607010615","123456","abcd");
//database.delete("201607010615");
//database.delete("20210006");
UserData user1 = database.getUser("20210001");
System.out.println(user1.getUserName());
ArrayList<UserData> userList = database.getAllUser();
for (UserData each : userList) {
System.out.println(each.getUserAccount());
}
System.out.println(userList.size());
UserData userData = database.check("20210003", "123456");
if (userData == null)
System.out.println("账号或密码错误!");
else
System.out.println(userData.getUserName() + ",欢迎!");
database.close();
database.showConnect();
}
}
Login.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="LoginServlet" method="post">
账号:<input type="text" name="userAccount"><br>
密码:<input type="text" name="userPwd"><br>
<input type="submit" value="点击登录"><input type="reset" value="重新输入">
form>
body>
html>
Register.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form method="post" action="RegisterServlet">
姓名:<input type="text" name="userName"><br>
账号:<input type="text" name="userAccount"><br>
输入密码:<input type="password" name="userPwd1"><br>
重复密码:<input type="password" name="userPwd2"><br>
<input type="submit" value="提交注册"><input type="reset" value="重新输入">
form>
body>
html>