本指南面向希望参与 JPrompt 项目开发、贡献代码或深入理解框架原理的开发者。
-
JDK 17+
java -version # 确保版本 >= 17 -
Maven 3.6+
mvn -version # 确保版本 >= 3.6 -
IDE 推荐
- IntelliJ IDEA (推荐)
- Eclipse
- VS Code + Java Extension Pack
-
安装插件
- Lombok Plugin
- Maven Helper
- CamelCase (可选)
-
配置设置
- Settings → Build → Compiler → Annotation Processors
- ✅ Enable annotation processing
- Settings → Build → Build Tools → Maven
- Maven home directory: 指向本地 Maven 安装路径
- User settings file: ~/.m2/settings.xml
- Settings → Build → Compiler → Annotation Processors
-
代码样式
- 导入 Google Java Style Guide 配置
- Settings → Editor → Code Style → Java → Import Scheme
-
安装插件
- M2Eclipse (Maven 集成)
- Lombok Installer
- Spring Tools
-
配置
- Window → Preferences → Java → Compiler
- Compiler compliance level: 17
- Window → Preferences → Maven
- User Settings: ~/.m2/settings.xml
- Window → Preferences → Java → Compiler
git clone https://github.com/CalmChih/JPrompt.git
cd JPrompt# 清理并编译
mvn clean compile
# 运行测试
mvn test
# 打包(跳过测试)
mvn clean package -DskipTests
# 完整构建(包含测试和文档)
mvn clean install
# 跳过检查(快速构建)
mvn clean install -DskipTests -Dcheckstyle.skip将项目安装到本地 Maven 仓库,以便其他项目引用:
mvn clean install# 方式一: 使用 Maven 插件
mvn spring-boot:run -pl JPrompt-demo
# 方式二: 先打包再运行
mvn clean package -pl JPrompt-demo
java -jar JPrompt-demo/target/JPrompt-demo-1.0.0.jarJPrompt/
├── JPrompt-core/ # 核心引擎模块(零 Spring 依赖)
│ ├── src/main/java/
│ │ └── com/chih/JPrompt/core/
│ │ ├── annotation/ # 注解定义
│ │ ├── engine/ # 核心引擎
│ │ ├── spi/ # SPI 接口
│ │ ├── impl/ # 核心实现
│ │ ├── domain/ # 领域模型
│ │ ├── support/ # 支持类
│ │ └── exception/ # 异常体系
│ └── src/test/java/ # 单元测试
│
├── JPrompt-spring-boot-starter/ # Spring Boot 集成
│ ├── src/main/java/
│ │ └── com/chih/JPrompt/spring/
│ │ ├── scan/ # Mapper 扫描
│ │ ├── health/ # 健康检查
│ │ └── metrics/ # 监控指标
│ └── src/test/java/ # 集成测试
│
└── JPrompt-demo/ # 演示应用
├── src/main/java/
│ └── com/chih/JPrompt/demo/
│ ├── mapper/ # 示例 Mapper
│ ├── controller/ # REST API
│ └── dto/ # 数据传输对象
└── src/main/resources/
└── prompts/ # 提示词模板
annotation/ - 注解定义
@PromptMapper- 标记 Mapper 接口@Prompt- 关联 Prompt Key@Param- 指定参数名
engine/ - 核心引擎
PromptManager- Prompt 管理器,协调 Source 和 CachePromptMapperFactory- 动态代理工厂
spi/ - SPI 扩展接口
PromptSource- Prompt 来源接口TemplateEngine- 模板引擎接口PromptMetrics- 监控指标接口
impl/ - 核心实现
FilePromptSource- 文件系统 Prompt 源MustacheTemplateEngine- Mustache 模板引擎NoOpPromptMetrics- 空操作的监控实现
domain/ - 领域模型
PromptMeta- Prompt 元数据
support/ - 支持类
FileResource- 文件资源封装PromptParser- Prompt 解析器
exception/ - 异常体系
PromptNotFoundException- Prompt 未找到异常PromptRenderException- Prompt 渲染异常
scan/ - Mapper 扫描机制
ClassPathPromptMapperScanner- 类路径扫描器PromptFactoryBean- Mapper 工厂 Bean
health/ - 健康检查
JPromptHealthIndicator- 健康检查指示器
metrics/ - 监控指标
MicrometerPromptMetrics- Micrometer 指标适配
自动配置
PromptAutoConfiguration- 核心自动配置类JPromptProperties- 配置属性绑定
关键规范:
- 缩进: 使用 2 个空格(不使用 Tab)
- 行宽: 每行最多 100 个字符
- 命名:
- 类名: UpperCamelCase (如
PromptManager) - 方法名: lowerCamelCase (如
renderPrompt) - 常量: UPPER_SNAKE_CASE (如
MAX_SIZE) - 包名: 全小写,点分隔 (如
com.chih.JPrompt.core)
- 类名: UpperCamelCase (如
- 大括号:
- 左大括号不换行
- 右大括号换行
- 即使只有一条语句也使用大括号
示例:
// ✅ 正确
public class Example {
private static final int MAX_SIZE = 100;
public void process(String input) {
if (input == null) {
throw new IllegalArgumentException("Input cannot be null");
}
// ...
}
}
// ❌ 错误
public class example {
private static final int max_size = 100;
public void process(String input) {
if (input == null) throw new IllegalArgumentException();
}
}所有公共类、方法、字段都必须包含 JavaDoc 注释。
格式:
/**
* 简洁的一句话描述。
*
* <p>详细说明(可选)。</p>
*
* <h3>使用示例:</h3>
* <pre>{@code
* // 示例代码
* Example.example();
* }</pre>
*
* @param paramName 参数说明
* @return 返回值说明
* @throws ExceptionName 异常说明
* @author 作者名
* @since 版本号
*/
public String exampleMethod(String paramName) throws Exception {
// 实现
}使用 // 进行单行注释,使用 /* */ 进行多行注释。
示例:
// 1. 创建缓存
Cache<String, String> cache = Caffeine.newBuilder().build();
// 2. 加载数据
String data = loadData();
/*
* 复杂的逻辑说明
* 包含多行解释
*/
for (String item : items) {
process(item);
}遵循 Conventional Commits 规范。
格式:
<type>(<scope>): <subject>
<body>
<footer>
Type 类型:
feat- 新功能fix- Bug 修复docs- 文档更新style- 代码格式调整refactor- 重构(不改变功能)test- 测试相关chore- 构建/工具链相关
示例:
feat(core): add support for partial templates
- Implement {{> partial}} syntax in Mustache engine
- Add dependency tracking for cascading updates
- Update documentation with examples
Closes #123
src/test/java/
└── com/chih/JPrompt/core/
├── engine/ # 引擎测试
│ ├── PromptManagerTest.java
│ └── PromptMapperFactoryTest.java
├── spi/ # SPI 测试
│ └── TemplateEngineTest.java
└── integration/ # 集成测试
└── HotReloadTest.java
命名规范: 类名 + Test.java
示例:
class PromptManagerTest {
private PromptManager manager;
private PromptSource mockSource;
@BeforeEach
void setUp() {
mockSource = mock(PromptSource.class);
manager = new PromptManager(mockSource);
}
@Test
@DisplayName("应该成功渲染 Prompt")
void shouldRenderPromptSuccessfully() {
// Given
String key = "greeting";
Map<String, Object> vars = Map.of("name", "Alice");
// When
String result = manager.render(key, vars);
// Then
assertThat(result).contains("Alice");
}
@Test
@DisplayName("当 Prompt 不存在时应该抛出异常")
void shouldThrowExceptionWhenPromptNotFound() {
// Given
String key = "nonexistent";
// When & Then
assertThatThrownBy(() -> manager.render(key, Map.of()))
.isInstanceOf(PromptNotFoundException.class)
.hasMessageContaining(key);
}
}命名规范: 功能描述 + IntegrationTest.java
示例:
@SpringBootTest
class HotReloadIntegrationTest {
@Autowired
private PromptManager manager;
@Test
@DisplayName("应该支持热更新 Prompt")
void shouldSupportHotReload() throws IOException, InterruptedException {
// Given
Path promptFile = Paths.get("./prompts/test.yaml");
String originalContent = Files.readString(promptFile);
// When
modifyFile(promptFile, "updated content");
Thread.sleep(1000); // 等待热更新生效
// Then
String result = manager.render("test", Map.of());
assertThat(result).contains("updated");
// Cleanup
Files.writeString(promptFile, originalContent);
}
}使用 JUnit 5 并发测试和 Awaitility 等待异步操作。
示例:
@Test
@DisplayName("应该支持并发渲染")
void shouldSupportConcurrentRendering() throws InterruptedException {
// Given
int threadCount = 10;
int callsPerThread = 100;
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
CountDownLatch latch = new CountDownLatch(threadCount);
// When
for (int i = 0; i < threadCount; i++) {
executor.submit(() -> {
try {
for (int j = 0; j < callsPerThread; j++) {
manager.render("greeting", Map.of("name", "User" + j));
}
} finally {
latch.countDown();
}
});
}
// Then
assertTrue(latch.await(30, TimeUnit.SECONDS));
executor.shutdown();
}目标: 核心模块测试覆盖率 > 85%
查看覆盖率:
mvn clean test jacoco:report
# 报告路径: target/site/jacoco/index.html使用 JMH (Java Microbenchmark Harness) 进行微基准测试。
依赖配置:
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
<scope>test</scope>
</dependency>基准测试示例:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class PromptManagerBenchmark {
private PromptManager manager;
private Map<String, Object> variables;
@Setup
public void setup() {
PromptSource source = new FilePromptSource("/prompts");
manager = new PromptManager(source);
variables = Map.of("name", "Alice");
}
@Benchmark
public String benchmarkRender() {
return manager.render("greeting", variables);
}
}运行基准测试:
mvn clean test -jar target/benchmarks.jar-
减少锁竞争
- 使用读写锁替代全局 synchronized
- 缩小锁的范围
- 使用并发集合(ConcurrentHashMap)
-
缓存优化
- 使用 Caffeine 替代 Guava Cache
- 配置合理的缓存大小和过期策略
- 避免缓存雪崩
-
内存优化
- 使用 Index-Only 模式,避免缓存原始内容
- 及时释放大对象
- 使用对象池减少 GC 压力
-
IO 优化
- 使用 NIO 进行文件操作
- 批量读取减少 IO 次数
- 使用缓冲流
在 application.yml 中配置日志级别:
logging:
level:
com.chih.JPrompt: DEBUG
com.chih.JPrompt.core.engine: TRACE
com.chih.JPrompt.core.impl: DEBUG启动参数:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar app.jarIDE 配置:
- Run → Edit Configurations → Remote → Debug
- Host: localhost, Port: 5005
-
条件断点: 只在满足条件时暂停
右键断点 → Edit Breakpoint → Condition: variables.size() > 100 -
日志断点: 打印日志而不暂停
右键断点 → Edit Breakpoint → Log evaluated expression -
异常断点: 捕获特定异常
Run → View Breakpoints → Java Exception Breakpoints 添加: PromptNotFoundException
格式: MAJOR.MINOR.PATCH
- MAJOR: 不兼容的 API 变更
- MINOR: 向后兼容的功能新增
- PATCH: 向后兼容的 Bug 修复
示例: 1.0.0, 1.1.0, 1.1.1
-
更新版本号
# 更新所有模块的 pom.xml mvn versions:set -DnewVersion=1.0.1 -
更新文档
- 更新 README.md 中的版本号
- 更新 CHANGELOG.md
-
运行测试
mvn clean test -
打包
mvn clean package -DskipTests
-
发布到 Maven Central
mvn deploy -P release
-
打标签
git tag -a v1.0.1 -m "Release version 1.0.1" git push origin v1.0.1 -
发布 GitHub Release
- 在 GitHub 上创建 Release
- 上传构建产物
- 编写 Release Notes
A: 使用文件监听日志和断点:
logging:
level:
com.chih.JPrompt.core.impl.FilePromptSource: TRACE在 PromptManager.handleIncrementalUpdate 方法设置断点。
A: 使用 JMH 基准测试或 JUnit 并发测试:
ExecutorService executor = Executors.newFixedThreadPool(10);
// ... 并发测试逻辑A: 实现 SPI 接口并注册为 Spring Bean:
@Component
public class CustomPromptSource implements PromptSource {
// ...
}