iT邦幫忙

0

應用系統建置前準備工具 - GlobalConstants 系統基礎常數定義

  • 分享至 

  • xImage
  •  

GlobalConstants - 全域常數定義文檔

概述

GlobalConstants 是系統基礎常數定義類別,提供專案中常用的路徑、環境變數、加密設定等靜態常數。本類別所有成員皆為 static,方便全域存取,使用常數可保證跨平台一致性並方便集中管理。

***因為是系統全域變數,所以放在project 跟目錄 (package tw.lewishome.webapp) ***

專案相關程式

  • TypeConvert
  • NetUtils

第三方元件(Dependency)

主要功能

1. 路徑常數定義

  • 定義外部檔案資料夾、上傳、下載、預設路徑
  • 支援多種檔案操作場景

2. 系統識別常數

  • 專案套件名稱
  • 系統啟動時產生的唯一 UUID
  • 執行伺服器主機名稱

3. 環境變數管理

  • 提供系統可用環境變數清單
  • 支援 OS、Spring 屬性、容器變數的統一管理

4. 加密與安全設定

  • AES-256 加密鹽值與初始向量
  • RSA 金鑰配置
  • KeyStore 相關設定
  • JWT Secret Key 動態產生

5. Spring Boot 配置

  • Active Profile 設定
  • JWT Token 密鑰管理

常數定義說明

系統信息常數

USER_HOME

public static final String USER_HOME = System.getProperty("user.home");
  • 說明: 使用者主目錄
  • 用途: 用作檔案操作的基礎路徑
  • 範例: /Users/lewisC:\Users\lewis

ROOT_PACKAGE_NAME

public static final String ROOT_PACKAGE_NAME = GlobalConstants.class.getClass().getPackage().getName();
  • 說明: 專案根套件名稱
  • : tw.lewishome.webapp
  • 用途: 套件掃描、反射操作等

DEFAULT_CHAR_SET

public static final String DEFAULT_CHAR_SET = "UTF-8";
  • 說明: 預設字符集
  • 用途: 檔案讀寫、郵件編碼、加密解密
  • : UTF-8

SYSTEM_BOOT_UUID

public static final String SYSTEM_BOOT_UUID = UUID.randomUUID().toString().replaceAll("\\-", "");
  • 說明: 系統啟動時產生的唯一識別碼
  • 格式: 32 字元十六進位字串(去除連字符)

GlobalConstants (全域常數)

簡短說明

GlobalConstants 提供系統運行時會用到的全域常數(路徑、檔名、環境變數容器、加密鍵名等)。類別以全靜態成員設計,並在應用啟動期間由初始化流程補充動態值。

檔案位置: src/main/java/tw/lewishome/webapp/GlobalConstants.java

--

目錄

  • 概要
  • 常數清單(分類)
  • 使用範例
  • 初始化與注意事項
  • 相關類別

--

概要

  • 類型: 工具類(皆為 static)
  • 設計目標: 提供一致的路徑與鍵名、集中管理環境變數與啟動時候的安全參數

--

常數清單(重點)

