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

JSP Application 內置對象實現網站訪問計數器完整示例

     編輯:Java 綜合教學

場景

利用 JSP application 內置對象(對應 ServletContext)的生命周期特性:隨 Web 應用啟動而創建,隨應用關閉而銷毀,全局唯一、多用戶共享,實現簡單的全站訪問計數器。

完整代碼 counter.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>訪問計數器演示</title>
</head>
<body>
<%
    // 1. 讀取初始化參數(需在 web.xml 中配置 <context-param>)
    String initParam = application.getInitParameter("test2");
    out.print("test2=" + initParam + "<br>");

    // 2. 從 application 域獲取計數器
    Object obj = application.getAttribute("count");

    // 3. 首次訪問初始化
    if (obj == null) {
        application.setAttribute("count", 1);
        obj = 1;
    }

    // 4. 計數器遞增
    long count = Long.parseLong(obj.toString());
    count++;

    // 5. 輸出當前計數
    out.print("count=" + count);

    // 6. 更新回 application 域,供下次訪問使用
    application.setAttribute("count", count);
%>
</body>
</html>

關鍵點解析

方法/屬性說明
application.getInitParameter(name)讀取 web.xml 中 <context-param> 定義的全局初始化參數。
application.getAttribute(name)從 ServletContext 獲取屬性值,返回 Object,需轉型。
application.setAttribute(name, value)向 ServletContext 存放屬性,全局可見,線程不安全。

線程安全隱患與改進

上述代碼在高併發下存在競態條件:多線程同時讀取舊值、遞增、寫回,導致計數丟失。生產環境建議:

方案一:使用 AtomicLong(推薦)

<%
    // 初始化階段(可放在 ServletContextListener 中)
    AtomicLong counter = (AtomicLong) application.getAttribute("counter");
    if (counter == null) {
        counter = new AtomicLong(0);
        application.setAttribute("counter", counter);
    }
    long current = counter.incrementAndGet(); // 原子遞增
    out.print("count=" + current);
%>

方案二:同步塊(舊版本兼容)

<%
    synchronized (application) {
        Object obj = application.getAttribute("count");
        long count = (obj == null) ? 1 : Long.parseLong(obj.toString()) + 1;
        application.setAttribute("count", count);
        out.print("count=" + count);
    }
%>

web.xml 配置初始化參數(可選)

<context-param>
    <param-name>test2</param-name>
    <param-value>init-value-demo</param-value>
</context-param>

總結

  • application 域適合存放全局共享、讀多寫少的數據(如配置、緩存、計數器)。
  • 計數器等寫入場景必須考慮線程安全,優先選 AtomicLong 或 LongAdder(Java 8+)。
  • 生產級計數器建議持久化到 Redis/數據庫,防止重啟歸零。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved