首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

基於 MVC 架構的學生信息管理系統實戰:JDBC + Servlet + JSP 完整實現

     編輯:Java 綜合教學

基於 MVC 架構的學生信息管理系統實戰

本文通過一個完整的學生信息增刪改查 (CRUD) 系統,演示基於 JDBC、Servlet、JSP 的傳統 Java Web MVC 架構開發全流程。涵蓋數據庫設計、分層架構、DAO 實現、Servlet 控制器、JSP 視圖及常見問題排查,適合 Java Web 初學者鞏固基礎。

一、數據庫設計

單表 student,字段:

字段類型說明
idINT PRIMARY KEY學號
nameVARCHAR(50)姓名
ageINT年齡
classVARCHAR(50)班級
CREATE TABLE student (
  id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  age INT NOT NULL,
  class VARCHAR(50)
);

二、分層架構

  • Bean 層:com.mm.bean.Student — POJO,封裝數據。
  • DAO 接口層:com.mm.Dao.IStuDao — 定義 CRUD 契約。
  • DAO 實現層:com.mm.Dao.impl.StuDaoImpl — JDBC 具體操作。
  • DB 工具類:com.mm.db.JDBCUtils — 連接獲取與資源釋放。
  • Servlet 控制器:com.mm.sevlet.studentServlet — 接收請求、調度業務、轉發/重定向視圖。
  • JSP 視圖層:列表、新增、編輯、查看頁面。

三、核心代碼實現

1. 實體類 Student

package com.mm.bean;
public class Student {
    private int id;
    private String name;
    private int age;
    private String classes; // 注意:數據庫列名 class 是關鍵字,實體用 classes
    // 構造器、Getter/Setter 省略
}

2. DAO 接口 IStuDao

package com.mm.Dao;
import com.mm.bean.Student;
import java.util.List;
public interface IStuDao {
    void addstu(Student stu);
    void updatestu(Student stu);
    void delstu(int id);
    List findall();
    Student findStubyId(int id);
}

3. JDBC 工具類 JDBCUtils

package com.mm.db;
import java.sql.*;
public class JDBCUtils {
    private static final String URL = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";
    private static final String USER = "mxning";
    private static final String PASS = "mxning";

    static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); } }

    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASS);
    }
    public static void release(ResultSet rs, PreparedStatement ps, Connection con) {
        closeQuietly(rs); closeQuietly(ps); closeQuietly(con);
    }
    private static void closeQuietly(AutoCloseable c) {
        if (c != null) try { c.close(); } catch (Exception ignored) {}
    }
}

4. DAO 實現 StuDaoImpl(關鍵點:PreparedStatement 防注入、資源關閉、ResultSet 映射)

package com.mm.Dao.impl;
import com.mm.Dao.IStuDao;
import com.mm.bean.Student;
import com.mm.db.JDBCUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class StuDaoImpl implements IStuDao {
    @Override public void addstu(Student stu) {
        String sql = "INSERT INTO student (id, name, age, class) VALUES (?, ?, ?, ?)";
        executeUpdate(sql, stu.getId(), stu.getName(), stu.getAge(), stu.getClasses());
    }
    @Override public void updatestu(Student stu) {
        String sql = "UPDATE student SET name=?, age=?, class=? WHERE id=?";
        executeUpdate(sql, stu.getName(), stu.getAge(), stu.getClasses(), stu.getId());
    }
    @Override public void delstu(int id) {
        executeUpdate("DELETE FROM student WHERE id=?", id);
    }
    @Override public List findall() {
        String sql = "SELECT * FROM student";
        List list = new ArrayList<>();
        try (Connection con = JDBCUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {
            while (rs.next()) list.add(mapRow(rs));
        } catch (SQLException e) { throw new RuntimeException(e); }
        return list;
    }
    @Override public Student findStubyId(int id) {
        String sql = "SELECT * FROM student WHERE id=?";
        try (Connection con = JDBCUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) return mapRow(rs);
            }
        } catch (SQLException e) { throw new RuntimeException(e); }
        return null;
    }

    private void executeUpdate(String sql, Object... params) {
        try (Connection con = JDBCUtils.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {
            for (int i = 0; i < params.length; i++) ps.setObject(i + 1, params[i]);
            ps.executeUpdate();
        } catch (SQLException e) { throw new RuntimeException(e); }
    }
    private Student mapRow(ResultSet rs) throws SQLException {
        Student s = new Student();
        s.setId(rs.getInt("id"));
        s.setName(rs.getString("name"));
        s.setAge(rs.getInt("age"));
        s.setClasses(rs.getString("class"));
        return s;
    }
}