以下列出專案中常用且應被直接引用的靜態常數(摘錄):

  • 系統資訊

    • USER_HOME — 使用者主目錄 (System.getProperty("user.home"))
    • ROOT_PACKAGE_NAME — 專案根套件名稱
    • DEFAULT_CHAR_SET — 預設字元集 ("UTF-8")
    • SYSTEM_BOOT_UUID — 啟動時產生的 UUID(去除 '-'
    • HOST_SERVER_NAME — 由 NetUtils.getHostName() 取得
  • 路徑與檔案名稱

    • EXTERNAL_FOLDER — 外部資料根目錄(USER_HOME + "/webappData")
    • UPLOAD_PATH / DOWNLOAD_PATH / DEFAULT_FOLDER_PATH
    • RSA_KEYFILE, KEY_STORE_FILE, PROPERTIES_FILE
  • 加密與設定鍵名

    • AES256_SALT_KEY, AES256_IV_KEY, AES256_PASSWORD_KEY
    • KEY_STORE_PASSWORD(啟動時由初始化填入)
    • JWT_SECRET(由 SYSTEM_BOOT_UUID 經 TypeConvert.stringToHexString() 轉換)
  • 動態容器

    • ENV_VAR — Map<String,String>,啟動時載入 OS / Spring / container / default.Properties
    • LIST_SYSTEM_ENDPOINT — 系統 EndPoint 列表

--

使用範例

  1. 讀取環境變數(SMTP 範例)
String host = GlobalConstants.ENV_VAR.get("SMTP_SERVER");
int port = Integer.parseInt(GlobalConstants.ENV_VAR.get("SMTP_PORT"));
  1. 構建上傳路徑
String dest = GlobalConstants.UPLOAD_PATH + userId + "/" + fileName;
FileUtils.byteArrayToFile(bytes, dest);

--

初始化與注意事項

  • 類別載入時 (JVM) 會初始化 final static 常數(如 USER_HOME, SYSTEM_BOOT_UUID)。
  • 應用啟動時(SystemApplicationListener)應負責:
    • 載入 ENV_VAR、設定 SYS_PROFILE_ACTIVE、設定 KEY_STORE_PASSWORD 等動態值

重要注意事項:

  • ENV_VAR 使用 HashMap,若在多執行緒情況下會有競爭風險,必要時應採同步或替換為 ConcurrentHashMap
  • JWT_SECRET 每次啟動會變動,既有 Token 在重啟後會失效——這是設計的一部分以提升安全性。

程式碼 GlobalConstants.java

package tw.lewishome.webapp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import tw.lewishome.webapp.base.utility.common.NetUtils;
import tw.lewishome.webapp.base.utility.common.TypeConvert;

/**
 * 系統基礎常數定義類別,提供專案中常用的路徑、環境變數、加密設定等靜態常數。
 *
 * 主要功能包含:
 * 1. 定義專案套件名稱。
 * 2. 定義外部檔案資料夾、上傳、下載、預設路徑。
 * 3. 提供系統可用環境變數清單及其說明。
 * 4. 系統啟動時產生的 UUID 及 JWT Secret Key。
 * 5. 系統 Spring Boot Profile、主機名稱等資訊。
 * 6. 預設加密相關設定(AES Salt、RSA Key、KeyStore)。
 *
 * 本類別所有成員皆為 static,方便全域存取。
 *
 * @author lewis
 */
public class GlobalConstants {

    /** Private constructor to prevent instantiation */
    private GlobalConstants() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated.");
    }
    /** Constant <code>USER_HOME=System.getProperty("user.home")</code> */
    public static final String USER_HOME = System.getProperty("user.home");
    /** Constant <code>PackageName="tw.lewishome.webapp"</code> */
    public static final String ROOT_PACKAGE_NAME = GlobalConstants.class.getClass().getPackage().getName();
    /** Constant <code>DefaultCharSet="UTF-8"</code> */
    public static final String DEFAULT_CHAR_SET = "UTF-8";
    /** base external file folder */
    public static final String EXTERNAL_FOLDER = USER_HOME + "/webappData";
    /** base file upload folder */
    public static final String UPLOAD_PATH = GlobalConstants.EXTERNAL_FOLDER + "/upload/";
    /** base file download folder */
    public static final String DOWNLOAD_PATH = GlobalConstants.EXTERNAL_FOLDER + "/download/";
    /** base file default folder */
    public static final String DEFAULT_FOLDER_PATH = GlobalConstants.EXTERNAL_FOLDER + "/default/";
    /** Default RSAKey File */
    public static final String RSA_KEYFILE = "RSAKey.properties";
    /** String to hold the KeyStore file */
    public static final String KEY_STORE_FILE = "KeyStore.jceks";
    /** String to hold the default properties file */
    public static final String PROPERTIES_FILE = "default.Properties";
    /** 啟動時產生 randomUUID 設定為 SystemBootUuid 變數。 */
    public static final String SYSTEM_BOOT_UUID = UUID.randomUUID().toString().replaceAll("\\-", "");

    // 以下是系統開啟時,由 SystemApplicationListener 設定的參數
    /** 系統Spring Boot active profile (ENV) */
    public static String SYS_PROFILE_ACTIVE = "DEV";
    /** Default AES256Salt Property Key*/
    public static String AES256_SALT_KEY = "AES256_SALT_KEY";
    /** Default AES256Salt IV Property Key*/
    public static String AES256_IV_KEY = "AES256_IVT_KEY";
    /** Default AES256Salt IV Property Key*/
    public static String AES256_PASSWORD_KEY = "AES256_PASSWORD_KEY";


    /** Default KeyStorePassword */
    public static String KEY_STORE_PASSWORD = "";
    /** 系統EndPoint清單 */
    public static List<String> LIST_SYSTEM_ENDPOINT = new ArrayList<>();

    /**
     * 系統可用的環境變數清單,無須每次使用時再讀取資料
     * (OS_Environment_Variables/Spring_Properties/container_variables/default.Properties)
     */
    public static Map<String, String> ENV_VAR = new HashMap<>();

    /** 執行Server name (host name) */
    public static String HOST_SERVER_NAME = NetUtils.getHostName();

    /**
     * <pre>
     * 系統產出 JWT Token 時的,secret key string,設計每次開機變更
     * 所以,由SystemApplicationListener 取的RandomUUid後加密指定
     * </pre>
     */
    public static String JWT_SECRET = TypeConvert.stringToHexString(SYSTEM_BOOT_UUID);

}

