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

Java Web MVC 登入系統實作:Session 監聽器、Filter 過濾器與線上人數統計

     編輯:程式設計綜合問答

專案需求分析

建立一個基於 JSP/Servlet 的 MVC 登入系統,需包含以下核心功能:

  • 使用者登入驗證 (不使用資料庫,以 Collection 模擬)
  • 登入成功導向主頁面,顯示當前線上人數
  • 使用 HttpSessionListener 監聽 Session 建立/銷毀,即時統計線上人數
  • 使用 Filter 進行權限控管:已登入放行、未登入導向登入頁
  • 處理重複登入、登出等邊界情況

專案結構規劃

src/
├── controller/
│   ├── LoginServlet.java
│   ├── LogoutServlet.java
│   └── MainServlet.java
├── filter/
│   └── AuthFilter.java
├── listener/
│   └── OnlineCounterListener.java
├── model/
│   └── User.java
└── util/
    └── UserStore.java   // 以 Map 模擬使用者資料
web/
├── login.jsp
├── main.jsp
└── error.jsp

核心元件實作

1. 模擬使用者資料存儲

public class UserStore {
    private static final Map USERS = new ConcurrentHashMap<>();
    static {
        USERS.put("admin", new User("admin", "123456", "管理員"));
        USERS.put("user1", new User("user1", "111111", "測試用戶"));
    }
    public static User validate(String username, String password) {
        User u = USERS.get(username);
        return (u != null && u.getPassword().equals(password)) ? u : null;
    }
}

2. Session 監聽器 - 線上人數統計

@WebListener
public class OnlineCounterListener implements HttpSessionListener {
    private static final AtomicInteger onlineCount = new AtomicInteger(0);

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        onlineCount.incrementAndGet();
        se.getSession().getServletContext().setAttribute("onlineCount", onlineCount.get());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        onlineCount.decrementAndGet();
        se.getSession().getServletContext().setAttribute("onlineCount", onlineCount.get());
    }

    public static int getOnlineCount() { return onlineCount.get(); }
}

3. 權限過濾器

@WebFilter("/*")
public class AuthFilter implements Filter {
    private static final Set EXCLUDE_PATHS = Set.of("/login.jsp", "/login", "/logout", "/css/", "/js/", "/error.jsp");

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        String path = request.getRequestURI().substring(request.getContextPath().length());

        // 靜態資源與排除路徑直接放行
        if (EXCLUDE_PATHS.stream().anyMatch(path::startsWith)) {
            chain.doFilter(req, res);
            return;
        }

        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("user") != null) {
            chain.doFilter(req, res); // 已登入
        } else {
            response.sendRedirect(request.getContextPath() + "/login.jsp"); // 未登入導向登入頁
        }
    }
}

4. 登入 Servlet

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        User user = UserStore.validate(username, password);

        if (user != null) {
            HttpSession session = req.getSession();
            // 防止重複登入:若舊 session 存在則使其失效 (可選)
            session.setAttribute("user", user);
            resp.sendRedirect(req.getContextPath() + "/main");
        } else {
            req.setAttribute("error", "帳號或密碼錯誤");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }
}

5. 主頁面 JSP (顯示線上人數)

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<body>
  <h1>歡迎, ${sessionScope.user.username} (<span style="color:red">${sessionScope.user.realName}</span>)</h1>
  <p>目前線上人數: ${applicationScope.onlineCount}</p>
  <a href="${pageContext.request.contextPath}/logout">登出</a>
</body>
</html>

進階:處理重複登入 (單一帳號同一時間僅允許一處登入)

在 HttpSessionListener 中維護 Map usernameToSessionId,當新 Session 建立時檢查該帳號是否已有對應 Session,若有則手動 invalidate() 舊 Session。

部署與測試

  1. 打包為 WAR 部署至 Tomcat 9+
  2. 開啟多瀏覽器/無痕視窗測試並發登入
  3. 觀察主頁面線上人數是否即時更新
  4. 測試直接輸入受保護網址是否被 Filter 攔截導向登入頁

總結

本範例展示了純 Servlet/JSP 實作 MVC 登入系統的完整架構:Listener 負責全域狀態統計、Filter 集中處理認證授權、Servlet 處理業務流程、JSP 僅負責視圖渲染。不依賴資料庫、框架,適合教學與輕量級專案快速原型開發。

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