司素浏览器
61.24M · 2026-02-07
本文深入解析 ooder 框架的核心 BridgeCode 机制,从设计原理、生成编译流程,到基于此机制的分层 SKILLS 设计,最后展示在 Trae Solo 环境中的 Skill 构建实践。通过源码分析和实战案例,揭示 ooder 如何通过元数据驱动的代码生成实现高效的 A2UI 组件开发。
BridgeCode 是 ooder 框架中连接元数据配置与运行时组件的桥梁,其核心设计理念是元数据驱动(Metadata-Driven):
元数据配置(JSON/注解)
↓
BridgeCode 生成器
↓
Java 源代码
↓
动态编译
↓
运行时组件
设计目标:
BridgeCode 系统采用三层架构设计:
┌─────────────────────────────────────────────┐
│ 元数据层(Metadata Layer) │
│ - CustomViewMeta │
│ - CustomDataMeta │
│ - MethodConfig │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 生成器层(Generator Layer) │
│ - GenCustomViewJava │
│ - GenRepositoryViewJava │
│ - GenAggCustomViewJava │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 运行时层(Runtime Layer) │
│ - UIComponent │
│ - ModuleUIComponent │
│ - AggRootBuild │
└─────────────────────────────────────────────┘
AggRootBuild 是 BridgeCode 生成流程的核心协调类,位于 net.ooder.engine.codegen.java.AggRootBuild:
public class AggRootBuild {
private GenCustomViewJava viewTask;
private GenRepositoryViewJava voRepositoryTask;
private GenRepositoryViewJava serviceRepositoryTask;
private GenAggCustomViewJava rootTask;
private GenAggCustomJava genAggCustomJava;
public List<JavaGenSource> build() throws JDSException {
// 1. 创建子节点
CustomViewMeta = genChildJava();
// 2. 创建视图层
javaViewSource = buildView();
// 3. 创建资源层接口
repositorySource = buildRepositoryView(true);
// 4. 预编译一次
javaGen.dynCompile(getModuleJavaSrc());
return aggServiceRootBean;
}
}
关键特性:
所有代码生成器都继承自 GenJavaTask,提供统一的生成框架:
public abstract class GenJavaTask implements Callable<List<JavaGenSource>> {
protected JavaGenSource javaGen;
protected CustomViewMeta viewMeta;
protected String euClassName;
protected Chrome chrome;
public abstract List<JavaGenSource> build() throws JDSException;
protected JavaGenSource createJavaSource(String className, String content) {
JavaGenSource source = new JavaGenSource();
source.setClassName(className);
source.setContent(content);
source.setPackage(viewMeta.getPackageName());
return source;
}
}
设计优势:
D2CGenerator 是核心的代码生成引擎,使用 Freemarker 模板引擎:
public class D2CGenerator {
private Configuration freemarkerConfig;
private TemplateManager templateManager;
public String generate(String templateName, Map<String, Object> dataModel)
throws JDSException {
try {
Template template = freemarkerConfig.getTemplate(templateName);
StringWriter writer = new StringWriter();
template.process(dataModel, writer);
return writer.toString();
} catch (Exception e) {
throw new JDSException("代码生成失败: " + e.getMessage(), e);
}
}
public void dynCompile(List<JavaGenSource> sources) throws JDSException {
JavaCompiler compiler = new JavaCompiler();
compiler.compile(sources);
}
}
技术栈:
BridgeCode 的生成编译流程分为五个阶段:
阶段 1: 元数据解析
↓
阶段 2: 代码生成
↓
阶段 3: 源码组装
↓
阶段 4: 动态编译
↓
阶段 5: 运行时绑定
输入:
处理流程:
public class MetadataParser {
public MethodConfig parseFromJson(String jsonConfig) {
JSONObject json = JSON.parseObject(jsonConfig);
MethodConfig config = new MethodConfig();
// 解析视图元数据
config.setView(parseViewMeta(json.getJSONObject("view")));
// 解析数据元数据
config.setDataBean(parseDataMeta(json.getJSONObject("data")));
// 解析方法配置
config.setMethodName(json.getString("methodName"));
config.setUrl(json.getString("url"));
return config;
}
public MethodConfig parseFromAnnotation(Class<?> bridgeClass) {
MethodConfig config = new MethodConfig();
// 解析 @CustomClass 注解
CustomClass classAnnotation = bridgeClass.getAnnotation(CustomClass.class);
config.setCaption(classAnnotation.caption());
// 解析方法注解
for (Method method : bridgeClass.getMethods()) {
if (method.isAnnotationPresent(CustomMenuItem.class)) {
config.addMenuItem(parseMenuItem(method));
}
if (method.isAnnotationPresent(CustomGridEvent.class)) {
config.addEvent(parseGridEvent(method));
}
}
return config;
}
}
验证机制:
生成器层次:
GenCustomViewJava (视图层生成器)
├── GenLayoutChildModule (布局生成)
├── GenTabsChildModule (标签页生成)
└── GenFormChildModule (表单生成)
GenRepositoryViewJava (仓储层生成器)
├── GenEntityJava (实体生成)
├── GenEntityServiceJava (服务生成)
└── GenTableJava (表生成)
GenAggCustomViewJava (聚合层生成器)
├── GenAggRootJava (聚合根生成)
├── GenAggMenuJava (菜单生成)
└── GenAggAPIJava (API生成)
生成示例:
public class GenCustomViewJava extends GenJavaTask {
@Override
public List<JavaGenSource> build() throws JDSException {
List<JavaGenSource> sources = new ArrayList<>();
// 1. 生成视图类
sources.add(generateViewClass());
// 2. 生成字段配置
sources.add(generateFieldConfigs());
// 3. 生成事件处理器
sources.add(generateEventHandlers());
return sources;
}
private JavaGenSource generateViewClass() throws JDSException {
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("className", viewMeta.getClassName());
dataModel.put("packageName", viewMeta.getPackageName());
dataModel.put("fields", viewMeta.getFields());
String content = d2cGenerator.generate("view.ftl", dataModel);
return createJavaSource(viewMeta.getClassName(), content);
}
}
模板示例(Freemarker):
package ${packageName};
import net.ooder.engine.ub.component.*;
import net.ooder.engine.ub.annotation.*;
<#list fields as field>
import ${field.type};
</#list>
/**
* ${viewMeta.caption}
* 自动生成的视图类,请勿手动修改
*/
@CustomView
public class ${className} extends UIComponent {
<#list fields as field>
private ${field.type} ${field.name};
</#list>
public ${className}() {
super();
// 初始化组件
}
}
组装策略:
public class SourceAssembler {
public JavaSrcMeta assemble(List<JavaGenSource> sources) {
JavaSrcMeta srcMeta = new JavaSrcMeta();
// 1. 按包分组
Map<String, List<JavaGenSource>> packageMap =
sources.stream().collect(Collectors.groupingBy(JavaGenSource::getPackage));
// 2. 生成包结构
for (Map.Entry<String, List<JavaGenSource>> entry : packageMap.entrySet()) {
String packageName = entry.getKey();
List<JavaGenSource> packageSources = entry.getValue();
// 生成包目录
String packagePath = packageName.replace('.', '/');
srcMeta.addPackage(packagePath, packageSources);
}
// 3. 生成导入语句
srcMeta.addImports(calculateImports(sources));
return srcMeta;
}
}
依赖解析:
编译流程:
public class DynamicCompiler {
public Class<?> compile(JavaGenSource source) throws JDSException {
try {
// 1. 创建 Java 文件
File javaFile = createJavaFile(source);
// 2. 编译 Java 文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, null);
Iterable<? extends JavaFileObject> compilationUnits =
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(javaFile));
// 3. 执行编译
compiler.getTask(null, null, diagnostics, fileManager, null, null)
.call(compilationUnits);
// 4. 检查编译错误
if (!diagnostics.getDiagnostics().isEmpty()) {
throw new JDSException("编译失败: " + diagnostics);
}
// 5. 加载编译后的类
ClassLoader classLoader = fileManager.getClassLoader(null);
return classLoader.loadClass(source.getClassName());
} catch (Exception e) {
throw new JDSException("动态编译失败: " + e.getMessage(), e);
}
}
}
编译优化:
绑定机制:
public class RuntimeBinder {
public void bind(MethodConfig config, Class<?> bridgeClass)
throws JDSException {
try {
// 1. 创建 Bridge 实例
Object bridgeInstance = bridgeClass.newInstance();
// 2. 绑定方法到事件
for (Event event : config.getEvents()) {
Method handler = findHandlerMethod(bridgeClass, event.getHandler());
bindEvent(event, handler, bridgeInstance);
}
// 3. 绑定菜单项
for (MenuItem menu : config.getMenus()) {
Method handler = findHandlerMethod(bridgeClass, menu.getHandler());
bindMenuItem(menu, handler, bridgeInstance);
}
// 4. 注册到 UI 框架
registerToUIFramework(bridgeInstance);
} catch (Exception e) {
throw new JDSException("运行时绑定失败: " + e.getMessage(), e);
}
}
}
绑定特性:
public class GenerationCache {
private Map<String, JavaGenSource> cache = new ConcurrentHashMap<>();
public JavaGenSource getOrGenerate(String key, Callable<JavaGenSource> generator)
throws JDSException {
return cache.computeIfAbsent(key, k -> {
try {
return generator.call();
} catch (Exception e) {
throw new JDSException("生成失败: " + e.getMessage(), e);
}
});
}
public void invalidate(String key) {
cache.remove(key);
}
}
public class ParallelGenerator {
private ExecutorService executor = Executors.newFixedThreadPool(4);
public List<JavaGenSource> generateParallel(
List<GenJavaTask> tasks) throws JDSException {
try {
List<Future<JavaGenSource>> futures = new ArrayList<>();
for (GenJavaTask task : tasks) {
Future<JavaGenSource> future = executor.submit(task);
futures.add(future);
}
List<JavaGenSource> results = new ArrayList<>();
for (Future<JavaGenSource> future : futures) {
results.add(future.get());
}
return results;
} catch (Exception e) {
throw new JDSException("并行生成失败: " + e.getMessage(), e);
}
}
}
基于 BridgeCode 机制,ooder 设计了分层 SKILLS 架构,为 LLM 提供结构化的知识访问能力:
┌─────────────────────────────────────────────┐
│ Skill 知识层(Knowledge Layer) │
│ - Foundation Skill │
│ - Module Skill │
│ - Component Skill │
│ - Metadata Skill │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Skill 执行层(Execution Layer) │
│ - Skill Loader │
│ - Skill Context │
│ - Skill Orchestrator │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Skill 集成层(Integration Layer) │
│ - Trae Solo Integration │
│ - LLM Provider │
│ - Tool Registry │
└─────────────────────────────────────────────┘
职责:提供基础组件的知识和生成能力
public class FoundationSkill {
private static final String NAME = "foundation";
private static final String DESCRIPTION = "基础组件 Skill";
public SkillContext load() {
SkillContext context = new SkillContext();
// 1. 加载 NlpBaseUIComponent 知识
context.addClass(NlpBaseUIComponent.class);
// 2. 加载生成器知识
context.addGenerator(GenJavaTask.class);
// 3. 加载模板知识
context.addTemplate("base.ftl");
return context;
}
public List<SkillAction> getActions() {
return Arrays.asList(
new SkillAction("create-base-component", "创建基础组件"),
new SkillAction("initialize-component", "初始化组件"),
new SkillAction("validate-component", "验证组件")
);
}
}
知识内容:
职责:提供模块组件的知识和生成能力
public class ModuleSkill {
private static final String NAME = "module";
private static final String DESCRIPTION = "模块组件 Skill";
public SkillContext load() {
SkillContext context = new SkillContext();
// 1. 加载 ModuleUIComponent 知识
context.addClass(ModuleUIComponent.class);
context.addClass(CustomModuleUIComponent.class);
// 2. 加载生命周期方法
context.addMethod("setCurrComponent");
context.addMethod("findComponentByAlias");
// 3. 加载生成器
context.addGenerator(GenRepositoryViewJava.class);
return context;
}
public List<SkillAction> getActions() {
return Arrays.asList(
new SkillAction("create-module", "创建模块"),
new SkillAction("bind-component", "绑定组件"),
new SkillAction("manage-lifecycle", "管理生命周期")
);
}
}
知识内容:
职责:提供具体组件的知识和生成能力
public class ComponentSkill {
private static final String NAME = "component";
private static final String DESCRIPTION = "组件 Skill";
public SkillContext load() {
SkillContext context = new SkillContext();
// 1. 加载具体组件知识
context.addClass(NlpGroupUIComponent.class);
context.addClass(NlpGridUIComponent.class);
context.addClass(TreeGridUIComponent.class);
// 2. 加载组件配置
context.addConfig("group-config");
context.addConfig("grid-config");
// 3. 加载视图生成器
context.addGenerator(GenCustomViewJava.class);
return context;
}
public List<SkillAction> getActions() {
return Arrays.asList(
new SkillAction("create-group", "创建分组组件"),
new SkillAction("create-grid", "创建网格组件"),
new SkillAction("create-tree", "创建树形组件")
);
}
}
知识内容:
职责:提供元数据的知识和生成能力
public class MetadataSkill {
private static final String NAME = "metadata";
private static final String DESCRIPTION = "元数据 Skill";
public SkillContext load() {
SkillContext context = new SkillContext();
// 1. 加载元数据类
context.addClass(CustomViewMeta.class);
context.addClass(CustomDataMeta.class);
context.addClass(MethodConfig.class);
// 2. 加载解析器
context.addParser(MetadataParser.class);
// 3. 加载验证规则
context.addValidator(MetadataValidator.class);
return context;
}
public List<SkillAction> getActions() {
return Arrays.asList(
new SkillAction("parse-metadata", "解析元数据"),
new SkillAction("validate-metadata", "验证元数据"),
new SkillAction("generate-code", "生成代码")
);
}
}
知识内容:
public class SkillOrchestrator {
private Map<String, Skill> skills = new ConcurrentHashMap<>();
public void registerSkill(Skill skill) {
skills.put(skill.getName(), skill);
}
public SkillContext execute(String skillName, Map<String, Object> params)
throws JDSException {
Skill skill = skills.get(skillName);
if (skill == null) {
throw new JDSException("Skill 不存在: " + skillName);
}
// 1. 加载 Skill 上下文
SkillContext context = skill.load();
// 2. 应用参数
context.applyParams(params);
// 3. 执行 Skill
SkillResult result = skill.execute(context);
return result;
}
public List<SkillAction> getAllActions() {
return skills.values().stream()
.flatMap(skill -> skill.getActions().stream())
.collect(Collectors.toList());
}
}
trae-solo-project/
├── .trae/
│ ├── rules/
│ │ ├── project_rules.md # 项目规则
│ │ └── skill_rules.md # Skill 规则
│ └── skills/
│ ├── foundation-skill.md # Foundation Skill
│ ├── module-skill.md # Module Skill
│ ├── component-skill.md # Component Skill
│ └── metadata-skill.md # Metadata Skill
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── net/ooder/
│ │ │ └── engine/
│ │ │ ├── codegen/ # 代码生成器
│ │ │ └── ub/ # BridgeCode
│ │ └── resources/
│ │ └── templates/ # Freemarker 模板
│ └── test/
│ └── java/
│ └── net/ooder/
│ └── engine/
│ └── codegen/
└── pom.xml
.trae/rules/project_rules.md:
# Trae Solo 项目规则
## 代码生成规则
1. 所有生成的代码必须遵循 Java 编码规范
2. 生成的类必须添加 @Generated 注解
3. 生成的代码必须包含完整的 Javadoc
4. 生成的代码必须通过编译检查
## Skill 使用规则
1. LLM 必须通过 Skill 访问代码生成知识
2. LLM 不能直接修改生成的代码
3. LLM 必须使用 Skill 提供的 Action
4. LLM 必须遵循 Skill 的执行顺序
## 质量保证规则
1. 所有生成的代码必须经过单元测试
2. 所有生成的代码必须经过集成测试
3. 所有生成的代码必须经过代码审查
.trae/rules/skill_rules.md:
# Skill 规则
## Skill 定义规则
1. 每个 Skill 必须定义清晰的职责边界
2. 每个 Skill 必须提供完整的知识内容
3. 每个 Skill 必须定义可执行的 Action
4. 每个 Skill 必须提供使用示例
## Skill 加载规则
1. Skill 必须支持懒加载
2. Skill 必须支持缓存
3. Skill 必须支持热更新
4. Skill 必须支持版本管理
## Skill 执行规则
1. Skill 执行必须支持参数传递
2. Skill 执行必须支持上下文管理
3. Skill 执行必须支持错误处理
4. Skill 执行必须支持结果返回
.trae/skills/foundation-skill.md:
# Foundation Skill
## 概述
Foundation Skill 提供基础组件的知识和生成能力,是所有其他 Skill 的基础。
## 知识内容
### 核心类
#### NlpBaseUIComponent
```java
public abstract class NlpBaseUIComponent extends UIComponent {
private String componentType;
private boolean initialized;
public abstract void initializeFromNaturalLanguage(String naturalLanguage);
public abstract void initializeFromConfig(Object config);
public String getComponentType() {
return componentType;
}
public boolean isInitialized() {
return initialized;
}
}
职责:
public abstract class GenJavaTask implements Callable<List<JavaGenSource>> {
protected JavaGenSource javaGen;
protected CustomViewMeta viewMeta;
protected String euClassName;
protected Chrome chrome;
public abstract List<JavaGenSource> build() throws JDSException;
}
职责:
描述:创建基础组件
参数:
componentType:组件类型className:类名packageName:包名执行流程:
示例:
用户:创建一个基础组件
LLM:使用 Foundation Skill 的 create-base-component Action
参数:{"componentType": "CUSTOM", "className": "MyComponent", "packageName": "net.ooder.example"}
结果:生成 MyComponent.java
描述:初始化组件
参数:
component:组件实例config:配置对象执行流程:
示例:
用户:初始化组件
LLM:使用 Foundation Skill 的 initialize-component Action
参数:{"component": "myComponent", "config": {"type": "FORM"}}
结果:组件初始化完成
描述:验证组件
参数:
component:组件实例执行流程:
示例:
用户:验证组件
LLM:使用 Foundation Skill 的 validate-component Action
参数:{"component": "myComponent"}
结果:验证通过
用户需求:创建一个自定义基础组件
LLM 处理:
1. 加载 Foundation Skill
2. 调用 create-base-component Action
3. 生成组件代码
4. 返回生成的代码
用户需求:初始化一个现有组件
LLM 处理:
1. 加载 Foundation Skill
2. 调用 initialize-component Action
3. 执行初始化逻辑
4. 返回初始化结果
#### 4.2.2 Module Skill 实现
**.trae/skills/module-skill.md**:
```markdown
# Module Skill
## 概述
Module Skill 提供模块组件的知识和生成能力,管理组件的生命周期和依赖关系。
## 知识内容
### 核心类
#### ModuleUIComponent
```java
public class ModuleUIComponent<M extends UIComponent> extends UIComponent<ModuleProperties, ModuleEventEnum> {
private String className;
private String desc;
private ModuleViewType moduleViewType;
private Map<String, Object> valueMap;
private UIModule UIModule;
private CustomModuleMeta moduleBean;
private MethodConfig methodAPIBean;
private DomainInst domainInst;
private ModuleProperties properties;
private M currComponent;
private UIComponent navUIComponent;
private ModuleViewConfig viewConfig;
private List<String> dependencies;
private List<String> required;
private Map<String, ModuleFunction> functions;
private List<ModuleFormulaInst> formulas;
private Map<String, String> customFunctions;
private String customAppend;
private String afterAppend;
private Map<String, String> moduleVar;
private Map<String, UIComponent> components;
public void setCurrComponent(M currComponent) {
this.currComponent = currComponent;
if (currComponent != null) {
this.currComponentAlias = currComponent.getAlias();
if (currComponent.getParent() == null) {
currComponent.setParent(this);
}
this.components.put(currComponentAlias, currComponent);
ComponentType type = ComponentType.fromType(currComponent.getKey());
moduleViewType = ModuleViewType.getModuleViewByCom(type);
properties.setCurrComponentAlias(currComponentAlias);
} else {
this.currComponentAlias = null;
properties.setCurrComponentAlias(null);
}
}
public UIComponent findComponentByAlias(String alias) {
List<UIComponent> UIComponentList = this.findComponentsByAlias(alias);
UIComponent UIComponent = null;
if (UIComponentList.size() > 0) {
UIComponent = UIComponentList.get(0);
}
return UIComponent;
}
}
职责:
public class GenRepositoryViewJava extends GenJavaTask {
@Override
public List<JavaGenSource> build() throws JDSException {
List<JavaGenSource> sources = new ArrayList<>();
// 1. 生成 VO 接口
sources.add(generateVOInterface());
// 2. 生成 Service 接口
sources.add(generateServiceInterface());
// 3. 生成 Repository 接口
sources.add(generateRepositoryInterface());
// 4. 生成 RepositoryImpl 实现
sources.add(generateRepositoryImpl());
return sources;
}
}
职责:
描述:创建模块
参数:
moduleName:模块名称className:类名packageName:包名components:组件列表执行流程:
示例:
用户:创建一个模块
LLM:使用 Module Skill 的 create-module Action
参数:{"moduleName": "UserModule", "className": "UserModule", "packageName": "net.ooder.example", "components": ["grid", "form"]}
结果:生成 UserModule.java 和相关仓储代码
描述:绑定组件
参数:
module:模块实例component:组件实例alias:组件别名执行流程:
示例:
用户:绑定组件
LLM:使用 Module Skill 的 bind-component Action
参数:{"module": "userModule", "component": "userGrid", "alias": "grid"}
结果:组件绑定完成
描述:管理生命周期
参数:
module:模块实例action:生命周期动作(init/destroy)执行流程:
示例:
用户:初始化模块
LLM:使用 Module Skill 的 manage-lifecycle Action
参数:{"module": "userModule", "action": "init"}
结果:模块初始化完成
用户需求:创建一个用户管理模块
LLM 处理:
1. 加载 Module Skill
2. 调用 create-module Action
3. 生成模块代码和仓储代码
4. 返回生成的代码
用户需求:绑定网格组件到模块
LLM 处理:
1. 加载 Module Skill
2. 调用 bind-component Action
3. 执行绑定逻辑
4. 返回绑定结果
#### 4.2.3 Component Skill 实现
**.trae/skills/component-skill.md**:
```markdown
# Component Skill
## 概述
Component Skill 提供具体组件的知识和生成能力,包括分组组件、网格组件、树形组件等。
## 知识内容
### 核心类
#### NlpGroupUIComponent
```java
public class NlpGroupUIComponent<M extends CustomFieldGroupUIComponent> extends CustomModuleUIComponent<M> {
void init(MethodConfig methodConfig) throws JDSException {
CustomGroupFormViewMeta viewBean = (CustomGroupFormViewMeta) methodConfig.getView();
CustomGroupDataMeta dataBean = (CustomGroupDataMeta) methodConfig.getDataBean();
if (dataBean != null) {
this.dataUrl = dataBean.getDataUrl();
this.saveUrl = dataBean.getSaveUrl();
this.searchUrl = dataBean.getSearchUrl();
this.reSetUrl = dataBean.getReSetUrl();
}
CustomFieldGroupUIComponent currComponent = new CustomFieldGroupUIComponent(UIModule, methodConfig, valueMap);
this.addChildLayoutNav(currComponent);
this.setCurrComponent((M) currComponent);
this.fillAction(viewBean);
this.fillToolBar(viewBean.getToolBar(), currComponent);
this.fillContextAction(viewBean.getContextMenuBean(), currComponent);
if (viewBean.getOnReady() != null) {
for (ModuleOnReadyEventEnum eventEnum : viewBean.getOnReady()) {
this.addModuleEvent(eventEnum);
}
}
if (viewBean.getOnDestroy() != null) {
for (CustomOnDestroyEventEnum eventEnum : viewBean.getOnDestroy()) {
this.addModuleEvent(eventEnum);
}
}
}
}
职责:
public class NlpGridUIComponent extends CustomGridUIComponent {
public NlpGridUIComponent(MethodConfig methodConfig) {
super();
CustomGridViewMeta viewBean = (CustomGridViewMeta) methodConfig.getView();
init(viewBean);
}
public NlpGridUIComponent(CustomGridViewMeta viewBean) {
super();
init(viewBean);
}
public void init(CustomGridViewMeta viewBean) {
this.setProperties(new ClassGridProperties(viewBean));
this.setAlias(viewBean.getName());
}
}
职责:
public class GenCustomViewJava extends GenJavaTask {
@Override
public List<JavaGenSource> build() throws JDSException {
List<JavaGenSource> sources = new ArrayList<>();
// 1. 生成视图类
sources.add(generateViewClass());
// 2. 生成字段配置
sources.add(generateFieldConfigs());
// 3. 生成事件处理器
sources.add(generateEventHandlers());
return sources;
}
}
职责:
描述:创建分组组件
参数:
groupName:分组名称fields:字段列表events:事件列表执行流程:
示例:
用户:创建一个分组组件
LLM:使用 Component Skill 的 create-group Action
参数:{"groupName": "UserGroup", "fields": [...], "events": [...]}
结果:生成 UserGroup.java 和相关代码
描述:创建网格组件
参数:
gridName:网格名称columns:列配置dataUrl:数据 URL执行流程:
示例:
用户:创建一个网格组件
LLM:使用 Component Skill 的 create-grid Action
参数:{"gridName": "UserGrid", "columns": [...], "dataUrl": "/api/users"}
结果:生成 UserGrid.java 和相关代码
描述:创建树形组件
参数:
treeName:树形名称treeField:树字段parentField:父字段执行流程:
示例:
用户:创建一个树形组件
LLM:使用 Component Skill 的 create-tree Action
参数:{"treeName": "DepartmentTree", "treeField": "id", "parentField": "parentId"}
结果:生成 DepartmentTree.java 和相关代码
用户需求:创建一个用户分组表单
LLM 处理:
1. 加载 Component Skill
2. 调用 create-group Action
3. 生成分组组件代码
4. 返回生成的代码
用户需求:创建一个用户数据网格
LLM 处理:
1. 加载 Component Skill
2. 调用 create-grid Action
3. 生成网格组件代码
4. 返回生成的代码
#### 4.2.4 Metadata Skill 实现
**.trae/skills/metadata-skill.md**:
```markdown
# Metadata Skill
## 概述
Metadata Skill 提供元数据的知识和生成能力,包括元数据解析、验证和代码生成。
## 知识内容
### 核心类
#### CustomViewMeta
```java
public abstract class CustomViewMeta<F extends FieldFormConfig, I extends UIItem, C extends UIComponent> {
private String name;
private String caption;
private String desc;
private String methodName;
private String domainId;
private String sourceClassName;
private ModuleViewType moduleViewType;
private List<F> allFields;
private List<F> fields;
private List<Event> events;
private List<MenuItem> menus;
private List<ToolBar> toolBars;
private List<BottomBar> bottomBars;
private List<ContextMenu> contextMenus;
private List<ModuleFormulaInst> formulas;
private List<CustomBean> annotationBeans;
public abstract F createFieldConfig();
public abstract I createUIItem();
public abstract C createUIComponent();
public List<CustomBean> getAnnotationBeans() {
List<CustomBean> annotationBeans = new ArrayList<>();
if (this.getModuleBean() != null) {
annotationBeans.addAll(this.getModuleBean().getAnnotationBeans());
}
if (this.getDataBean() != null) {
annotationBeans.add(this.getDataBean());
}
if (this.getFieldAggConfig() != null) {
annotationBeans.addAll(this.getFieldAggConfig().getAnnotationBeans());
}
return annotationBeans;
}
}
职责:
public abstract class CustomDataMeta {
private String dataUrl;
private String editorPath;
private String addPath;
private String delPath;
private String sortPath;
private String saveRowPath;
private String saveAllRowPath;
private String searchUrl;
private String reloadUrl;
private String selectUrl;
private String unSelectUrl;
private String selectAllUrl;
private String unSelectAllUrl;
private String exportUrl;
private String importUrl;
private String customUrl;
}
职责:
public class MethodConfig<T extends CustomViewMeta, K extends CustomDataMeta> implements Comparable<MethodConfig> {
private String className;
private String desc;
private ModuleViewType moduleViewType;
private UIModule UIModule;
private CustomModuleMeta moduleBean;
private MethodConfig methodAPIBean;
private DomainInst domainInst;
private T view;
private K dataBean;
private BridgeClass bridgeClass;
private BridgeClass parentClass;
private String url;
private String caption;
private String methodName;
private String expression;
private String filter;
private String itemsExpression;
private String metaInfo;
private String fieldInfo;
private RequestMappingBean requestMapping;
private RequestBodyBean requestBody;
private Set<RequestParamBean> paramSet;
private RouteMenuMeta routeMenuBean;
private FieldAggConfig fieldAggConfig;
private CustomFieldMeta FieldMeta;
private RefBean refBean;
private CustomAPICallMeta api;
private List<CustomBean> annotationBeans;
public List<CustomBean> getAnnotationBeans() {
List<CustomBean> annotationBeans = new ArrayList<>();
if (this.getApi() != null) {
annotationBeans.addAll(this.getApi().getAnnotationBeans());
}
if (this.isModule()) {
annotationBeans.addAll(this.getModuleBean().getAnnotationBeans());
if (this.getDataBean() != null) {
annotationBeans.add(this.getDataBean());
}
}
if (routeMenuBean != null) {
annotationBeans.add(routeMenuBean);
}
if (this.getFieldAggConfig() != null) {
List<CustomBean> FieldMetas = this.getFieldAggConfig().getAnnotationBeans();
for (CustomBean customBean : FieldMetas) {
if (!annotationBeans.contains(customBean)) {
annotationBeans.add(customBean);
}
}
}
if (requestMapping != null && this.getPublicMethod()) {
annotationBeans.add(requestMapping);
}
if (getResponseBody() || api != null) {
if (!annotationBeans.contains(new SimpleCustomBean(ResponseBody.class))) {
annotationBeans.add(new SimpleCustomBean(ResponseBody.class));
}
}
return annotationBeans;
}
@JSONField(serialize = false)
public String getMetaInfo() {
if (this.getMethod() != null) {
List<RequestParamBean> params = new ArrayList(this.getParamSet());
if (isModule() && parentEuPackage != null) {
String euClassName = parentEuPackage + "." + getJavaSimpleName();
this.metaInfo = MethodUtil.toMethodStr(this.getMethod(),
getViewType(), euClassName, requestBody, params).toString();
} else {
this.metaInfo = MethodUtil.toMethodStr(this.getMethod(),
getViewType(), getJavaSimpleName(), requestBody, params).toString();
}
}
return metaInfo;
}
}
职责:
描述:解析元数据
参数:
source:元数据源(JSON/注解)type:元数据类型执行流程:
示例:
用户:解析元数据
LLM:使用 Metadata Skill 的 parse-metadata Action
参数:{"source": "{"viewClassName": "UserView", ...}", "type": "json"}
结果:返回 MethodConfig 对象
描述:验证元数据
参数:
metadata:元数据对象执行流程:
示例:
用户:验证元数据
LLM:使用 Metadata Skill 的 validate-metadata Action
参数:{"metadata": methodConfig}
结果:验证通过
描述:生成代码
参数:
metadata:元数据对象type:代码类型执行流程:
示例:
用户:生成代码
LLM:使用 Metadata Skill 的 generate-code Action
参数:{"metadata": methodConfig, "type": "view"}
结果:生成视图代码和仓储代码
用户需求:从 JSON 解析元数据
LLM 处理:
1. 加载 Metadata Skill
2. 调用 parse-metadata Action
3. 解析 JSON 配置
4. 返回 MethodConfig 对象
用户需求:生成组件代码
LLM 处理:
1. 加载 Metadata Skill
2. 调用 generate-code Action
3. 生成视图代码和仓储代码
4. 返回生成的代码
### 4.3 Skill 集成实现
#### 4.3.1 Skill Loader 实现
```java
public class SkillLoader {
private Map<String, Skill> skillCache = new ConcurrentHashMap<>();
public Skill loadSkill(String skillName) throws JDSException {
// 1. 检查缓存
Skill cachedSkill = skillCache.get(skillName);
if (cachedSkill != null) {
return cachedSkill;
}
// 2. 加载 Skill 定义
String skillPath = ".trae/skills/" + skillName + "-skill.md";
String skillContent = readFile(skillPath);
// 3. 解析 Skill 定义
Skill skill = parseSkillDefinition(skillContent);
// 4. 缓存 Skill
skillCache.put(skillName, skill);
return skill;
}
public void invalidateSkill(String skillName) {
skillCache.remove(skillName);
}
public List<String> getAvailableSkills() {
File skillsDir = new File(".trae/skills");
File[] skillFiles = skillsDir.listFiles((dir, name) ->
name.endsWith("-skill.md"));
return Arrays.stream(skillFiles)
.map(File::getName)
.map(name -> name.replace("-skill.md", ""))
.collect(Collectors.toList());
}
}
public class SkillContext {
private Map<String, Object> data = new HashMap<>();
private List<String> loadedClasses = new ArrayList<>();
private List<String> loadedGenerators = new ArrayList<>();
private List<String> loadedTemplates = new ArrayList<>();
public void addClass(Class<?> clazz) {
String className = clazz.getName();
if (!loadedClasses.contains(className)) {
loadedClasses.add(className);
}
}
public void addGenerator(Class<?> generator) {
String generatorName = generator.getName();
if (!loadedGenerators.contains(generatorName)) {
loadedGenerators.add(generatorName);
}
}
public void addTemplate(String templateName) {
if (!loadedTemplates.contains(templateName)) {
loadedTemplates.add(templateName);
}
}
public void applyParams(Map<String, Object> params) {
if (params != null) {
data.putAll(params);
}
}
public Object getParam(String key) {
return data.get(key);
}
public List<String> getLoadedClasses() {
return new ArrayList<>(loadedClasses);
}
public List<String> getLoadedGenerators() {
return new ArrayList<>(loadedGenerators);
}
public List<String> getLoadedTemplates() {
return new ArrayList<>(loadedTemplates);
}
}
public class LLMIntegration {
private SkillOrchestrator orchestrator;
private SkillLoader skillLoader;
public LLMIntegration() {
this.skillLoader = new SkillLoader();
this.orchestrator = new SkillOrchestrator();
// 注册所有 Skill
registerSkills();
}
private void registerSkills() {
orchestrator.registerSkill(new FoundationSkill());
orchestrator.registerSkill(new ModuleSkill());
orchestrator.registerSkill(new ComponentSkill());
orchestrator.registerSkill(new MetadataSkill());
}
public String processUserRequest(String userRequest) throws JDSException {
// 1. 分析用户请求
RequestAnalysis analysis = analyzeRequest(userRequest);
// 2. 选择合适的 Skill
String skillName = selectSkill(analysis);
// 3. 准备参数
Map<String, Object> params = prepareParams(analysis);
// 4. 执行 Skill
SkillResult result = orchestrator.execute(skillName, params);
// 5. 返回结果
return formatResult(result);
}
private RequestAnalysis analyzeRequest(String userRequest) {
RequestAnalysis analysis = new RequestAnalysis();
// 分析请求类型
if (userRequest.contains("创建") && userRequest.contains("基础组件")) {
analysis.setSkillName("foundation");
analysis.setActionName("create-base-component");
} else if (userRequest.contains("创建") && userRequest.contains("模块")) {
analysis.setSkillName("module");
analysis.setActionName("create-module");
} else if (userRequest.contains("创建") && userRequest.contains("网格")) {
analysis.setSkillName("component");
analysis.setActionName("create-grid");
} else if (userRequest.contains("解析") && userRequest.contains("元数据")) {
analysis.setSkillName("metadata");
analysis.setActionName("parse-metadata");
}
return analysis;
}
private String selectSkill(RequestAnalysis analysis) {
return analysis.getSkillName();
}
private Map<String, Object> prepareParams(RequestAnalysis analysis) {
Map<String, Object> params = new HashMap<>();
// 从用户请求中提取参数
// ...
return params;
}
private String formatResult(SkillResult result) {
// 格式化结果
return result.toString();
}
}
用户请求:
创建一个用户管理模块,包含用户列表网格和用户编辑表单
LLM 处理流程:
分析请求:
执行 Skill:
生成组件:
生成仓储:
返回结果:
已成功创建用户管理模块:
- UserModule.java
- UserGrid.java
- UserForm.java
- UserRepository.java
- UserService.java
用户请求:
从以下 JSON 配置生成代码:
{
"viewClassName": "net.ooder.example.UserTableView",
"moduleViewType": "GRIDCONFIG",
"fields": [
{"fieldname": "id", "caption": "ID", "type": "input", "editable": false},
{"fieldname": "name", "caption": "姓名", "type": "input", "editable": true},
{"fieldname": "age", "caption": "年龄", "type": "number", "editable": true}
]
}
LLM 处理流程:
分析请求:
解析元数据:
生成代码:
编译代码:
返回结果:
已成功生成代码:
- UserTableView.java
- UserRepository.java
- UserService.java
编译成功
用户请求:
创建一个部门树形组件,显示组织结构
LLM 处理流程:
分析请求:
执行 Skill:
生成仓储:
返回结果:
已成功创建部门树形组件:
- DepartmentTree.java
- DepartmentRepository.java
- DepartmentService.java
元数据驱动架构:
分层生成系统:
动态编译机制:
清晰的职责划分:
可扩展的架构:
完整的 Action 体系:
完整的集成方案:
实战验证:
最佳实践指导:
模板方法模式:
策略模式:
工厂模式:
观察者模式:
缓存机制:
并行处理:
增量构建:
清晰的代码结构:
完整的文档:
自动化测试:
完善 Skill 体系:
提升生成性能:
增强集成能力:
智能化生成:
可视化工具:
生态系统建设:
本文深入解析了 ooder 框架的 BridgeCode 机制,从设计原理、生成编译流程,到分层 SKILLS 设计,最后展示了在 Trae Solo 环境中的 Skill 构建实践。
BridgeCode 设计原理:
分层 SKILLS 设计:
Trae Solo 实践:
这种设计既保持了架构的清晰性,又提供了强大的扩展能力,为 LLM 的使用和后续开发提供了坚实的基础。通过元数据驱动的代码生成和分层 SKILLS 设计,ooder 框架实现了高效的 A2UI 组件开发,为开发者提供了强大的工具支持。