Java Web实现简易CRUD操作笔记(基于Servlet+MySQL)
一、项目概述
本次上课练习的代码是一套基于 Java Servlet + MySQL 实现的简易CRUD(增删改查)系统,核心围绕animal(动物)、person(人员)、student(学生)三张数据库表,通过Servlet接收前端HTTP请求,调用封装的数据库工具类完成数据操作,并返回JSON格式的响应结果。
整体技术栈:Servlet 3.0+(注解式配置)、JDBC(数据库连接)、MySQL(存储数据)、原生JSON字符串拼接(响应数据)。
二、核心工具类解析
2.1 DBConnection:数据库连接工具类
作用:封装MySQL数据库的连接创建与关闭逻辑,是所有数据库操作的基础。
java
package com.qcby.sql;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBConnection {
// 数据库连接参数(硬编码)
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/may7?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false";
String user = "root";
String password = "123456";
public Connection conn;
// 构造方法:创建连接
public DBConnection() {
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
}
// 关闭连接
public void close() {
try {
this.conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键笔记:
- 采用
DriverManager方式获取JDBC连接,驱动类为MySQL 5.x的com.mysql.jdbc.Driver(MySQL 8.x需改用com.mysql.cj.jdbc.Driver); - 连接参数(URL、用户名、密码)硬编码在代码中,后续可优化为配置文件(如
db.properties); - 构造方法自动创建连接,提供
close()方法释放连接资源。
2.2 MysqlUtil:数据库操作封装类
作用:基于DBConnection封装通用的增、删、改、查方法,简化Servlet层的数据库操作,同时提供查询结果转JSON的工具方法。
核心方法分类
| 方法名 | 作用 | 返回值 |
|---|---|---|
add(sql) |
执行INSERT语句 | int(1成功) |
update(sql) |
执行UPDATE语句 | int(1成功) |
del(sql) |
执行DELETE语句 | int(1成功) |
getJsonBySql(sql, columns) |
执行SELECT并转JSON | String(JSON串) |
listToJson(list, columns) |
把查询结果集转标准JSON | String(JSON串) |
关键笔记:
- 增/删/改方法逻辑一致:获取连接→创建PreparedStatement→执行SQL→关闭资源→返回执行结果;
- 查询方法会将ResultSet结果集转为
ArrayList<String[]>,再通过listToJson拼接成固定格式的JSON(包含code、msg、data字段); - JSON拼接时处理了
null值和双引号转义,避免JSON格式错误。
三、Servlet层CRUD实现(按功能分类)
Servlet是前端与数据库之间的中间层,通过@WebServlet注解配置访问路径,重写doGet方法处理GET请求,核心逻辑:接收请求参数→拼接SQL→调用MysqlUtil→返回JSON响应。
3.1 查询操作(ShowXXXServlet)
以ShowStudentServlet为例:
java
@WebServlet("/showStudent1")
public class ShowStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 拼接查询SQL
String sql = "select * from student order by id desc";
// 2. 指定数据库字段(与查询结果列对应)
String[] columns = {"id","name","sex","age","sno","class_num"};
// 3. 调用工具类获取JSON数据
String data = MysqlUtil.getJsonBySql(sql, columns);
// 4. 设置响应格式(UTF-8编码+JSON类型)
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=UTF-8");
// 5. 返回JSON数据
resp.getWriter().append(data);
}
}
通用规律:
- 所有查询Servlet(ShowAnimal/ShowPerson/ShowStudent)逻辑一致,仅SQL和字段数组不同;
- 响应格式固定为
application/json,编码UTF-8,避免中文乱码。
3.2 新增操作(AddXXXServlet)
以AddAnimalServlet为例:
java
@WebServlet("/addAnimal")
public class AddAnimalServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取前端传入的参数
String color = req.getParameter("color");
String age = req.getParameter("age");
String type = req.getParameter("type");
// 2. 拼接INSERT SQL
String sql = "insert into animal(color,age,type) values('"+color+"','"+age+"','"+type+"')";
// 3. 调用工具类执行新增
int count = MysqlUtil.add(sql);
// 4. 构造响应JSON(成功/失败)
String data = count>0 ? "{\"code\":200,\"msg\":\"新增成功\"}" : "{\"code\":999,\"msg\":\"新增失败\"}";
// 5. 返回响应
resp.setCharacterEncoding("UTF-8");
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().append(data);
}
}
通用规律:
- 通过
req.getParameter()获取前端参数; - 拼接SQL时注意字符串参数加单引号,数值参数直接拼接;
- 根据
MysqlUtil.add()返回值(1/0)判断新增结果,返回固定格式的JSON。
3.3 修改操作(UpdateXXXServlet)
以UpdatePersonServlet为例:
java
@WebServlet("/updatePerson")
public class UpdatePersonServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取参数(含主键id)
String id = req.getParameter("id");
String name = req.getParameter("name");
// ... 其他参数
// 2. 拼接UPDATE SQL
String sql = "update person set name = '"+name+"',... where id = "+id;
// 3. 执行修改
int count = MysqlUtil.update(sql);
// 4. 构造响应JSON
String data = count>0 ? "{\"code\":200,\"msg\":\"更新成功\"}" : "{\"code\":999,\"msg\":\"更新失败\"}";
// 5. 返回响应(同新增)
...
}
}
通用规律:
- 必须传入主键
id,用于定位要修改的记录; - SQL拼接格式:
update 表名 set 字段=值 where id=主键; - 响应逻辑与新增一致,仅提示语不同。
3.4 删除操作(DelXXXServlet)
以DelStudentServlet为例:
java
@WebServlet("/delStudent")
public class DelStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取主键id
String id=req.getParameter("id");
// 2. 拼接DELETE SQL
String sql="delete from student where id="+id;
// 3. 执行删除
int count=MysqlUtil.del(sql);
// 4. 构造响应JSON
String data = count>0 ? "{\"code\":200,\"msg\":\"删除成功\"}" : "{\"code\":999\"msg\":\"删除失败\"}";
// 5. 返回响应(同新增)
...
}
}
注意点:
- 代码中存在语法错误:
"code\":999\"msg\""缺少逗号,应改为"code\":999,\"msg\":\"删除失败\"}; - 删除操作仅需主键id,逻辑最简单,但需谨慎(无软删除,直接物理删除)。
四、代码优化建议(重点!)
本次练习代码实现了核心功能,但存在生产环境需优化的问题:
4.1 解决SQL注入问题(最高优先级)
当前SQL通过字符串拼接生成(如where id="+id),存在严重的SQL注入风险。
改进方案 :使用PreparedStatement参数化查询,示例:
java
// 原拼接方式(危险)
String sql = "delete from student where id="+id;
// 优化后(参数化)
String sql = "delete from student where id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id); // 绑定参数
pstmt.executeUpdate();
4.2 配置解耦
将DBConnection中的数据库连接参数(URL、用户名、密码)抽离到db.properties配置文件,通过类加载器读取:
properties
# db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/may7?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
jdbc.user=root
jdbc.password=123456
4.3 规范请求方式
增/删/改操作应使用POST请求(doPost方法),查询用GET,符合HTTP语义规范:
java
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把原doGet中的逻辑移到这里
}
4.4 优化JSON生成方式
手动拼接JSON字符串易出错,建议引入FastJSON/Jackson等工具:
java
// 引入FastJSON示例
import com.alibaba.fastjson.JSONObject;
JSONObject result = new JSONObject();
result.put("code", 200);
result.put("msg", "新增成功");
String data = result.toJSONString();
4.5 完善异常处理
当前仅e.printStackTrace()打印异常,应添加日志记录(如SLF4J/Logback),并返回友好的错误提示。
4.6 参数校验
新增/修改时校验参数合法性(如年龄是否为数字、字段是否为空),避免非法参数导致SQL执行失败。
五、总结
本次练习代码完整覆盖了Servlet + JDBC 实现CRUD的核心流程:
- 数据库连接封装 → 2. 通用SQL操作封装 → 3. Servlet接收请求/处理业务/返回响应;
- 掌握了
@WebServlet注解、请求参数获取、JSON响应格式、JDBC基础操作等关键知识点; - 代码虽能运行,但在安全性(SQL注入)、可维护性(硬编码)、规范性(请求方式)等方面仍需优化。
这是Java Web入门的经典练习,理解这套代码的逻辑后,可进一步学习框架(如SSM/Spring Boot),但底层的JDBC和Servlet原理仍是基础。