學生選課信息管理系統
1、效果圖
2、項目闡述
該項目是模擬學生選課信息的管理系統,用戶類型有三種,分別是管理員、教師、學生。學生入校註冊後需統一記錄學生個人基本信息,對於面向學生開設的相關課程需要記錄每門課程的基本信息,每個任課教師規定其可主講三門課程,學生選課時系統將相應的選課信息記錄入庫,考試結束後教師需在相應的選課記錄中補上考試成績,管理員可查看所有用戶信息,同時查看一系列的數據報表。
- 由於代碼量較多,就不放上完整代碼啦,若有需要可評論交流聯繫或者私信博主哦O(∩_∩)O
- 該項目的所有頁面樣式,佈局等均由博主自主編寫
- 本文不涉及前端頁面編寫知識
3、開發環境
- 編譯軟件:IntelliJ IDEA 2019
- 頁面設計軟件:Adobe Dreamweaver CC 2019
- 數據庫:MySQL 8.0
- 數據庫操作工具:Navicat Premium 12
- 服務器:Tomcat 9.0.37
- 環境:jdk1.8
4、功能開發
4.1、登錄
- 用戶類型選擇
- 登錄
由於項目分爲三個類型的用戶,即管理員、教師、學生,因此在進入系統前須先選擇相應的用戶類型。
- 如何區分用戶類型?
答:當用戶選擇完類型後,將對應的value值設置爲session域對象值,session域可簡單理解爲只要瀏覽器未關閉,session域對象就會一直存在。但是在Tomcat中,域對象的生命週期默認爲30分鐘,即若30分鐘內客戶端沒有再發送請求,則會超時從而自動銷燬session域中相應的對象。
/**
* 登錄
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
String type = userService.queryTypeByUsername(username);
String typeChoose = String.valueOf(req.getSession().getAttribute("UserType"));
User user = userService.login(new User(username, password, null, type));
//判斷用戶類型及賬號密碼是否成功匹配
if (type.equalsIgnoreCase(typeChoose) == false){
System.out.println("登錄失敗");
req.setAttribute("username",username);
req.setAttribute("tip","不存在此"+typeChoose+"用戶");
req.getRequestDispatcher("/page/user/login.jsp").forward(req,resp);
}else if (user==null){
System.out.println("登錄失敗");
req.setAttribute("username",username);
req.setAttribute("tip","用戶名或密碼錯誤");
req.getRequestDispatcher("/page/user/login.jsp").forward(req,resp);
}
else {
System.out.println("登錄成功");
req.setAttribute("username",username);
if (typeChoose.equalsIgnoreCase("student")){
req.getSession().setAttribute("stuNum",username);
req.getRequestDispatcher("/page/student/index.jsp").forward(req,resp);
}else if (typeChoose.equalsIgnoreCase("system")){
req.getSession().setAttribute("systemNum",username);
req.getRequestDispatcher("/page/system/index.jsp").forward(req,resp);
}else if (typeChoose.equalsIgnoreCase("teacher")){
req.getSession().setAttribute("teacherNum",username);
req.getRequestDispatcher("/page/teacher/index.jsp").forward(req,resp);
}
}
}
4.2、學生模塊
4.2.1、個人信息查詢
個人信息查詢功能的實現,只需將數據庫中對應的信息讀取即可。通過Servlet調用Service層,Service層再去調用DAO層,DAO層與數據庫交互獲取該用戶信息,並逐層返回,最後由Servlet發送數據並跳轉到相應的Jsp頁面。
- 由於功能邏輯不復雜,此處就貼jsp頁面的代碼啦
- 涉及知識點:JSTL(JSP標準標籤庫)
<%--
自我介紹
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!doctype html>
<html>
<head>
<%@include file="/common/head.jsp" %>
<title>index</title>
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" type="text/css" href="css/introduction.css">
</head>
<body>
<%@include file="/common/header_student.jsp" %>
<section>
<%@include file="/common/menu_student.jsp" %>
<div class="info">
<div class="address">
<img src="static/picture/home.png"> > 信息查詢 > 個人信息
</div>
<div class="introduction">
<%-- 頭像--%>
<div class="intr-first">
<div class="head-image">
<img class="face_image" src="static/picture/6.jpg">
</div>
</div>
<%-- 學生信息遍歷--%>
<div class="intr-second">
<c:forEach var="info" items="${requestScope.info}">
<div class="subassemble">
<label class="sub-1">${info.key} </label>
<label class="sub-2">${info.value}</label>
</div>
</c:forEach>
</div>
</div>
</div>
</section>
</body>
</html>
4.2.2、 選課
學生選課會有兩種情況,一是處於選課時間,二是未在選課時間段。並且此處的限制是只選擇一門課,不可多選。
- 如何確定是否爲選課時間?
答:選課開啓是由管理員開啓的,即可以設置一個servletContext域對象,當管理員開啓選課時,則該域對象的值爲true,若關閉則爲false。當學生點擊選課時,對應的Servlet先獲取servletContext域對象並進行判斷,若爲true,則代表處在選課時間段,反之。
/**
* 設置是否是選課時間
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void isChooseTime(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String isChecked = req.getParameter("isChecked");
if (isChecked!=null && isChecked.equals("true")){
req.getServletContext().setAttribute("isTime",isChecked);
}
req.getRequestDispatcher("/page/system/systemSetting.jsp").forward(req,resp);
}
- 如何限定只選一門課?
答:使用JQuery爲選課圖標綁定一個點擊事件,當點擊選課時先獲取已選列表的數據對象,若已存在對象,即不爲null,則說明已選一門課,則alert()提示並返回false阻止點擊事件。
<script type="text/javascript">
$(function () {
//選課
$(".choose").click(function () {
var b = ${
requestScope.isChoose.cno};
if (b != null) {
alert("已選一門功課!請先退選!");
return false;
}
});
//退課
$(".delete").click(function () {
return confirm("確定刪除已選課程嗎?");
})
})
</script>
4.3、教師模塊
4.3.1、分數錄入
- 教師只可錄入其所教課程的成績
- 錄入方式,在這裏我使用的是input組件,直接進行錄入,錄入後修改對應的數據庫數據,並把input組件的默認值改成新的成績
4.4、管理員模塊
4.4.1 信息管理
管理員可以查看所有信息,同時對信息進行增刪查改的操作
-
信息查詢
-
添加信息
-
信息修改
-
添加信息的方式?
答:在項目中,通過css編寫“添加信息”組件,實現下拉動畫效果,當點擊添加信息時,會在當前頁面下方彈出一個添加框,填入一系列信息並點擊確定,將信息更新到數據庫中,並再由Servlet跳轉回當前信息查詢頁面。
4.4.2、數據報表
項目中的數據報表使用Echarts圖表,關於Echarts圖表的使用方式在博主首頁噢!先給大家看看效果o( ̄▽ ̄)o
5、其他小技巧
5.1、實現打印功能
打印功能可以使用第三方插件,或者直接調用window.print()方法打印,window.print()的好處是使用方便,只需要直接調用即可,但缺點是直接調用的話不能打印像Echarts的圖表,還有一些css樣式也需要重新設置。總結下來,若只是爲了簡單的打印網頁,沒有其他樣式要求,則可直接使用window.print(),若對打印樣式有需求,則需使用第三方插件。
- 利用 window.print() 打印指定部分的內容
在要打印的內容前面一行加上“< !–startprint-- >”,最後一行後面加上“< !–endprint-- >”,再給一個如button組件綁定下方的doPrint()事件即可。
function doPrint() {
bdhtml=window.document.body.innerHTML;
sprnstr="<!--startprint-->"; //開始打印標識字符串有17個字符
eprnstr="<!--endprint-->"; //結束打印標識字符串
prnhtml=bdhtml.substr(bdhtml.indexOf(sprnstr)+17); //從開始打印標識之後的內容
prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr)); //截取開始標識和結束標識之間的內容
window.document.body.innerHTML=prnhtml; //把需要打印的指定內容賦給body.innerHTML
window.print(); //調用瀏覽器的打印功能打印指定區域
window.document.body.innerHTML=bdhtml;//重新給頁面內容賦值
return false;
}
5.2、數據輸入約束性
- 儘可能地使用下拉列表組件(select-option),避免了手動輸入數據時數據不合法。
- 使用JS正則表達式輔助判斷數據的合法
function check() {
var options=$("#searchType option:selected").val();
var val = $("#searchInfo").val();
var number = /^\+?[1-9][0-9]*$/;//數字
if (options == "cno" || options == "priorId" || options == "credit"){
if (number.test(val))//判斷輸入的是否爲數字
return true;
else{
alert("內容輸入錯誤!")
return false;
}
}
return true;
}
5.3、全選\全不選
- 在Jsp上使用type爲checkbox的input組件,再給其添加綁定事件(如下)
//全選/全不選
$("#checkAll").click(function () {
let checked = document.getElementById("checkAll").checked;
if (checked==true){
<c:forEach items="${requestScope.CourseMap}" var="entry">
document.getElementById("${entry.value.id}").checked=true;
</c:forEach>
}else if (checked==false){
<c:forEach items="${requestScope.CourseMap}" var="entry">
document.getElementById("${entry.value.id}").checked=false;
</c:forEach>
}
})
5.4、批量刪除
- 獲取當前Jsp中已選中的數據編號,並將所有編號以一個字符(如s)作爲連接,將其連接成一段字符串,再把該字符串傳送到Servlet中,再在Service層對字符串以“s”作爲分隔符,將字符串分割後再逐一對每一個數據進行操作。
//批量刪除
$(".deleteAll").click(function () {
let array = new Array();
<c:forEach items="${requestScope.CourseMap}" var="entry">
if (document.getElementById("${entry.value.id}").checked==true){
array.push("${entry.value.id}");
}
</c:forEach>
let allcno=array[0];
for (let i = 1; i < array.length; i++) {
allcno += "s"+array[i];
}
if (array[0]!=null){
let b = confirm("確定刪除課程號"+allcno+"嗎?");
if (b==true){
location.href="http://localhost:8080/StudentsInfoSystem/systemCourseServlet?action=deleteMoreCourse&allcno="+allcno;
}
}
})
5.5、模糊查詢
- 模糊查詢這裏以MySQL爲例,主要使用“LIKE”關鍵詞,如要查詢學號中帶有10的學生,只需要輸入“10”即可,具體DAO層語句如下:
/**
* 通過學號查詢所有學生信息
* @return
*/
public List<Student> queryAllBySno(String sno){
String sql="select * from student where sno like ?";
return queryForList(Student.class,sql,sno);
}
6、總結
- 項目開發使用了三層架構,即“Web視圖層-Service業務層-Dao持久層”,分層的目的是爲了解耦,即降低代碼耦合度,便於後期的維護。
- 建議多使用工廠模式創建實例化對象,這樣便於當底層數據庫有所變動時,只需DAO層變動,無需每一個頁面都進行修改,大大降低了工作量。
- 要有封裝的思想,把重複的,常用的語句進行封裝,再調用,這樣代碼看起來更加清楚整潔,而且修改方便。
謝謝看完的你!有幫助記得點個贊噢!有問題可隨時評論或者私信博主交流!!o( ̄▽ ̄)o