5. 控制器 Servlet:統一入口,op 參數分發

package com.mm.sevlet;
@WebServlet("/studentServlet")
public class StudentServlet extends HttpServlet {
    private IStuDao dao = new StuDaoImpl();

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String op = req.getParameter("op");
        if (op == null) op = "list";

        switch (op) {
            case "list":
                req.setAttribute("list", dao.findall());
                req.getRequestDispatcher("studentlist.jsp").forward(req, resp);
                break;
            case "add":
                resp.sendRedirect("studentadd.jsp");
                break;
            case "edit":
                int id = Integer.parseInt(req.getParameter("id"));
                req.setAttribute("stu", dao.findStubyId(id));
                String cmd = req.getParameter("command");
                if ("view".equals(cmd)) 
                    req.getRequestDispatcher("studentedit.jsp").forward(req, resp);
                else 
                    resp.sendRedirect("studentview.jsp?id=" + id);
                break;
            case "delete":
                dao.delstu(Integer.parseInt(req.getParameter("id")));
                resp.sendRedirect("studentServlet?op=list");
                break;
            case "store":
                String idStr = req.getParameter("id");
                Student s = new Student();
                s.setName(req.getParameter("name"));
                s.setAge(Integer.parseInt(req.getParameter("age")));
                s.setClasses(req.getParameter("class"));
                if (idStr == null || idStr.isEmpty()) dao.addstu(s);
                else { s.setId(Integer.parseInt(idStr)); dao.updatestu(s); }
                resp.sendRedirect("studentServlet?op=list");
                break;
        }
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
}

6. JSP 視圖頁面(片段)

  • studentlist.jsp:<c:forEach items="${list}" var="st"> 遍歷顯示,操作列提供編輯/刪除鏈接。
  • studentadd.jsp:POST 表單提交到 studentServlet?op=store。
  • studentedit.jsp:隱藏域攜帶 id,表單回顯現有數據,提交同 add。
  • studentview.jsp:只讀顯示詳情,提供返回按鈕。

完整 JSP 代碼請參考源文件,核心在於 EL 表達式 ${stu.name} 取值與表單 action 映射。

四、運行效果演示

  1. 列表頁:顯示所有學生,支持新增、編輯、刪除、查看。
  2. 新增頁:填寫姓名、年齡、班級,提交後重定向列表。
  3. 編輯頁:回顯數據,修改提交更新數據庫。
  4. 刪除:直接執行 DELETE,無確認彈窗(生產環境需加 JS 確認)。

五、常見坑點與改進方向

問題原因改進
中文亂碼請求/響應編碼未統一、DB 連接無 characterEncodingFilter 統一 UTF-8、URL 加 ?characterEncoding=UTF-8
資源洩漏手動 close 易漏、異常拋出前未關閉JDK 7+ try-with-resources 或連接池 (Druid/HikariCP)
SQL 注入風險字符串拼接 SQL(如 findStubyId 初版)全面使用 PreparedStatement 佔位符 ?
Servlet 線程不安全實例變量存狀態無狀態設計,DAO 可作為單例注入
代碼重複JDBC 模板代碼多封裝 BaseDao / 使用 Spring JdbcTemplate / MyBatis
前後端耦合JSP 混合 Java 代碼、業務邏輯引入模板引擎或前後端分離

六、總結

本案例完整展示了 Java Web 基礎開發全棧:JDBC 底層數據訪問、Servlet 請求分發、JSP 視圖渲染、MVC 分層思想。雖然生產環境多用 Spring Boot + MyBatis + 前端框架,但理解這套原生實現機制,對掌握框架原理、排查疑難雜症、進行技術選型至關重要。建議初學者手敲一遍,體會「約定優於配置」框架背後的艱辛與智慧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved