一个完整javaweb项目大致可以分为这三个层:
显示层、业务层、数据访问层(DAO层)
显示层:显示在客户端的html,jsp等网页文件和处理来自网页提交数据(controller)
业务层:是显示层和数据访问层之间的桥梁,通过显示层的需求进行不同的数据访问
数据访问层:又称持久化层、DAO层,对数据库进行增删改查等操作,直接连接到数据库
在分析一个javaweb项目时,需要从上层到下层分析(显示层到数据访问层)
而在编写一个javaweb项目时,需要从下层开始写(数据访问层到显示层)
原因是一个web项目,是围绕显示层,也就是网页需求来编写,需求决定业务层与数据访问层要执行什么操作,分析到下层之后就可以从下层开始编写垒起一个web项目了
首先开始进行分析,我要做一个注册界面,有用户名与密码两个数据,第一是要验证用户名和密码是否符合规范,第二是验证数据库中不存在这个用户名,不存在才能注册嘛。
这样我们的需求就明确了:
显示层:有两个数据要获取,验证合法后,传给业务层
业务层:拿到数据后判断用户名是否与数据库有撞名字的
这个过程需要访问数据库,所以业务层会踢皮球一样把数据交给数据访问层
数据访问层:需要查询mysql数据库
当然首先要连接到数据库
在这个src下创建一个file包,file包下面创建一个mysql.properties文件
将配置文件都写到这个文件中,像这样:
driver是你导入mysql的jar包中驱动类的位置
url是数据库的位置
username与password是你连接数据库时设置的用户名与密码
再创建一个DataConnect类在Connect包下
package Connect;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class DataConnectDemo {
public static Connection DataConnect(){
Properties properties = new Properties();
InputStream resourceAsStream = DataConnect.class.getClassLoader().
getResourceAsStream("配置文件路径");
try {
properties.load(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
Connection connection = null;
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
connection = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
此方法返回一个Connection对象,用于数据访问层对数据库访问,数据访问层中访问数据库的方法都要使用Connection对象
当然有连接就有关闭,还需要写一个关闭数据库的方法
public static void CloseDB(ResultSet rs, PreparedStatement stm, Connection con){
try {
if (rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (stm!=null){
stm.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con!=null){
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
Connection、PreparedStatement、Resultset 这三兄弟的创建顺序是C -> P -> R
当使用结束后,就要释放资源,不然这次对数据库的连接会一直存在
而关闭顺序是先开的后关,后开的先关,这样才能保证资源完全释放,不占用内存
判断数据库是否存在此用户
判断数据库中是否添加成功
sql语句为什么第一个是null,因为我的数据表有自增id,虽然插入数据不用自己加,但是数据库会以为你在设置第一和第二个值,所以要写一个null占位
刚才介绍关闭资源的三兄弟,还没介绍这三兄弟的功能
Connection:连接数据库的作用
PreparedStatement:提交对已连接的数据库操作的sql语句
Resultset:获取执行sql语句后的结果集
再补充一个小知识:PreparedStatement对象的两个提交sql语句的方法
executeQuery()和executeUpdate()的区别
executeQuery()的返回值是Result对象,Result对象是一个结果集,包含了此次sql语句的所有结果,查询语句最好使用这个方法
executeUpdate()的返回值是一个int值,返回对数据库影响的行数,在对数据库进行增删改时,可以使用这个方法
业务逻辑类本质上是将数据访问层中的原始数据拿到,在此类中进行处理,以实现显示层的需求,
不要觉得多此一举,业务逻辑层不仅降低了耦合度,还提高了代码的可读性,维护性
他就像一个厨师,将小工切的菜按照客人的口味进行烹饪
在正式进入显示层之前,我们还有两件事没有解决
1、就是创建一个对用户名密码验证是否合法的类
2、就是创建一个对象类,方便传参
如果你说你非要一个个传字符串进行注册行不行呢,那当然可以,但最好别让我看到,因为这种没有美感的代码,会让我泪流满面
工具类:
import java.util.HashMap;
import java.util.Map;
public class valiDate {
public static Map valiDate(User user) {
Map map = new HashMap<>();
if (user.getUsername() == null || "".equals(user.getUsername().trim())) {
map.put("username", "用户名不能为空");
} else if (!(user.getUsername().matches("\\w{6,18}"))) {
map.put("username", "用户名不合法");
}
if (user.getPassword() == null || "".equals(user.getPassword().trim())) {
map.put("password", "密码不能为空");
} else if (!(user.getPassword().matches("[a-zA-Z0-9]{6,18}"))) {
map.put("password", "密码不合法");
}
return map;
}
}
这是用正则表达式验证是否合法,然后有错误时将错误值放入一个Map集合中返回
对象类:
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
public User() {
}
}
没想到一眨眼,就到了显示层了,Control类之所以是显示层,是因为他继承自HttpServlet,既接收来自网页的数据,也向网页提供数据
Controller类
package Controller;
import service.User;
import service.UserService;
import service.valiDate;
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.util.Map;
@WebServlet("/ControllerDemo")//这个括号内要与控制器类名一致,也要与网页中form表单action属性值一致
public class ControllerDemo extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;utf-8");
User user = new User();
UserService userService = new UserService();
Map error = valiDate.valiDate(user);
if (error.isEmpty()){
int result = userService.register(user);
if (result == 0){
req.setAttribute("message","该用户已存在");
req.getRequestDispatcher("register.jsp").forward(req,resp);
}
else if (result == 1){
resp.sendRedirect("login.jsp");
}
}
else {
resp.sendRedirect("register.jsp?error="+error);
}
}
}
关于网页跳转的重定向与转发的区别可以通过我的另一篇博客深入了解一下
javaweb网页跳转中转发和重定向的区别-CSDN博客不可以通过函数将参数携带到跳转网页,但是由于重定向第二次请求是get方式,所以可。是浏览器对服务器进行一次请求,在服务器端将要跳转的网页的网址作为数据响应。以通过拼接url地址获取参数。是浏览器对服务器进行一次请求,在服务器端进行网页的跳转,将跳转好的网页响应到浏览器中,以整个web站点(服务器)为根目录。URL网址不会有变化,地址不会改变。以当前webapps项目为根目录。https://blog.csdn.net/weixin_74250204/article/details/133099891?spm=1001.2014.3001.5502
创建注册网页
<%
HashMap error = (HashMap)request.getAttribute("error");
String message = (String) request.getAttribute("message");
%>
<%=message==null?"":message%>
注意:这是jsp文件中的代码
<%%>中可以写java代码,<%=变量名%>可以在网页中输出变量
form表单中的action属性是你执行网页的控制器类的名字
通过三目运算符的嵌套可以实现,有错误信息时输出错误信息,没有错误信息时隐藏
当你做完这些,你就已经编写出一个简单但是基本完整的JavaWeb项目了,我知道你很棒,但是只给你99分,多一分怕你骄傲,继续加油吧!
书山有路勤为径,学海无涯苦作舟
以上,就是使用idea工具写一个连接MySQL数据库的javaweb项目的全部内容了,如有不同意见欢迎评论区讨论,如果这篇文章对你有帮助的话,还请三连支持一下,你的支持就是我更新的最大动力,886~