tinystruct-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

tinystruct Development Patterns

tinystruct 开发模式

Architecture and implementation patterns for building modules with the tinystruct Java framework – a lightweight, high-performance framework that treats CLI and HTTP as equal citizens, requiring no
main()
method and minimal configuration.
使用tinystruct Java框架构建模块的架构与实现模式——这是一个轻量、高性能的框架,将CLI和HTTP视为同等重要的交互方式,无需
main()
方法,且配置极简。

Core Principle

核心原则

CLI and HTTP are equal citizens. Every method annotated with
@Action
should ideally be runnable from both a terminal and a web browser without modification. This "dual-mode" capability is the core design philosophy of tinystruct.
CLI与HTTP地位平等。所有标注了
@Action
的方法理论上无需修改即可同时在终端和浏览器中运行。这种“双模式”能力是tinystruct的核心设计理念。

When to Activate

适用场景

When to Use

何时使用

  • Creating new
    Application
    modules by extending
    AbstractApplication
    .
  • Defining routes and command-line actions using
    @Action
    .
  • Handling per-request state via
    Context
    .
  • Performing JSON serialization using the native
    Builder
    and
    Builders
    components.
  • Working with database persistence via
    AbstractData
    POJOs.
  • Generating POJOs from database tables using the
    generate
    command.
  • Implementing Server-Sent Events (SSE) for real-time push.
  • Handling file uploads via multipart data.
  • Making outbound HTTP requests with
    URLRequest
    and
    HTTPHandler
    .
  • Configuring database connections or system settings in
    application.properties
    .
  • Debugging routing conflicts (Actions) or CLI argument parsing.
  • 通过继承
    AbstractApplication
    创建新的
    Application
    模块。
  • 使用
    @Action
    定义路由与命令行操作。
  • 通过
    Context
    处理请求级状态。
  • 使用原生
    Builder
    Builders
    组件进行JSON序列化。
  • 通过
    AbstractData
    POJO实现数据库持久化。
  • 使用
    generate
    命令从数据库表生成POJO。
  • 实现Server-Sent Events(SSE)进行实时推送。
  • 通过multipart数据处理文件上传。
  • 使用
    URLRequest
    HTTPHandler
    发起出站HTTP请求。
  • application.properties
    中配置数据库连接或系统设置。
  • 调试路由冲突(Actions)或CLI参数解析问题。

How It Works

工作原理

The tinystruct framework treats any method annotated with
@Action
as a routable endpoint for both terminal and web environments. Applications are created by extending
AbstractApplication
, which provides core lifecycle hooks like
init()
and access to the request
Context
.
Routing is handled by the
ActionRegistry
, which automatically maps path segments to method arguments and injects dependencies. For data-only services, the native
Builder
and
Builders
components should be used for JSON serialization to maintain a zero-dependency footprint. The database layer uses
AbstractData
POJOs paired with XML mapping files for CRUD operations without external ORM libraries.
tinystruct框架将所有标注了
@Action
的方法视为终端和Web环境均可访问的路由端点。应用通过继承
AbstractApplication
创建,该基类提供了
init()
等核心生命周期钩子,以及对请求
Context
的访问能力。
路由由
ActionRegistry
处理,它会自动将路径段映射到方法参数并注入依赖。对于纯数据服务,应使用原生
Builder
Builders
组件进行JSON序列化,以保持零依赖特性。数据库层使用
AbstractData
POJO搭配XML映射文件实现CRUD操作,无需外部ORM库。

Examples

示例

Basic Application (MyService)

基础应用(MyService)

java
public class MyService extends AbstractApplication {
    @Override
    public void init() {
        this.setTemplateRequired(false); // Disable .view lookup for data/API apps
    }

    @Override public String version() { return "1.0.0"; }

    @Action("greet")
    public String greet() {
        return "Hello from tinystruct!";
    }

