引入Dao

1.crm和数据库的结合

我们先前实现的crm项目的数据都是自定义的 而非数据库获取 因此现在我们应该实现crm和数据库的集成

  • ListServlet.java
    • doPost方法中在处理异常的选项中 并没有发现throws方式 而只有try-catch方式 这是因为子类throws的异常必须和父类throws异常一致或者是父类throws异常的子类型异常 显然子类throws异常超出了父类throws异常的范围
    • ResultSet属于资源 需要关闭以释放资源 所以我们需要通过try-with-resources对其自动关闭
    • 我们在写sql语句的时候 尽量写明字段名以代替*
    • 转发操作可以保证attribute的共享 具体是为了在ListServlet和list.jsp之间进行共享 重定向则不然 并且我们的转发操作一定不要忽略forward方法
java 复制代码
package com.axihh.servlet;

import com.axihh.bean.Customer;

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.*;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/list")
public class ListServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 通过变量保存url、用户名、密码
        String url = "jdbc:mysql://localhost:3306/crm?serverTimezone=UTC";// 由于是新版的驱动包 所以我们需要指定时区
        String username = "root";
        String password = "root";
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            try (Connection conn = DriverManager.getConnection(url, username, password);// 连接数据库(注意获取Connection对象的时候会抛出异常 处理异常的方式却只有一种 即try-catch 并没有throws方式 很奇怪 这是因为我们的doPost方法是继承自HttpServlet的doPost 而父类的该方法限制了子类throws的对象只能是ServletException/IOException或者他们的子类型异常 而当前获取连接操作所抛出的异常超出了这个范围 所以他不允许你通过throws手段对异常进行处理 只能通过try-catch进行处理)
                 PreparedStatement pstmt = conn.prepareStatement("SELECT id, name, age, height FROM customer");// 创建语句(注意创建语句需要同时传入要执行的sql语句 同时他属于资源 所以也要放置在try-with-resources的()中 sql语句中的*尽量写清楚具体的字段名)
                 ResultSet rs = pstmt.executeQuery())// 执行sql语句 将sql语句的返回值用ResultSet进行保存)
            {
                // 定义一个集合 用于存放用户bean
                List<Customer> customers = new ArrayList<>();
                // 循环遍历数据库中的用户 并且将用户存入集合中
                while (rs.next()) {
                    // 创建一个bean实例 用于存放当前用户的字段
                    Customer customer = new Customer();
                    Integer id = rs.getInt("id");
                    String name = rs.getString("name");
                    Integer age = rs.getInt("age");
                    Double height = rs.getDouble("height");
                    customer.setId(id);
                    customer.setName(name);
                    customer.setAge(age);
                    customer.setHeight(height);
                    customers.add(customer);
                }
                // 将集合存放到attribute中
                request.setAttribute("customers", customers);
                // 转发到list.jsp中
                request.getRequestDispatcher("page/list.jsp").forward(request, response);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

}

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
  • list.jsp
html 复制代码
<%--
  Created by IntelliJ IDEA.
  User: 19938
  Date: 2024/5/25
  Time: 9:51
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
    <title>Title</title>
    <style>
        th, td {
            border: 1px solid red;
        }
    </style>
</head>
<body>
<a href="page/add.html">添加</a>
<table>
    <thead>
        <tr>
            <th>id</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>身高</th>
        </tr>
    </thead>
    <tbody>
        <%-- 我们在获取存储在attribute中的customers时 我们应该通过el表达式去获取 具体的格式就是${} 而本质上就是在调用getAttribute --%>
        <c:forEach items="${customers}" var="customer">
            <tr>
                <%-- 我们以下的el表达式的本质是调用getter获取属性 --%>
                <td>${customer.id}</td>
                <td>${customer.name}</td>
                <td>${customer.age}</td>
                <td>${customer.height}</td>
            </tr>
        </c:forEach>
    </tbody>
</table>

</body>
</html>
  • add.html
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/crm5/save" method="post">
    <div>姓名 <input type="text" name="name"></div>
    <div>年龄 <input type="text" name="age"></div>
    <div>身高 <input type="text" name="height"></div>
    <div><button>保存</button></div>
</form>
</body>
</html>
  • SaveServlet
java 复制代码
package com.axihh.servlet;

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.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

