學生信息管理系統案例小結

週末拿最近學習的知識 (JDBC, Servlet, JSP) 作一個小案例, 原本週末就應該整理筆記的, 可是打球也不能耽誤啊, 因此只好趕着在今天下班的時間, 作下記錄.javascript

<br>css

技術準備

  1. Java 基礎知識, JavaEE 基礎html

    tomcat, servlet, jsp(EL + JSTL)前端

  2. web前端的基礎知識java

    html, css, javascript基礎 + Jquery 基礎python

  3. 關係型數據庫mysql

    使用 SpringJDBC 操做 mysqljquery

  4. 開發工具git

    IDEA, JDK8.0github

<br>

需求分析

  1. 使用 mysql 來存儲學生信息
  2. 頁面上完成學生數據的展現, 可進行學生信息的增刪改差, 而後支持上一頁, 下一頁操做, 以及學生信息查詢.

<br>

實現

一. 表結構設計

  • 建立數據庫: student

    將編碼設置爲 utf-8, 便於存取中文

    drop database if exists student;
    create database student default charset=utf8;
  • 建立表: student

    create table student(
        id int unsigned primary key auto_increment not null,
        student_id varchar(20) not null unique COMMENT '學號',
        name varchar(20) not null,
        gender varchar(5),
        birthday date, 
        address varchar(50),
        qq varchar(20),
        email varchar(50)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    設置student_id的緣由是由於學號可能會改變, 而主鍵 id 沒法修改.

<br>

二. 建立JavaEE項目, 導入 jar 包

項目結構圖以下:

<br>

三. 準備前端頁面 (原型設計)

在項目中就是前端的 html 代碼, 這一步也很是的重要.

首頁以列表的形式展現學生信息

新增 和 修改信息頁面, 這兩個頁面應該長的很像

若是把新增和修改當作一個頁面, 那麼一共就兩個頁面 ~

學生信息列表

添加學生頁面

編輯學生頁面

<br>

四. src目錄層次結構

代碼模塊的劃分:

  1. 實體類: student (就一張學生表, 因此對應的實體類只有一個)
  2. 數據訪問對象: dao (操做學生對象的 StudentDao)
  3. 邏輯處理: Servlet (學生信息列表展現, 新增, 修改, 刪除學生信息)
  4. 工具類: JDBCDruidUtils (封裝了 SpringJDBC 對數據庫的操做)
  5. 單元測試: test

在 src 目錄下建立代碼的層次結構:

<br>

五. 具體代碼邏輯實現

student 實體類
package com.student.entity;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Student {
    private int id;
    private String studentId;
    private String name;
    private String gender;
    private Date birthday;
    private String address;
    private String qq;

    // setter and getter ,  日期類型須要額外轉換下
    
    public String getBirthday() {
        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
        return formater.format(this.birthday);
    }

    public void setBirthday(String birthday) {
        SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = formater.parse(birthday);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        this.birthday = date;
    }
}

<br>

JDBCDruidUtils 鏈接池:
package com.student.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * JDBCDruidUtils 工具類
 */
public class JDBCDruidUtils {
    private static DataSource ds = null;

    static {
        try {
            // 加載配置文件
            Properties pro = new Properties();
            // 獲取 src 路徑下的文件 --> ClassLoader
            ClassLoader cl = JDBCDruidUtils.class.getClassLoader();
            InputStream is = cl.getResourceAsStream("druid.properties");
            pro.load(is);
            // 經過工廠函數 獲取 數據庫鏈接池 (傳入配置文件)
            ds = DruidDataSourceFactory.createDataSource(pro);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 獲取鏈接池對象
    public static DataSource getDataSource(){
        return ds;
    }

    // 獲取鏈接對象
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

<br>

druid.properties 配置文件
driverClassName=com.mysql.jdbc.Driver
# useUnicode表示容許使用自定義的Unicode
url=jdbc:mysql://192.168.0.115:3306/JDBC?useUnicode=true&characterEncoding=utf8
username=username
password=password
initialSize=5
maxActive=10
maxWait=3000

<br>

studentDao

DAO (Data Access Object) 數據庫訪問, 就是對數據庫的操做進行封裝, 讓 servlet 裏邊看不到 JDBC 的代碼

package com.student.dao;

import com.student.entity.Student;
import com.student.utils.JDBCDruidUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * student 對象相關的操做方法
 */
public class StudentDao {
    // 獲取 JdbcTemplate 對象
    private static JdbcTemplate template = new JdbcTemplate(JDBCDruidUtils.getDataSource());

    /**
     * 獲取 JdbcTemplate 對象, 將學生信息寫入到數據庫中
     */
    public static int createStudent(Student student){
        String createSql = "insert into student values(?,?,?,?,?,?,?,?);";
        int num = StudentDao.template.update(createSql, student.getId(), student.getStudentId(), student.getName(),
                student.getGender(), student.getBirthday(), student.getAddress(), student.getQq(), student.getEmail());
        return num;
    }

    /**
     * 經過id查詢學生
     * @param id
     * @return
     */
    public static Student queryStudentById(String id){
        String querySql = "select * from student where id = ?";
        Student student = StudentDao.template.queryForObject(querySql, new BeanPropertyRowMapper<Student>(Student.class), id);
        return student;
    }


    /**
     * 更新 學生信息
     * @param student
     * @return
     */
    public static int updateStudent(Student student){
        String updateSql = "update student set gender = ?, birthday = ?, address = ?," +
                           "qq = ?, email = ? where id = ?;";
        int num = StudentDao.template.update(updateSql, student.getGender(), student.getBirthday(), student.getAddress(),
                student.getQq(), student.getEmail(), student.getId());
        return num;
    }

    /**
     * 刪除學生信息
     * @param id
     * @return
     */
    public static int deleteStudentById(String id){
        String deleteSql = "delete from student where id = ?";
        int num = StudentDao.template.update(deleteSql, id);
        return num;
    }
}

<br>

學生列表展現
package com.student.servlet;

import com.student.utils.JDBCDruidUtils;
import org.springframework.jdbc.core.JdbcTemplate;
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 javax.sql.DataSource;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@WebServlet("/list")
public class ReadList extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 不用獲取參數, 因此不用設置流的編碼
            // 獲取 JdbcTemplate 對象
        DataSource ds  = JDBCDruidUtils.getDataSource();
        JdbcTemplate template = new JdbcTemplate(ds);

        // 查詢結果, 將結果集封裝爲 ReadList 集合
//        String querySql = "select * from student limit 0, 3";
        String querySql = "select * from student";
        java.util.List<Map<String, Object>> studentList = template.queryForList(querySql);
        // 將學生對象列表存儲到 request 對象域中
        request.setAttribute("studentList", studentList);
        // 轉發到 list 頁面
        request.getRequestDispatcher("/list.jsp").forward(request, response);
    }
}

jsp 頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <!-- 使用Edge最新的瀏覽器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport視口:網頁能夠根據設置的寬度自動進行適配,在瀏覽器的內部虛擬一個容器,容器的寬度與設備的寬度相同。
    width: 默認寬度與設備的寬度相同
    initial-scale: 初始的縮放比,爲1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3個meta標籤*必須*放在最前面,任何其餘內容都*必須*跟隨其後! -->
    <title>學生信息管理系統</title>
    <!-- 1. 導入CSS的全局樣式 -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery導入,建議使用1.9以上的版本 -->
    <script src="js/jquery-2.1.0.min.js"></script>
    <!-- 3. 導入bootstrap的js文件 -->
    <script src="js/bootstrap.min.js"></script>
    <style type="text/css">
        td, th {
            text-align: center;
        }
    </style>
</head>
<body>
<div class="container">
    <h3 style="text-align: center">學生信息列表</h3>
    <br>
    <form id="form" action="${pageContext.request.contextPath}/delete" method="post">
        <table border="1" class="table table-bordered table-hover">
        <tr class="success">
            <%--<th><input type="checkbox" id="firstCb"></th>--%>
            <th>序號</th>
            <th>學號</th>
            <th>姓名</th>
            <th>性別</th>
            <th>生日</th>
            <th>地址</th>
            <th>QQ</th>
            <th>郵箱</th>
            <th>操做</th>
        </tr>

        <c:forEach items="${requestScope.studentList}" var="student" varStatus="s">
            <tr>
                <%--<td><input type="checkbox" name="uid" value="${student.id}"></td>--%>
                <td>${s.count}</td>
                <td>${student.student_id}</td>
                <td>${student.name}</td>
                <td>${student.gender}</td>
                <td>${student.birthday}</td>
                <td>${student.address}</td>
                <td>${student.qq}</td>
                <td>${student.email}</td>
                <td><a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/update?id=${student.id}">修改</a>&nbsp;
                    <a class="btn btn-default btn-sm" href="javascript:deleteStudent(${student.id});">刪除</a></td>
            </tr>

        </c:forEach>
    </table>
    </form>

    <div style="float: right;margin: 5px;">
        <a class="btn btn-primary" href="${pageContext.request.contextPath}/create.jsp">添加聯繫人</a>
    </div>

</div>
    <script>
        function deleteStudent(id){
            //用戶安全提示
            if(confirm("您肯定要刪除嗎?")){
                //訪問路徑
                location.href="${pageContext.request.contextPath}/delete?id="+id;
                location.submit();
            }
        }
    </script>
</body>
</html>

<br>

新增一條學生信息

先返回新增學生信息的 jsp 頁面, 而後用戶在鍵入信息以後, 提交表單到後端處理.

package com.student.servlet;

import com.student.dao.StudentDao;
import com.student.entity.Student;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/create")
public class Create extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取參數, 設置流的編碼
        request.setCharacterEncoding("utf-8");
        // 將參數封裝到 map 集合中 (使用JavaBeanUtils工具)
        Map<String, String[]> map = request.getParameterMap();
        Student student = StudentDao.mapToStudent(map);

        // 獲取 JdbcTemplate 對象, 將學生信息寫入到數據庫中
        int num = StudentDao.create(student);
        // 重定向到 list 頁面
        response.sendRedirect(request.getContextPath() + "/list");
    }
}

jsp 頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <!-- 使用Edge最新的瀏覽器的渲染方式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- viewport視口:網頁能夠根據設置的寬度自動進行適配,在瀏覽器的內部虛擬一個容器,容器的寬度與設備的寬度相同。
    width: 默認寬度與設備的寬度相同
    initial-scale: 初始的縮放比,爲1:1 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3個meta標籤*必須*放在最前面,任何其餘內容都*必須*跟隨其後! -->
    <title>添加學生信息</title>
    <!-- 1. 導入CSS的全局樣式 -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <!-- 2. jQuery導入,建議使用1.9以上的版本 -->
    <script src="js/jquery-2.1.0.min.js"></script>
    <!-- 3. 導入bootstrap的js文件 -->
    <script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
    <h3 style="text-align: center">添加學生信息頁面</h3>
    <br>
    <form action="${pageContext.request.contextPath}/create" method="post">
        <div class="form-group">
            <label for="studentId">學號:</label>
            <input type="text" class="form-control" id="studentId" name="studentId" placeholder="請輸入學號">
        </div>
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" placeholder="請輸入姓名">
        </div>
        <div class="form-group">
            <label>性別:</label>
            <input type="radio" name="gender" value="男" checked="checked"/>男
            <input type="radio" name="gender" value="女"/>女
        </div>
        <div class="form-group">
            <label for="birthday">生日:</label>
            <input type="text" class="form-control" id="birthday" name="birthday" placeholder="請輸入生日">
        </div>
        <div class="form-group">
            <label for="address">地址:</label>
            <input type="text" class="form-control" id="address" name="address" placeholder="請輸入地址"/>
        </div>
        <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" class="form-control" id="qq" name="qq" placeholder="請輸入QQ號碼"/>
        </div>
        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" id="email" name="email" placeholder="請輸入郵箱地址"/>
        </div>
        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" />
            <input class="btn btn-default" type="reset" value="重置" />
            <input class="btn btn-default" type="button" value="返回" id="getBack"/>
        </div>
    </form>
</div>
<script>
    //給返回按鈕添加單擊事件, 返回上一個頁面
    document.getElementById("getBack").onclick = function(){
         window.history.back(-1);
    };
</script>
</body>
</html>

<br>

更新學生信息

get 方法中返回編輯學生信息的 jsp 頁面, 填充當前學生的信息

post 方法對用戶提交的 form 表單, 對學生信息進行更新

package com.student.servlet;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import com.student.dao.StudentDao;
import com.student.entity.Student;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/update")
public class Update extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取參數, 設置流的編碼
        request.setCharacterEncoding("utf-8");
        // 將參數封裝到 map 集合中 (使用JavaBeanUtils工具)
        Map<String, String[]> map = request.getParameterMap();
        Student student = new Student();
        try {
            BeanUtils.populate(student, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        // 獲取 JdbcTemplate 對象, 將學生信息更新到數據庫中
        int num = StudentDao.updateStudent(student);
        System.out.println("更新成功, num: " + num);
        // 重定向到 list 頁面
        response.sendRedirect(request.getContextPath() + "/list");
    }

    // 返回帶有 student 信息的修改頁面
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取student的 id
        String id = request.getParameter("id");
        Student student = StudentDao.queryStudentById(id);
        // 將須要修改的學生信息放到 request 域對象中
        request.setAttribute("student", student);
        // 請求轉發到 update.jsp 頁面
        request.getRequestDispatcher("/update.jsp").forward(request, response);
    }
}

