1. 程式人生 > 實用技巧 >基於Servlet、JSP的學生管理系統(附完整原始碼)

基於Servlet、JSP的學生管理系統(附完整原始碼)

起因

最近重溫servlet,想到了大學時期用同一個“學生管理系統”水了幾門課的課程設計,不免感慨萬千。

週末簡單的寫了個介面,建了幾張表,做了一個小系統(試圖找一找當年划水的感覺,可惜沒找到)。

寫的比較簡單,不過做個普通的課程設計應該夠了,需要的可以自取。

原始碼地址

https://gitee.com/DayCloud/student-manage

介面截圖

主介面

管理員介面

學生管理(管理員視角)

新增系統使用者(管理員視角)

學生主頁

學生個人資訊

目錄結構

執行環境

tomcat9

jdk1.8

其他依賴jar包見WEB-INF下面的lib資料夾。

涉及技術:Servlet、JSP、BootStrap、Jquery(較少)

主要功能

系統有兩個角色,管理員和學生。做的比較簡單,沒有建額外的角色表、許可權表,僅僅用了一個欄位區分。

管理員可以管理學生資訊、教師資訊、可以新增系統使用者,錄入成績,具有增刪改查的一切許可權。

學生只能檢視自己的分數,個人檔案等。

程式碼分析

首頁資料統計

系統執行時常、當前線上人數,這兩個功能用到了servlet的元件,監聽器。

通過繼承ServletContextListener, HttpSessionListener, HttpSessionAttributeListener等介面,可以完成對servlet上下文、session的建立銷燬等關鍵節點的監聽。

線上人數,必然是登入成功的人數。而session是有人訪問頁面就會建立,所以我們不能根據session的建立和銷燬來統計線上人數。

在登陸成功後,會在session裡新增一個變數,我們可以監聽這一行為。

當設定session變數的時候,線上人數+1

移除session變數的時候,線上人數-1。

當然這種做法還是有問題的,比如直接關閉瀏覽器,不點登出,資料統計就會失效,這裡不做深入探究。

再來說說系統執行時長,我的思路是servlet上下文建立的時候,記錄下那個時刻的時間戳。

後面用到的時候,直接用當前的時間戳減去儲存的時間戳,就可以計算出相隔的毫秒數,也就可以得到天數。

@WebListener
public class CustomServerListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {

    
private volatile ServletContext application = null; //上下文初始化,記錄當前時間的時間戳,初始化人數統計變數 @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("初始化開始---------"); int onlineNum = 0; application = sce.getServletContext(); application.setAttribute("onlineNum", onlineNum); application.setAttribute("startTime", new Date().getTime()); } @Override public void contextDestroyed(ServletContextEvent sce) { ServletContextListener.super.contextDestroyed(sce); } //session建立的時候呼叫該方法。但是我們計算線上人數指的是登入成功的人 @Override public void sessionCreated(HttpSessionEvent se) { } //連線斷開 @Override public void sessionDestroyed(HttpSessionEvent se) { } // @Override public void attributeAdded(HttpSessionBindingEvent se) { System.out.println("有人登入了---------"); int onlineNum = (int) application.getAttribute("onlineNum"); application.setAttribute("onlineNum", ++onlineNum); } @Override public void attributeRemoved(HttpSessionBindingEvent se) { System.out.println("有人退出了---------"); int onlineNum = (int) application.getAttribute("onlineNum"); application.setAttribute("onlineNum", --onlineNum); } @Override public void attributeReplaced(HttpSessionBindingEvent se) { } }

計算統計資料的servlet

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        StudentService studentService = new StudentService();
        CourseService courseService = new CourseService();
        ScoreService scoreService = new ScoreService();
        int studentNum = studentService.count();
        int courseNum = courseService.count();
        int onlineNum = (int) request.getServletContext().getAttribute("onlineNum");
        long startTime = (long) request.getServletContext().getAttribute("startTime");
        List<ScoreDto> scoreList = scoreService.getTopScoreList(10);
        
        int days = (int)((new Date().getTime() - startTime) / (1000*3600*24)) + 1;
        request.setAttribute("studentNum", studentNum);
        request.setAttribute("courseNum", courseNum);
        request.setAttribute("onlineNums", onlineNum);
        request.setAttribute("days", days);
        request.setAttribute("scores", scoreList);
        
        
        
        
        request.getRequestDispatcher("/WEB-INF/pages/main.jsp").forward(request, response);
    }

身份校驗

身份校驗自然就用到了過濾器。

這邊沒有做複雜的角色許可權校驗,僅僅在使用者表加上一個欄位表示區分。

兩個過濾器。

一個檢查使用者是否登入(有些頁面需要登入,有些不需要的可以放行)

另一個檢查許可權夠不夠。

@WebFilter(value = "/*")
public class LoginFilter implements Filter {

    private static List<String> passUrlList = Arrays.asList("login.jsp", "css"
            , "js", "jpg", "loginUrl");

    /**
     * Default constructor.
     */
    public LoginFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        String uri = req.getRequestURI();
        // 登入頁以及靜態資源放行
        boolean needLogin = true;
        //頁面名稱
        String pageName = "";
        //字尾名
        String endName = "";
        if(uri.lastIndexOf("/") != -1 && uri.lastIndexOf("/") + 1 < uri.length()) {
            pageName = uri.substring(uri.lastIndexOf("/") + 1);
        }
        
        if(uri.lastIndexOf(".") != -1 && uri.lastIndexOf(".") + 1 < uri.length()) {
            endName = uri.substring(uri.lastIndexOf(".") + 1);
        }
        
        for (String passUrl : passUrlList) {
            if(passUrl.equals(pageName) || passUrl.equals(endName)) {
                //不需要登入
                needLogin = false;
            }
        }
        
        User user = (User) req.getSession().getAttribute("loginUser");
        
        if(needLogin && user == null) {
            //該資源需要登入,並且當前使用者沒有登入
            resp.sendRedirect("/StudentManage/login.jsp");
        }else {
            //不需要登入
            chain.doFilter(req, resp);
        }

        
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

許可權校驗過濾器

@WebFilter(value = "/admin/*", filterName = "B")
public class AuthenticationFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub
        HttpServletRequest req = (HttpServletRequest) request;
        
        User user = (User) req.getSession().getAttribute("loginUser");
        Byte type = user.getUserType();
        if(type != 1) {
            //不是管理員,跳轉到錯誤頁面
            req.setAttribute("msg", "抱歉,您沒有許可權訪問!");
            req.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(req, response);;
        }else {
            chain.doFilter(req, response);
        }
    }

}

其他

整體上寫的隨心所欲,不是很規範。

查詢以及分頁介面做了,後臺沒做。因為感覺沒啥必要,原生的servlet知道基本原理和用法即可,寫業務直接SpringBoot吧。