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
javapackage 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
javapackage 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
javapackage 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
-
存在繁杂的异常处理代码