    // Path parameter: GET /?q=greet/James  OR  bin/dispatcher greet/James
    @Action("greet")
    public String greet(String name) {
        return "Hello, " + name + "!";
    }
}
java
public class MyService extends AbstractApplication {
    @Override
    public void init() {
        this.setTemplateRequired(false); // 禁用数据/API应用的.view文件查找
    }

    @Override public String version() { return "1.0.0"; }

    @Action("greet")
    public String greet() {
        return "Hello from tinystruct!";
    }

    // 路径参数:GET /?q=greet/James 或  bin/dispatcher greet/James
    @Action("greet")
    public String greet(String name) {
        return "Hello, " + name + "!";
    }
}

HTTP Mode Disambiguation (login)

HTTP模式区分(登录)

java
@Action(value = "login", mode = Mode.HTTP_POST)
public String doLogin(Request<?, ?> request) throws ApplicationException {
    request.getSession().setAttribute("userId", "42");
    return "Logged in";
}
java
@Action(value = "login", mode = Mode.HTTP_POST)
public String doLogin(Request<?, ?> request) throws ApplicationException {
    request.getSession().setAttribute("userId", "42");
    return "Logged in";
}

Native JSON Data Handling (Builder + Builders)

原生JSON数据处理(Builder + Builders)

java
import org.tinystruct.data.component.Builder;
import org.tinystruct.data.component.Builders;

@Action("api/data")
public String getData() throws ApplicationException {
    Builders dataList = new Builders();
    Builder item = new Builder();
    item.put("id", 1);
    item.put("name", "James");
    dataList.add(item);

    Builder response = new Builder();
    response.put("status", "success");
    response.put("data", dataList);
    return response.toString(); // {"status":"success","data":[{"id":1,"name":"James"}]}
}
java
import org.tinystruct.data.component.Builder;
import org.tinystruct.data.component.Builders;

@Action("api/data")
public String getData() throws ApplicationException {
    Builders dataList = new Builders();
    Builder item = new Builder();
    item.put("id", 1);
    item.put("name", "James");
    dataList.add(item);

    Builder response = new Builder();
    response.put("status", "success");
    response.put("data", dataList);
    return response.toString(); // {"status":"success","data":[{"id":1,"name":"James"}]}
}

SSE (Server-Sent Events)

SSE(Server-Sent Events)

java
import org.tinystruct.http.SSEPushManager;

@Action("sse/connect")
public String connect() {
    return "{\"type\":\"connect\",\"message\":\"Connected to SSE\"}";
}

// Push to a specific client
String sessionId = getContext().getId();
Builder msg = new Builder();
msg.put("text", "Hello, user!");
SSEPushManager.getInstance().push(sessionId, msg);

// Broadcast to all
// Broadcast to all
SSEPushManager.getInstance().broadcast(msg);
java
import org.tinystruct.http.SSEPushManager;

@Action("sse/connect")
public String connect() {
    return "{\"type\":\"connect\",\"message\":\"Connected to SSE\"}";
}

// 推送给指定客户端
String sessionId = getContext().getId();
Builder msg = new Builder();
msg.put("text", "Hello, user!");
SSEPushManager.getInstance().push(sessionId, msg);

// 广播给所有客户端
SSEPushManager.getInstance().broadcast(msg);

File Upload

文件上传

java
import org.tinystruct.data.FileEntity;

@Action(value = "upload", mode = Mode.HTTP_POST)
public String upload(Request<?, ?> request) throws ApplicationException {
    List<FileEntity> files = request.getAttachments();
    if (files != null) {
        for (FileEntity file : files) {
            System.out.println("Uploaded: " + file.getFilename());
        }
    }
    return "Upload OK";
}
java
import org.tinystruct.data.FileEntity;

@Action(value = "upload", mode = Mode.HTTP_POST)
public String upload(Request<?, ?> request) throws ApplicationException {
    List<FileEntity> files = request.getAttachments();
    if (files != null) {
        for (FileEntity file : files) {
            System.out.println("Uploaded: " + file.getFilename());
        }
    }
    return "Upload OK";
}

Configuration

配置

