add core view extension with JTE and Thymeleaf support
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# Architecture
|
||||
|
||||
`flash-ext-view-thymeleaf` has two layers:
|
||||
|
||||
1. **Boot-time**
|
||||
- `ThymeleafExtension` installs runtime + annotation processor.
|
||||
- `ThymeleafTargetResolver` validates handlers and resolves `@Template` / `@Fragment`.
|
||||
- Resolved targets are cached per handler class.
|
||||
|
||||
2. **Request-time**
|
||||
- Handler builds local `ViewModel`.
|
||||
- Runtime injects globals under reserved `global` namespace and merges local model.
|
||||
- Thymeleaf renders template or fragment.
|
||||
|
||||
## Handler Contract
|
||||
|
||||
- Must extend `ThymeleafHandler`.
|
||||
- Must have route annotation (`@Route`, `@GET`, `@POST`, ...).
|
||||
- Must declare exactly one view annotation:
|
||||
- `@Template`
|
||||
- `@Fragment`
|
||||
|
||||
Invalid configurations fail fast at startup.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Fragments
|
||||
|
||||
Use `@Fragment` for Thymeleaf fragment responses.
|
||||
|
||||
```java
|
||||
@GET("/users/table")
|
||||
@Fragment(template = "fragments/users", value = "rows")
|
||||
public final class UsersRows extends ThymeleafHandler {
|
||||
@Override
|
||||
public ViewModel render(dev.relism.models.Request req) {
|
||||
return ViewModel.of("users", List.of());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If `value` is blank, runtime uses the configured default fragment (default: `content`).
|
||||
@@ -0,0 +1,35 @@
|
||||
# Handlers
|
||||
|
||||
Use `ThymeleafHandler` for class-based Thymeleaf routes.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
- `onViewInit()` runs once at boot.
|
||||
- `render(...)` runs per request.
|
||||
|
||||
Use `onViewInit()` to cache dependencies via `require(...)`.
|
||||
|
||||
## Example
|
||||
|
||||
```java
|
||||
@GET("/dashboard")
|
||||
@Template("pages/dashboard")
|
||||
public final class DashboardPage extends ThymeleafHandler {
|
||||
|
||||
private DashboardService service;
|
||||
|
||||
@Override
|
||||
protected void onViewInit() {
|
||||
service = require(DashboardService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewModel render(dev.relism.models.Request req) {
|
||||
return ViewModel.empty()
|
||||
.with("title", "Dashboard")
|
||||
.with("stats", service.stats());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use `render(Request, Response)` when you need response access while building model variables.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Model and Globals
|
||||
|
||||
`ViewModel` (from `flash-ext-view-core`) is the per-request model builder.
|
||||
|
||||
## Merge Order
|
||||
|
||||
Runtime merge order is:
|
||||
|
||||
1. all extension globals under reserved `global` namespace
|
||||
2. local handler model
|
||||
|
||||
Handlers cannot set top-level `global`; runtime throws fail-fast to prevent namespace collisions.
|
||||
|
||||
## Globals
|
||||
|
||||
Register globals on extension setup:
|
||||
|
||||
```java
|
||||
new ThymeleafExtension()
|
||||
.addGlobal("appName", req -> "Flash")
|
||||
.addGlobal("path", req -> req.path());
|
||||
```
|
||||
|
||||
Template usage:
|
||||
|
||||
```html
|
||||
<span th:text="${global.appName}"></span>
|
||||
<span th:text="${global.path}"></span>
|
||||
```
|
||||
|
||||
Keep globals cheap: no blocking I/O or heavy allocations.
|
||||
@@ -0,0 +1,17 @@
|
||||
# Performance
|
||||
|
||||
`flash-ext-view-thymeleaf` is optimized for low overhead on request path.
|
||||
|
||||
## Current runtime choices
|
||||
|
||||
- Handler view metadata resolved once and cached.
|
||||
- Global/local model merge done in a single pass.
|
||||
- Thymeleaf target metadata resolved and cached per handler class.
|
||||
- No engine-agnostic adapter indirection.
|
||||
|
||||
## Best practices
|
||||
|
||||
- Cache services in `onViewInit()`.
|
||||
- Keep `addGlobal(...)` resolvers cheap and side-effect free.
|
||||
- Build only the model fields needed by template.
|
||||
- Avoid blocking I/O in `render(...)`; delegate to precomputed service data when possible.
|
||||
Reference in New Issue
Block a user