3. 开发环境搭建与项目初始化
说实话,很多新手在审计SDK改造上栽跟头,不是因为代码写不出来,而是环境没搭好就开始写。我曾经见过一个团队,因为protobuf版本冲突,排查了整整两天。嗯,这种事完全可以避免。
今天我们就来把这套环境彻底捋顺。你跟着我走一遍,后面三十章基本不会在构建上卡壳。
3.1 构建工具选型:Maven还是Gradle?
我个人习惯用Maven做企业级项目。原因很简单:稳定、可复现、生态成熟。审计SDK通常会集成到客户的已有平台里,客户的平台十有八九是Maven,你用Gradle反而增加适配成本。
当然,这不是说Gradle不好。如果你追求极致的构建速度,或者项目本身就在Gradle生态里,选Gradle完全没问题。我这边以Maven为例展开,但会同时给出Gradle的等效配置。
| 对比维度 | Maven | Gradle |
|---|---|---|
| 学习曲线 | 平缓,XML配置容易理解 | 稍陡,Groovy/Kotlin DSL需要适应 |
| 构建速度 | 中等 | 更快(增量编译、构建缓存) |
| 企业普及率 | 极高 | 中等,常见于新项目 |
| 依赖管理 | 成熟,Maven Central | 兼容Maven仓库,语法更灵活 |
3.2 创建Maven项目
咱们从零开始。我建议用maven-archetype-quickstart原型来创建项目骨架。直接在命令行里跑:
mvn archetype:generate \
-DgroupId=com.example.audit \
-DartifactId=audit-sdk-core \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
生成后的目录结构应该是这样的:
audit-sdk-core/
├── pom.xml
└── src/
├── main/java/com/example/audit/
└── test/java/com/example/audit/
你想想看,这个骨架其实就两个目录。但改造后的SDK会比这个复杂得多——后面我们会加模块、加SPI接口、加插件加载器。所以一开始就把目录理清楚,能省很多回头路。
3.3 核心依赖清单
下面这张表是我从实际项目里提炼出来的。每个依赖都有明确的用途,不搞多余的东西。
| 依赖坐标 | 版本 | 用途 |
|---|---|---|
com.google.protobuf:protobuf-java |
3.21.12 | 审计事件的序列化 |
com.google.protobuf:protobuf-java-util |
3.21.12 | JSON与Protobuf互转 |
org.slf4j:slf4j-api |
2.0.9 | 日志门面 |
ch.qos.logback:logback-classic |
1.4.11 | 日志实现 |
com.fasterxml.jackson.core:jackson-databind |
2.15.2 | JSON解析/格式化 |
org.apache.commons:commons-lang3 |
3.12.0 | 字符串、枚举等工具 |
junit:junit |
4.13.2 | 单元测试 |
你可能会问,为什么审计SDK要依赖protobuf?其实很多企业级审计系统都用Protobuf来做事件交换协议。我接手过一个老项目,用的是Java原生序列化,结果跨语言解析时各种踩坑。Protobuf天生带schema,能保证前后端对齐,这是刚需。
RELEASE或LATEST。我曾经吃过这个亏——某次构建时拉到了新版本的protobuf,与企业服务端的协议字段对不上,线上事故就这样发生了。
3.4 填充pom.xml
把上面的依赖整理一下,加入pom.xml的<dependencies>块里。同时别忘了加上<build>里的protobuf编译插件:
<project>
...
<properties>
<protobuf.version>3.21.12</protobuf.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>${protobuf.version}</version>
</dependency>
<!-- 其他依赖同上表 -->
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
</configuration>
<executions>
<execution>
<goals><goal>compile</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
说白了,这个插件就是帮我们把.proto文件编译成Java类。你把它配好了,后面写审计事件的定义时就能一键生成。
3.5 配置日志框架
日志在审计SDK里特别重要。每一笔审计记录都可能需要回放查证。
在src/main/resources/logback.xml里配置:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/audit-sdk.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/audit-sdk-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
<logger name="com.example.audit" level="DEBUG"/>
</configuration>
注意,我把SDK自己的包配置成DEBUG级别,这样开发时能看到详细的审计事件流转日志。上线后可以调回INFO。
3.6 搭建本地调试环境
既然是SDK改造,调试时你一定希望看到完整的调用链。我推荐三步走:
- 单元测试调试:JUnit + Mockito,在IDE里直接跑测试方法。
- 集成测试调试:启动一个嵌入式服务(后面会讲),模拟真实调用。
- 远程调试:客户环境或测试服务器,挂上JMX端口。
具体来说,我们在src/test/java下建一个调试入口:
@Slf4j
public class AuditSdkLocalTest {
public static void main(String[] args) {
// 初始化审计SDK核心
AuditEngine engine = new AuditEngineBuilder()
.withSerializer(new ProtobufSerializer())
.withTransport(new LocalFileTransport("target/audit-events.bin"))
.build();
// 生成一条测试事件
AuditEvent event = AuditEvent.newBuilder()
.setEventId(UUID.randomUUID().toString())
.setTimestamp(System.currentTimeMillis())
.setAction("USER_LOGIN")
.build();
engine.record(event);
log.info("本地调试完成,事件已写入 target/audit-events.bin");
}
}
你直接在IDE里右键运行这个main方法,就能看见整个审计流程跑通。我建议把输出文件也用Protobuf的parseFrom读回来验证一下,确保序列化没问题。
3.7 验证环境
跑一下这个命令看看所有依赖都拉下来了没:
mvn clean compile
如果控制台输出BUILD SUCCESS,说明项目初始化成功。你可以继续加一条测试用例来验证:
@Test
public void testSdkInitialization() {
AuditEngine engine = new AuditEngineBuilder().build();
assertNotNull(engine);
log.info("SDK初始化成功 - 版本: {}", AuditSdkVersion.getVersion());
}
为什么会这么设计?因为我希望每个接手项目的人,都能在5分钟内跑起来。越是复杂的SDK,越需要这样的“体检式”验证入口。