Settings are managed in
src/main/resources/application.properties
.
properties
undefined
设置项在
src/main/resources/application.properties
中管理。
properties
undefined

Database

数据库

driver=org.h2.Driver database.url=jdbc:h2:~/mydb database.user=sa database.password=
driver=org.h2.Driver database.url=jdbc:h2:~/mydb database.user=sa database.password=

Server

服务器

default.home.page=hello server.port=8080
default.home.page=hello server.port=8080

Locale

区域设置

default.language=en_US
default.language=en_US

Session (Redis for clustered environments)

会话(集群环境使用Redis)

default.session.repository=org.tinystruct.http.RedisSessionRepository

default.session.repository=org.tinystruct.http.RedisSessionRepository

redis.host=127.0.0.1

redis.host=127.0.0.1

redis.port=6379

redis.port=6379


Access config values in your application:
```java
String port = this.getConfiguration("server.port");

在应用中访问配置值:
```java
String port = this.getConfiguration("server.port");

Red Flags & Anti-patterns

常见问题与反模式

SymptomCorrect Pattern
Importing
com.google.gson
or
com.fasterxml.jackson
Use
org.tinystruct.data.component.Builder
/
Builders
.
Using
List<Builder>
for JSON arrays
Use
Builders
to avoid generic type erasure issues.
ApplicationRuntimeException: template not found
Call
setTemplateRequired(false)
in
init()
for API-only apps.
Annotating
private
methods with
@Action
Actions must be
public
to be registered by the framework.
Hardcoding
main(String[] args)
in apps
Use
bin/dispatcher
as the entry point for all modules.
Manual
ActionRegistry
registration
Prefer the
@Action
annotation for automatic discovery.
Action not found at runtimeEnsure class is imported via
--import
or listed in
application.properties
.
CLI arg not visiblePass with
--key value
; access via
getContext().getAttribute("--key")
.
Two methods same path, wrong one firesSet explicit
mode
(e.g.,
HTTP_GET
vs
HTTP_POST
) to disambiguate.
问题表现正确做法
导入
com.google.gson
com.fasterxml.jackson
使用
org.tinystruct.data.component.Builder
/
Builders
使用
List<Builder>
处理JSON数组
使用
Builders
避免泛型类型擦除问题。
出现
ApplicationRuntimeException: template not found
init()
中调用
setTemplateRequired(false)
以适配纯API应用。
private
方法标注
@Action
Action方法必须为
public
才能被框架注册。
在应用中硬编码
main(String[] args)
使用
bin/dispatcher
作为所有模块的入口点。
手动注册
ActionRegistry
优先使用
@Action
注解实现自动发现。
运行时提示Action未找到确保类通过
--import
导入或在
application.properties
中列出。
CLI参数不可见使用
--key value
传递参数;通过
getContext().getAttribute("--key")
访问。
两个方法路径相同,触发错误的方法设置明确的
mode
(如
HTTP_GET
vs
HTTP_POST
)进行区分。

Best Practices

最佳实践

  1. Granular Applications: Break logic into smaller, focused applications rather than one monolithic class.
  2. Setup in
    init()
    : Leverage
    init()
    for setup (config, DB) rather than the constructor. Do NOT call
    setAction()
    — use
    @Action
    annotation.
  3. Mode Awareness: Use the
    Mode
    parameter in
    @Action
    to restrict sensitive operations to
    CLI
    only or specific HTTP methods.
  4. Context over Params: For optional CLI flags, use
    getContext().getAttribute("--flag")
    rather than adding parameters to the method signature.
  5. Asynchronous Events: For heavy tasks triggered by events, use
    CompletableFuture.runAsync()
    inside the event handler.
  1. 细粒度应用:将逻辑拆分为更小、专注的应用,而非单一的巨型类。
  2. init()
    中初始化
    :利用
    init()
    进行配置、数据库等初始化操作,而非构造函数。请勿调用
    setAction()
    ——使用
    @Action
    注解。
  3. 模式感知:在
    @Action
    中使用
    Mode
    参数将敏感操作限制为仅
    CLI
    模式或特定HTTP方法。
  4. 优先使用Context而非参数:对于可选CLI标志,使用
    getContext().getAttribute("--flag")
    而非在方法签名中添加参数。
  5. 异步事件处理:对于事件触发的重型任务,在事件处理器内部使用
    CompletableFuture.runAsync()