單元測試程式碼 GlobalConstantsTest.java


package tw.lewishome.webapp;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

/**
 * GlobalConstants 的單元測試類別
 */
class GlobalConstantsTest {


    @Test
    void testConstantsNotNullOrEmpty() {
        assertNotNull(GlobalConstants.USER_HOME);
        assertFalse(GlobalConstants.USER_HOME.isEmpty());

        assertEquals("UTF-8", GlobalConstants.DEFAULT_CHAR_SET);

        assertTrue(GlobalConstants.EXTERNAL_FOLDER.contains(GlobalConstants.USER_HOME));
        assertTrue(GlobalConstants.UPLOAD_PATH.endsWith("/upload/"));
        assertTrue(GlobalConstants.DOWNLOAD_PATH.endsWith("/download/"));
        assertTrue(GlobalConstants.DEFAULT_FOLDER_PATH.endsWith("/default/"));

        assertEquals("RSAKey.properties", GlobalConstants.RSA_KEYFILE);
        assertEquals("KeyStore.jceks", GlobalConstants.KEY_STORE_FILE);
        assertEquals("default.Properties", GlobalConstants.PROPERTIES_FILE);

        assertNotNull(GlobalConstants.SYSTEM_BOOT_UUID);
        assertEquals(32, GlobalConstants.SYSTEM_BOOT_UUID.length());
    }

    @Test
    void testDefaultMutableFields() {
        assertEquals("DEV", GlobalConstants.SYS_PROFILE_ACTIVE);
        assertEquals("AES256_SALT_KEY", GlobalConstants.AES256_SALT_KEY);
        assertEquals("AES256_IVT_KEY", GlobalConstants.AES256_IV_KEY);
        assertEquals("AES256_PASSWORD_KEY", GlobalConstants.AES256_PASSWORD_KEY);
        assertEquals("", GlobalConstants.KEY_STORE_PASSWORD);

        assertNotNull(GlobalConstants.LIST_SYSTEM_ENDPOINT);
        assertTrue(GlobalConstants.LIST_SYSTEM_ENDPOINT.isEmpty());

        assertNotNull(GlobalConstants.ENV_VAR);
        assertTrue(GlobalConstants.ENV_VAR.isEmpty());
    }

    @Test
    void testHostServerNameNotNull() {
        assertNotNull(GlobalConstants.HOST_SERVER_NAME);
        assertFalse(GlobalConstants.HOST_SERVER_NAME.isEmpty());
    }

    @Test
    void testJwtSecretIsHexOfSystemBootUuid() {
        String uuid = GlobalConstants.SYSTEM_BOOT_UUID;
        String jwtSecret = GlobalConstants.JWT_SECRET;
        // Should be twice the length of uuid if hex encoding
        assertEquals(uuid.length() * 2, jwtSecret.length());
        // Should only contain hex characters
        assertTrue(jwtSecret.matches("[0-9A-Fa-f]+"));
    }

    @Test
    void testPrivateConstructor() {
        assertThrows(IllegalAccessException.class, () -> {
            GlobalConstants.class.getDeclaredConstructor().newInstance();
        });
    }

    @Test
    void testMutableFieldsCanBeChanged() {
        GlobalConstants.SYS_PROFILE_ACTIVE = "TEST";
        assertEquals("TEST", GlobalConstants.SYS_PROFILE_ACTIVE);

        GlobalConstants.AES256_SALT_KEY = "NEW_SALT";
        assertEquals("NEW_SALT", GlobalConstants.AES256_SALT_KEY);

        GlobalConstants.LIST_SYSTEM_ENDPOINT.add("/api/test");
        assertTrue(GlobalConstants.LIST_SYSTEM_ENDPOINT.contains("/api/test"));

        GlobalConstants.ENV_VAR.put("KEY", "VALUE");
        assertEquals("VALUE", GlobalConstants.ENV_VAR.get("KEY"));
    }
}

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言