@WebServlet("/save")
public class SaveServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 变量保存url username password
        String url = "jdbc:mysql://localhost:3306/crm?serverTimezone=UTC";
        String username = "root";
        String password = "root";
        try{
            // 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            try(Connection conn = DriverManager.getConnection(url, username, password);
                PreparedStatement pstmt = conn.prepareStatement("INSERT INTO customer(name, age, height) VALUES (?, ?, ?)")){
                // 为pstmt设置参数
                pstmt.setString(1, request.getParameter("name"));
                pstmt.setInt(2, Integer.parseInt(request.getParameter("age")));
                pstmt.setDouble(3, Double.parseDouble(request.getParameter("height")));
                // 执行sql语句
                int i = pstmt.executeUpdate();
                // 重定向到指定的页面
                response.sendRedirect("/crm5/list");
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
  • 值得注意的是 有些时候 我们在启动Tomcat以后 会出现资源无法找到的现象 这时候 有可能是某个文件未及时编译打包到out/artifacts目录中(实际上部署到Tomcat上的项目是存放在out/artifacts中的 其中web-inf目录用于存放我们的src文件以及关联的函数库 而其他的一些html、jsp文件则存放在web-inf同目录下) 我们可以将out/artifacts目录下的contextPath文件删除 然后重启Tomcat以重新生成contextPath文件 或者说有更快速的手段 即idea->build->build artifacts->指定的contextPath文件->build/clean

2.项目缺陷

对于上述这个项目 实现至此 仍然存在着许多的问题

  • 数据库访问代码大量重复

    • 解决方法:将数据库访问代码抽取出来 放置在Dao类(即Database Access Object 该类用于专门负责数据库的访问)中 里面内置save、list等提供调用的方法
    • 需要注意的是 我们在进行保存操作的时候 如果某个字段以unique修饰 说明不能重复 我们要对重复添加做出反应 即转发到失败页面 为此 我们可以定义一个error.jsp展示失败信息 反之则执行重定向操作
    • 当然 我们也可以将常量单独抽取到一个Constant类 这边 我们就直接将其放置在dao中
    • CustomerDao
    java 复制代码
    package com.axihh.dao;
    
    import com.axihh.bean.Customer;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;
    
    public class CustomerDao {
        // 定义私有成员
        private static final String URL = "jdbc:mysql://localhost:3306/crm?serverTimezone=UTC";
        private static final String USERNAME = "root";
        private static final String PASSWORD = "root";
        public boolean save(Customer customer){
            try {
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                try(// 连接数据库
                    Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
                    // 创建语句
                    PreparedStatement pstmt = conn.prepareStatement("INSERT INTO customer(name, age, height) VALUES (?, ?, ?)")) {
                    // 设置参数
                    pstmt.setString(1, customer.getName());
                    pstmt.setInt(2, customer.getAge());
                    pstmt.setDouble(3, customer.getHeight());
                    // 执行sql语句
                    int a = pstmt.executeUpdate();
                    // 如果a的值大于0的话 那么说明dml语句执行成功
                    return a > 0;
                }
            }catch(Exception e) {
                // 打印报错信息
                e.printStackTrace();
                // 返回false 表示执行失败
                return false;
            }
        }
        public List<Customer> list() {
            try {
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                try(// 建立连接
                    Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
                    // 创建语句
                    PreparedStatement pstmt = conn.prepareStatement("SELECT id, name, age, height FROM customer" );
                    // 执行sql语句
                    ResultSet rs = pstmt.executeQuery()) {
                    // 接着将数据库中的用户信息存入到customer bean类中 并且将customer bean类储存到customer集合中
                    List<Customer> customers = new ArrayList<>();
                    while(rs.next()) {
                        Customer customer = new Customer();
                        customer.setId(rs.getInt("id"));
                        customer.setName(rs.getString("name"));
                        customer.setAge(rs.getInt("age"));
                        customer.setHeight(rs.getDouble("height"));
                        customers.add(customer);
                    }
                    // 返回用户信息集合
                    return customers;
                }
            } catch(Exception e) {
                // 打印报错信息
                e.printStackTrace();
                // 返回空值
                return null;
            }
        }
    }
    • ListServlet
    java 复制代码
    package com.axihh.servlet;
    
    import com.axihh.bean.Customer;
    import com.axihh.dao.CustomerDao;
    
    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.awt.*;
    import java.io.IOException;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.List;
    
    @WebServlet("/list")
    public class ListServlet extends HttpServlet {
        // 定义一个客户数据库访问类对象
        private final CustomerDao cd = new CustomerDao();
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            List<Customer> customers = cd.list();
            // 将customers储存到attribute中
            request.setAttribute("customers", customers);
            // 转发
            request.getRequestDispatcher("/page/list.jsp").forward(request, response);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    • SaveServlet
    java 复制代码
    package com.axihh.servlet;
    
    import com.axihh.bean.Customer;
    import com.axihh.dao.CustomerDao;
    
    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.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    
    @WebServlet("/save")
    public class SaveServlet extends HttpServlet {
        private final CustomerDao cd = new CustomerDao();
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 定义一个Customer bean对象
            Customer customer = new Customer();
            customer.setName(request.getParameter("name"));
            customer.setAge(Integer.parseInt(request.getParameter("age")));
            customer.setHeight(Double.parseDouble(request.getParameter("height")));
            if(cd.save(customer)) {
                // 表明添加成功 执行重定向操作
                response.sendRedirect("/crm5/list");
            }else {
                // 表明添加失败或者出现异常 需要执行转发操作
                request.setAttribute("error", "添加失败 请重新添加");
                request.getRequestDispatcher("/page/error.jsp").forward(request, response);
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request, response);
        }
    }
    • list.jsp
    html 复制代码
    <%--
      Created by IntelliJ IDEA.
      User: 19938
      Date: 2024/5/25
      Time: 9:51
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <html>
    <head>
        <title>Title</title>
        <style>
            th, td {
                border: 1px solid red;
            }
        </style>
    </head>
    <body>
    <a href="page/add.html">添加</a>
    <table>
        <thead>
            <tr>
                <th>id</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>身高</th>
            </tr>
        </thead>
        <tbody>
            <%-- 我们在获取存储在attribute中的customers时 我们应该通过el表达式去获取 具体的格式就是${} 而本质上就是在调用getAttribute --%>
            <c:forEach items="${customers}" var="customer">
                <tr>
                    <%-- 我们以下的el表达式的本质是调用getter获取属性 --%>
                    <td>${customer.id}</td>
                    <td>${customer.name}</td>
                    <td>${customer.age}</td>
                    <td>${customer.height}</td>
                </tr>
            </c:forEach>
        </tbody>
    </table>
    
    </body>
    </html>
    • error.jsp
    html 复制代码
    <%--
      Created by IntelliJ IDEA.
      User: 19938
      Date: 2024/5/25
      Time: 17:05
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>${error}</h1>
    </body>
    </html>
    • add.html
    html 复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="/crm5/save" method="post">
        <div>姓名 <input type="text" name="name"></div>
        <div>年龄 <input type="text" name="age"></div>
        <div>身高 <input type="text" name="height"></div>
        <div><button>保存</button></div>
    </form>
    </body>
    </html>
  • 每一次请求都对应着一个Servlet

  • 存在繁杂的异常处理代码

相关推荐
阿华的代码王国10 小时前
【JavaEE】——多线程(join阻塞,计算,引用,状态)
java·开发语言·数据结构·java-ee
GGBondlctrl10 小时前
【后端开发】JavaEE初阶—线程的理解和编程实现
java·java-ee·线程的创建方式·线程是什么·线程的内部原理
Miraitowa_cheems15 小时前
[JavaEE] UDP协议
网络·tcp/ip·java-ee
MTingle1 天前
【Java EE】文件IO
java·java-ee
JOJO___3 天前
Spring IoC 配置类 总结
java·后端·spring·java-ee
蜗牛学苑_武汉3 天前
设计模式之代理模式
java·网络·java-ee·代理模式
月临水3 天前
JavaEE:网络编程(UDP)
java·网络·udp·java-ee
kakwooi3 天前
JavaEE---Spring IOC(2)
java·spring·java-ee
奔强的程序3 天前
【计算机毕业设计】医院电子病历
java-ee·毕业设计·课程设计·源代码管理
ZachOn1y3 天前
Java 入门指南:JVM(Java虚拟机)—— 双亲委派模型(Parent Delegation Model)
java·jvm·后端·java-ee·团队开发·个人开发