feat: 设计模式-责任链模块

This commit is contained in:
2025-11-17 23:44:26 +08:00
parent b6b9624b91
commit 00b7d95159
3 changed files with 160 additions and 0 deletions

View File

@@ -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<ApplicationReadyEvent> {
@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);
}
}

View File

@@ -0,0 +1,19 @@
package cn.meowrain.aioj.backend.framework.designpattern.chains;
import org.springframework.core.Ordered;
public interface AbstractChianHandler<T> extends Ordered {
/**
* 执行责任链逻辑
*
* @param requestParam 责任链执行入参
*/
void handle(T requestParam);
/**
* 责任链组件标识
*
* @return String
*/
String mark();
}

View File

@@ -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 <T>
*/
@Component
@Slf4j
public class CommonChainContext<T> implements ApplicationContextAware, CommandLineRunner {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
private final Map<String, List<AbstractChianHandler<T>>> abstractChainHandlerMap = new HashMap<>();
public void handler(String mark, T requestParam) {
List<AbstractChianHandler<T>> 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("【责任链路初始化】所有处理器链已完全就绪。");
}
}