Technical Reference

技术参考

Detailed guides are available in the
references/
directory:
  • Architecture & Config — Abstractions, Package Map, Properties
  • Routing & @Action — Annotation details, Modes, Parameters
  • Data Handling — Builder, Builders, JSON serialization & parsing
  • Database Persistence — AbstractData POJOs, CRUD, mapping XML, POJO generation
  • System & Usage — Context, Sessions, SSE, File Uploads, Events, Networking
  • Testing Patterns — JUnit 5 unit and HTTP integration testing
详细指南位于
references/
目录中:
  • 架构与配置 — 抽象层、包结构、配置属性
  • 路由与@Action — 注解细节、模式、参数
  • 数据处理 — Builder、Builders、JSON序列化与解析
  • 数据库持久化 — AbstractData POJO、CRUD、映射XML、POJO生成
  • 系统与使用 — Context、会话、SSE、文件上传、事件、网络
  • 测试模式 — JUnit 5单元测试与HTTP集成测试

Reference Source Files (Internal)

参考源文件(内部)

  • src/main/java/org/tinystruct/AbstractApplication.java
    — Core base class with lifecycle hooks
  • src/main/java/org/tinystruct/system/annotation/Action.java
    — Annotation & Modes
  • src/main/java/org/tinystruct/application/ActionRegistry.java
    — Routing Engine
  • src/main/java/org/tinystruct/data/component/Builder.java
    — JSON object serializer
  • src/main/java/org/tinystruct/data/component/Builders.java
    — JSON array serializer
  • src/main/java/org/tinystruct/data/component/AbstractData.java
    — Base POJO class with CRUD
  • src/main/java/org/tinystruct/data/Mapping.java
    — Mapping XML parser
  • src/main/java/org/tinystruct/data/tools/MySQLGenerator.java
    — POJO generator reference
  • src/main/java/org/tinystruct/data/component/FieldType.java
    — SQL-to-Java type mappings
  • src/main/java/org/tinystruct/data/component/Condition.java
    — Fluent SQL query builder
  • src/main/java/org/tinystruct/http/SSEPushManager.java
    — SSE connection management
  • src/test/java/org/tinystruct/application/ActionRegistryTest.java
    — Registry test examples
  • src/test/java/org/tinystruct/system/HttpServerHttpModeTest.java
    — HTTP integration test patterns
  • src/main/java/org/tinystruct/AbstractApplication.java
    — 包含生命周期钩子的核心基类
  • src/main/java/org/tinystruct/system/annotation/Action.java
    — 注解与模式定义
  • src/main/java/org/tinystruct/application/ActionRegistry.java
    — 路由引擎
  • src/main/java/org/tinystruct/data/component/Builder.java
    — JSON对象序列化器
  • src/main/java/org/tinystruct/data/component/Builders.java
    — JSON数组序列化器
  • src/main/java/org/tinystruct/data/component/AbstractData.java
    — 带CRUD功能的POJO基类
  • src/main/java/org/tinystruct/data/Mapping.java
    — XML映射解析器
  • src/main/java/org/tinystruct/data/tools/MySQLGenerator.java
    — POJO生成器参考实现
  • src/main/java/org/tinystruct/data/component/FieldType.java
    — SQL到Java类型映射
  • src/main/java/org/tinystruct/data/component/Condition.java
    — 流式SQL查询构建器
  • src/main/java/org/tinystruct/http/SSEPushManager.java
    — SSE连接管理器
  • src/test/java/org/tinystruct/application/ActionRegistryTest.java
    — 注册器测试示例
  • src/test/java/org/tinystruct/system/HttpServerHttpModeTest.java
    — HTTP集成测试模式