diff --git a/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/banner/EnvironmentBanner.java b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/banner/EnvironmentBanner.java new file mode 100644 index 0000000..26307ea --- /dev/null +++ b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/banner/EnvironmentBanner.java @@ -0,0 +1,70 @@ +package cn.meowrain.aioj.backend.framework.banner; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.lang.management.ManagementFactory; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Slf4j +@Component +public class EnvironmentBanner implements ApplicationListener { + + @Value("${spring.application.name:unknown}") + private String appName; + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + + Environment env = event.getApplicationContext().getEnvironment(); + + // Active profiles + String profiles = String.join(",", env.getActiveProfiles()); + if (profiles.isEmpty()) { + profiles = "default"; + } + + // Port + String port = env.getProperty("server.port", "unknown"); + + // JVM info + String jvm = System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")"; + + // PID + String pid = ManagementFactory.getRuntimeMXBean().getPid() + ""; + + // Time + String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + // Git commit id (如果没有 git.properties,不会报错) + String gitCommit = env.getProperty("git.commit.id.abbrev", "N/A"); + + printBanner(appName, profiles, port, jvm, pid, time, gitCommit); + } + + private void printBanner(String appName, + String profiles, + String port, + String jvm, + String pid, + String time, + String gitCommit) { + + String banner = "\n" + + "------------------------------------------------------------\n" + + " ✨AI Online Judge✨ - " + appName + "\n" + + " Environment : " + profiles + "\n" + + " Port : " + port + "\n" + + " Git Commit : " + gitCommit + "\n" + + " JVM : " + jvm + "\n" + + " PID : " + pid + "\n" + + " Started At : " + time + "\n" + + "------------------------------------------------------------\n"; + System.out.println(banner); + } +} diff --git a/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/AbstractChianHandler.java b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/AbstractChianHandler.java new file mode 100644 index 0000000..f6d93da --- /dev/null +++ b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/AbstractChianHandler.java @@ -0,0 +1,19 @@ +package cn.meowrain.aioj.backend.framework.designpattern.chains; + +import org.springframework.core.Ordered; + +public interface AbstractChianHandler extends Ordered { + /** + * 执行责任链逻辑 + * + * @param requestParam 责任链执行入参 + */ + void handle(T requestParam); + + /** + * 责任链组件标识 + * + * @return String + */ + String mark(); +} diff --git a/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/CommonChainContext.java b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/CommonChainContext.java new file mode 100644 index 0000000..aef1774 --- /dev/null +++ b/aioj-backend-common/src/main/java/cn/meowrain/aioj/backend/framework/designpattern/chains/CommonChainContext.java @@ -0,0 +1,71 @@ +package cn.meowrain.aioj.backend.framework.designpattern.chains; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 公共责任链容器 + * + * @param + */ +@Component +@Slf4j +public class CommonChainContext implements ApplicationContextAware, CommandLineRunner { + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + private final Map>> abstractChainHandlerMap = new HashMap<>(); + + public void handler(String mark, T requestParam) { + List> merchantAdminAbstractChainHandlers = abstractChainHandlerMap.get(mark); + if (merchantAdminAbstractChainHandlers == null || merchantAdminAbstractChainHandlers.isEmpty()) { + throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark)); + } + merchantAdminAbstractChainHandlers.forEach(h -> { + h.handle(requestParam); + }); + } + + @Override + public void run(String... args) throws Exception { + log.info("【责任链路初始化】开始加载并分组所有处理器..."); + applicationContext.getBeansOfType(AbstractChianHandler.class) + .values() + .forEach(handler -> { + // 打印当前处理器的类名和它所属的 ChainMark + String handlerName = handler.getClass().getSimpleName(); + String mark = handler.mark(); + log.info(" -> 发现处理器:{},归属链路:{}", handlerName, mark); + abstractChainHandlerMap + .computeIfAbsent(handler.mark(), k -> new ArrayList<>()) + .add(handler); + }); + + // 步骤 2: 对每个链路中的处理器进行排序 (Sort 阶段) + abstractChainHandlerMap.forEach((mark, handlers) -> { + handlers.sort(Comparator.comparing(Ordered::getOrder)); + + // 打印排序后的 Bean 列表 + String sortedList = handlers.stream() + .map(h -> String.format("%s (Order:%d)", h.getClass().getSimpleName(), h.getOrder())) + .collect(Collectors.joining(" -> ")); + + log.info(" ✅ 链路 {} 排序完成:{}", mark, sortedList); + }); + + log.info("【责任链路初始化】所有处理器链已完全就绪。"); + } + +}