GlobalConstants 是系統基礎常數定義類別,提供專案中常用的路徑、環境變數、加密設定等靜態常數。本類別所有成員皆為 static,方便全域存取,使用常數可保證跨平台一致性並方便集中管理。
***因為是系統全域變數,所以放在project 跟目錄 (package tw.lewishome.webapp) ***
USER_HOMEpublic static final String USER_HOME = System.getProperty("user.home");
/Users/lewis 或 C:\Users\lewis
ROOT_PACKAGE_NAMEpublic static final String ROOT_PACKAGE_NAME = GlobalConstants.class.getClass().getPackage().getName();
tw.lewishome.webapp
DEFAULT_CHAR_SETpublic static final String DEFAULT_CHAR_SET = "UTF-8";
UTF-8
SYSTEM_BOOT_UUIDpublic static final String SYSTEM_BOOT_UUID = UUID.randomUUID().toString().replaceAll("\\-", "");
GlobalConstants 提供系統運行時會用到的全域常數(路徑、檔名、環境變數容器、加密鍵名等)。類別以全靜態成員設計,並在應用啟動期間由初始化流程補充動態值。
檔案位置: src/main/java/tw/lewishome/webapp/GlobalConstants.java
--
--
--
以下列出專案中常用且應被直接引用的靜態常數(摘錄):
系統資訊
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.PropertiesLIST_SYSTEM_ENDPOINT — 系統 EndPoint 列表--
String host = GlobalConstants.ENV_VAR.get("SMTP_SERVER");
int port = Integer.parseInt(GlobalConstants.ENV_VAR.get("SMTP_PORT"));
String dest = GlobalConstants.UPLOAD_PATH + userId + "/" + fileName;
FileUtils.byteArrayToFile(bytes, dest);
--
final static 常數(如 USER_HOME, SYSTEM_BOOT_UUID)。SystemApplicationListener)應負責:
ENV_VAR、設定 SYS_PROFILE_ACTIVE、設定 KEY_STORE_PASSWORD 等動態值重要注意事項:
ENV_VAR 使用 HashMap,若在多執行緒情況下會有競爭風險,必要時應採同步或替換為 ConcurrentHashMap。JWT_SECRET 每次啟動會變動,既有 Token 在重啟後會失效——這是設計的一部分以提升安全性。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);
}
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"));
}
}