Java Web实现简易CRUD操作笔记

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(包含codemsgdata字段);
  • 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的核心流程:

  1. 数据库连接封装 → 2. 通用SQL操作封装 → 3. Servlet接收请求/处理业务/返回响应;
  2. 掌握了@WebServlet注解、请求参数获取、JSON响应格式、JDBC基础操作等关键知识点;
  3. 代码虽能运行,但在安全性(SQL注入)、可维护性(硬编码)、规范性(请求方式)等方面仍需优化。

这是Java Web入门的经典练习,理解这套代码的逻辑后,可进一步学习框架(如SSM/Spring Boot),但底层的JDBC和Servlet原理仍是基础。

相关推荐
Zane1994几秒前
用了Optional,为什么NPE还是防不住?
java·后端
晚安日记wanna1 分钟前
批量请求失败只弹一个 Toast面试官想听五层
前端·面试·架构
大模型码小白6 分钟前
告别造假数据,直接连数据库查真实时序数据喂给 TimechoAI 大模型
java·数据库·人工智能·microsoft·架构
晚安日记wanna8 分钟前
TS const 类型参数一道面试题的四层追问
前端·面试·typescript
企业数字化笔记9 分钟前
固定资产Excel批量导入怎么防重复?资产编码、重复检查和错误回执
java·后端·excel
用户9210802628611 分钟前
前端 Vue 专栏 09:Vue Router 与前端路由
前端
golang学习记13 分钟前
IDEA 2026.3 EAP新特性:自动识别Spring Boot的新 profile 了
java·spring boot·intellij-idea
SamDeepThinking20 分钟前
Java 17内存屏障:为什么需要,怎么用
java·后端·面试
青山木23 分钟前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
小陈不好吃36 分钟前
深入理解 JVM 内存模型:从堆栈结构到 GC 日志分析实战
java·jvm·java-ee·jdk