jsp頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>修改學生信息</title>
        <link href="css/bootstrap.min.css" rel="stylesheet">
        <script src="js/jquery-2.1.0.min.js"></script>
        <script src="js/bootstrap.min.js"></script>
        
    </head>
    <body>
        <div class="container" style="width: 400px;">
        <h3 style="text-align: center;">修改學生信息</h3>
            <br>
        <form action="${pageContext.request.contextPath}/update" method="post">
            <!--  隱藏域 提交id-->
            <input type="hidden" name="id" value="${requestScope.student.id}">
          <div class="form-group">
            <label for="studentId">學號:</label>
            <input type="text" class="form-control" id="studentId" name="studentId"  value="${requestScope.student.studentId}" readonly="readonly" placeholder="請輸入學號" />
          </div>

          <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name"  value="${requestScope.student.name}" readonly="readonly" placeholder="請輸入姓名" />
          </div>

          <div class="form-group">
            <label>性別:</label>
              <c:if test="${requestScope.student.gender == '男'}">
                  <input type="radio" name="gender" value="男" checked />男
                  <input type="radio" name="gender" value="女"  />女
              </c:if>

              <c:if test="${requestScope.student.gender == '女'}">
                  <input type="radio" name="gender" value="男"  />男
                  <input type="radio" name="gender" value="女" checked  />女
              </c:if>

              <c:if test="${requestScope.student.gender == null}">
                  <input type="radio" name="gender" value="男" checked/>男
                  <input type="radio" name="gender" value="女"  />女
              </c:if>

          </div>

          <div class="form-group">
            <label for="birthday">生日:</label>
            <input type="text" class="form-control" value="${requestScope.student.birthday}" id="birthday"  name="birthday" placeholder="請輸入生日" />
          </div>

          <div class="form-group">
            <label for="address">地址:</label>
            <input type="text" id="address" class="form-control" value="${requestScope.student.address}" name="address" placeholder="請輸入地址"/>
          </div>
          <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" id="qq" class="form-control" value="${requestScope.student.qq}" name="qq" placeholder="請輸入QQ號碼"/>
          </div>
          <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" id="email" class="form-control" value="${requestScope.student.email}" name="email" placeholder="請輸入郵箱地址"/>
          </div>
         <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" />
            <%--<input class="btn btn-default" type="reset" value="重置" />--%>
            <input class="btn btn-default" type="button" value="返回" id="getBack"/>
         </div>
        </form>
    </div>
    <script>
    //給返回按鈕添加單擊事件, 返回上一個頁面
    document.getElementById("getBack").onclick = function(){
         window.history.back(-1);
    };
    </script>
</body>
</html>

<br>

刪除學生信息

寫到這裏, 刪除的邏輯就很是簡單了, 須要注意的是, 刪除的時候, 須要給用戶彈框確認, 這部分涉及到前端 js 的一個知識點.

function deleteStudent(id){
    //用戶安全提示
    if(confirm("您肯定要刪除嗎?")){				             								location.href="${pageContext.request.contextPath}/delete?id="+id; 						location.submit();
    }
}
package com.student.servlet;

import com.student.dao.StudentDao;
import com.student.entity.Student;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/delete")
public class Delete extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 獲取student的 id
        String id = request.getParameter("id");
        int num = StudentDao.deleteStudentById(id);
        System.out.println("刪除學生信息, num: " + num);
        // 重定向到 list 頁面
        response.sendRedirect(request.getContextPath() + "/list");
    }
}

<br>

案例總結

  1. 一共花了 6 個小時左右的時間, 後端的邏輯處理不算複雜, 知識點忘記了能夠看下前邊學習的筆記, 總的來講還算順利.
  2. 前端的頁面佈局是資料裏邊找的模板, 而後改了一些, 可以配合後端的 api 進行數據交互, 而後運用 jsp 中的 EL 表達式和 JSTL 標籤進行展現, 沒有涉及到一些很難的內容.
  3. 這是一個先後端不分離的案例, 和以前學習的 python flask 項目裏邊的 jinja2 模板引擎很是的類似, 例如大鬍子語法( {{}} ), 控制代碼塊( if else, for 循環 ), 過濾器, 模板繼承等內容, 有以前的項目經驗, 理解起來也比較的容易.

<br>

案例改進

寫到這裏, 仍是一個很是粗糙的案例, 能夠優化的點有:

  1. 新增, 修改學生信息時對參數進行校驗,
  2. 按學號, 姓名, 性別進行檢索,
  3. 分頁查詢,
  4. 批量刪除,
  5. 登陸功能,
  6. 權限管理 (分管理員, 普通用戶等, 普通用戶沒有刪除功能)

後邊有時間再持續優化 ~ (也許就這麼一說, haha)

<br>

最後, 附上github倉庫地址: https://github.com/kaichenkai/StudentManagement

<br>

ending ~

<br>

相關文章
相關標籤/搜索