From f106b520170b2da02b4f5a39db98cd9ebb40c9b9 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:02:10 +0800 Subject: [PATCH] docs: add docs for using shared objects within the plugin (#451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What this PR does? 完善 Halo 共享给插件的 Beans 列表和使用文档 ```release-note None ``` --- .../plugin/basics/server/object-management.md | 211 +++++++++++++++++- .../post-content-version-generation.png | Bin 0 -> 87483 bytes .../plugin/basics/server/object-management.md | 211 +++++++++++++++++- 3 files changed, 398 insertions(+), 24 deletions(-) create mode 100644 static/img/developer-guide/plugin/basic/server/post-content-version-generation.png diff --git a/docs/developer-guide/plugin/basics/server/object-management.md b/docs/developer-guide/plugin/basics/server/object-management.md index d4daeeab..ed9ea0e1 100644 --- a/docs/developer-guide/plugin/basics/server/object-management.md +++ b/docs/developer-guide/plugin/basics/server/object-management.md @@ -40,18 +40,205 @@ public class Demo { } ``` -### 依赖注入 Halo 提供的 Bean +## 依赖注入 Halo 共享的 Bean -目前 Halo 只提供了少数几个 Bean 可以供插件依赖注入: +Halo 提供了一些共享的 Bean,任何插件都可以直接依赖注入这些 Bean。 -- run.halo.app.extension.ReactiveExtensionClient:用于管理自定义模型对象的增删改查,它是反应式的。 -- run.halo.app.extension.ExtensionClient:用于管理自定义模型对象的增删改查,它是阻塞的,只能用在非 NIO 线程中,如后台任务。 -- run.halo.app.extension.SchemeManager:用于管理自定义模型定义的注册和销毁。 -- run.halo.app.infra.ExternalUrlSupplier:用于获取用户配置的 Halo 外部访问地址。 -- run.halo.app.core.extension.service.AttachmentService:用于操作附件。 -- run.halo.app.notification.NotificationReasonEmitter:用于发送通知。 -- run.halo.app.notification.NotificationCenter:用于管理通知的订阅和取消订阅。 -- run.halo.app.infra.ExternalLinkProcessor:用于处理将一个相对地址转换为外部访问地址。 -- org.springframework.security.web.server.context.ServerSecurityContextRepository:用于获取操作用户的认证上下文信息,如自动登录场景。 +### ReactiveExtensionClient -即其他不在上述列表中的类的对象都是不可依赖注入的。 +`ReactiveExtensionClient` 是一个用于管理自定义模型对象的增删改查的 Bean,它是反应式的。 + +参考 [与自定义模型交互](../../api-reference/server/extension-client.md) 了解更多。 + +### ExtensionClient + +`ExtensionClient` 作用和方法与 ReactiveExtensionClient 一样,但它是阻塞的,只能用在非 NIO 线程中,如后台任务。 + +### SchemeManager + +`SchemeManager` 是一个用于管理自定义模型定义的注册和销毁的 Bean。 + +API 参考:[SchemeManager](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/extension/SchemeManager.java) + +### UserService + +用于操作 Halo 用户的 Bean,包括获取用户信息、更新密码、创建用户等函数。 + +API 参考 [UserService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/user/service/UserService.java) + +### ReactiveUserDetailsService + +用于获取用户信息的 Bean,它只有一个方法 `Mono findByUsername(String username)`。 + +### RoleService + +用于操作 Halo 角色的 Bean,包括查询角色绑定、角色及依赖等函数。 + +API 参考 [RoleService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/user/service/RoleService.java) + +### AttachmentService + +用于操作 Halo 附件的 Bean,包括上传、删除附件以及获取附件访问链接等函数。 + +API 参考 [AttachmentService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/extension/service/AttachmentService.java)。 + +### PostContentService + +在 Halo 中,文章内容具有版本管理的概念。第一个版本是完整的文章内容,称为 `baseSnapshot`。从第二个版本开始,每个版本都是基于 `baseSnapshot` 的增量内容。因此,要查询完整的文章内容,需要获取 `baseSnapshot` 以及对应的版本增量内容并合并。 + +![文章内容版本模型](/img/developer-guide/plugin/basic/server/post-content-version-generation.png) + +为了方便插件开发者获取文章内容,Halo 提供了 `PostContentService`,以简化这一过程的复杂性。 + +- getHeadContent:获取文章的最新版本内容(包括正在编辑的草稿)。 +- getReleaseContent:获取最新发布的文章内容。 +- getSpecifiedContent:获取指定 snapshotName 对应的文章内容。 +- listSnapshots:获取指定文章的所有版本的 Snapshot 对象的名称列表。 + +API 参考:[PostContentService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/content/PostContentService.java) +文章自定义模型定义参考 [Post](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/extension/content/Post.java) + +### NotificationReasonEmitter + +用于发送通知事件的 Bean。 + +#### 使用示例 + +假如有一个 `NEW_COMMENT_ON_POST` 文章有新评论的通知事件,你可以这样发送通知: + +```java +Mono emitNewCommentOnPostReason(/* 此示例省略参数 */) { + return notificationReasonEmitter.emit(NotificationReasonConst.NEW_COMMENT_ON_POST, + builder -> { + // 填充事件的数据 + var attributes = CommentOnPostReasonData.builder() + .postName(subjectRef.getName()) + .postOwner(post.getSpec().getOwner()) + .postTitle(post.getSpec().getTitle()) + .postUrl(postUrl) + .commenter(owner.getDisplayName()) + .content(comment.getSpec().getContent()) + .commentName(comment.getMetadata().getName()) + .build(); + builder.attributes(ReasonDataConverter.toAttributeMap(attributes)) + .author(identityFrom(owner)) + .subject(reasonSubject); + }) +} +``` + +API 参考:[NotificationReasonEmitter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/notification/NotificationReasonEmitter.java) + +### NotificationCenter + +用于管理通知的订阅和取消订阅。 + +API 参考:[NotificationCenter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/notification/NotificationCenter.java) + +### ExternalLinkProcessor + +用于将一个站内相对链接转换为绝对链接。 + +如配置了外部访问地址为 `https://example.com`,那么将 `/post/1` 转换为 `https://example.com/post/1`。 + +API 参考:[ExternalLinkProcessor](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/infra/ExternalLinkProcessor.java); + +### LoginHandlerEnhancer + +Halo 提供了登录增强机制,插件可以在登录成功或失败时调用登录增强器,使 Halo 可以执行额外的处理逻辑。 + +参考 [登录增强器](../../api-reference/server/login-handler-enhancer.md) 了解更多。 + +使用示例参考 [用户名密码登陆成功和失败的增强切入示例](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/application/src/main/java/run/halo/app/security/authentication/login/UsernamePasswordHandler.java#L106) + +### BackupRootGetter + +用于获取 Halo 备份文件的根目录。它是 `Supplier` 的子类。 + +### PluginsRootGetter + +用于获取 Halo 插件的根目录。它是 `Supplier` 的子类。 + +### ExtensionGetter + +用于获取扩展点实例(扩展)的 Bean。 + +例如,Halo 定义了 `AttachmentHandler` 这个扩展点,你可以通过 `ExtensionGetter` 获取到所有实现了 `AttachmentHandler` 接口的扩展。 + +有了它,插件中便可以定义自己的扩展点,然后由其他插件实现以达到插件扩展插件的目的。 + +API 参考 [ExtensionGetter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/plugin/extensionpoint/ExtensionGetter.java) + +### ServerSecurityContextRepository + +用于获取操作用户的认证上下文信息,如登录成功后保存认证信息。 + +ServerSecurityContextRepository 被 [ReactorContextWebFilter](https://github.com/spring-projects/spring-security/blob/9d2ca3da6a285f31ebd2da5f019127e1527e5042/web/src/main/java/org/springframework/security/web/server/context/ReactorContextWebFilter.java) 使用来获取操作用户的认证上下文信息并填充到 ReactiveSecurityContextHolder 中。 +此过滤器的执行顺序在 [SecurityWebFiltersOrder](https://github.com/spring-projects/spring-security/blob/9d2ca3da6a285f31ebd2da5f019127e1527e5042/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java#L47) 中定义。因此如果你的过滤器在此过滤器之前执行,那么你将无法从 ReactiveSecurityContextHolder 中获取到操作用户的认证上下文信息只能通过注入 ServerSecurityContextRepository 来获取。 + +API 参考:[ServerSecurityContextRepository](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/server/context/ServerSecurityContextRepository.html) + +### CryptoService + +Halo 根据用户名密码登录时,会先使用 CryptoService 的 `readPublicKey` 方法读取公钥,然后使用公钥加密密码,再发送给服务器。 + +当插件需要添加一些拦截器处理登录请求时可能需要获取原始密码,此时可以使用 CryptoService 的 `decrypt` 方法解密密码。 + +也可以复用它的公钥来作为一些加密算法的密钥。 + +API 参考 [CryptoService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/security/authentication/CryptoService.java) + +### ExternalUrlSupplier + +`ExternalUrlSupplier` 是一个用于获取用户配置的 Halo 外部访问地址的 Bean。 + +API 参考:[ExternalUrlSupplier](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/infra/ExternalUrlSupplier.java) + +### RateLimiterRegistry + +`RateLimiterRegistry` 是一个用于管理限流器的 Bean。 + +如果插件定义的某些 API 需要限流,可以使用 `RateLimiterRegistry` 来创建一个限流器,但是需要注意的是,**必须要在插件停止的生命周期方法里销毁你所创建的限流器**,否则会导致内存泄漏。 + +#### 使用示例 + +以下示例展示了如何使用 `RateLimiterRegistry` 创建一个限流器: + +```java +final Set limiterNames = new HashSet<>(); + +Mono sendEmailVerificationCode(String username, String email) { + return buildSendEmailRateLimiter(username, email) // step 1: 构建一个限流器 + .transformDeferred(rateLimiter -> rateLimiter.map(RateLimiterOperator::of)) // step 2: 返回一个经过变换的新 Mono + // step 3: 从这里开始的操作符都会受到限流的影响 + .flatMap(rateLimiter -> emailVerificationService.sendVerificationCode(username, email)) + // 转换 RequestNotPermitted 为 RateLimitExceededException 以使全局异常处理器能够处理 + .onErrorMap(RequestNotPermitted.class, RateLimitExceededException::new); +} + +RateLimiter buildSendEmailRateLimiter(String username, String email) { + var rateLimiterKey = "send-email-verification-code-" + username + ":" + email; + var rateLimiter = rateLimiterRegistry.rateLimiter(rateLimiterKey, new RateLimiterConfig.Builder() + // 频次限制为 1 次 + .limitForPeriod(1) + // 限制刷新周期为 60 秒, 即 60 秒内只能执行 1 次 + .limitRefreshPeriod(Duration.ofSeconds(60)) + .build()); + // 添加 limiter 到自己实现的 Registry 中保存起来以便在插件停止时清理 + limiters.add(rateLimiterKey); + return limiter; +} +``` + +在插件停止的生命周期方法里销毁你所创建的限流器: + +```java +@Override +public void stop() { + limiters.forEach(rateLimiterRegistry::remove); +} +``` + +`transformDeferred` 的作用是将 Mono 传入你提供的变换器中,返回一个经过变换的新 Mono。由于 RateLimiterOperator 是基于 Publisher 的装饰器(decorator),它会监视这个 Mono 的订阅和执行情况,从而对整个 Mono 的操作链进行限流。 + +换句话说,因为 `RateLimiterOperator` 装饰了这个 Mono,所以任何接在 `transformDeferred()` 之后的操作符都会受到限流的影响,直到整个流结束。 diff --git a/static/img/developer-guide/plugin/basic/server/post-content-version-generation.png b/static/img/developer-guide/plugin/basic/server/post-content-version-generation.png new file mode 100644 index 0000000000000000000000000000000000000000..88e467e18e26f6880231cba2da48bc3005dbd99e GIT binary patch literal 87483 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

MXe%L9!j<3 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 d@2LD!GN-A$eYIH1@*Mc1Agd} findByUsername(String username)`。 + +### RoleService + +用于操作 Halo 角色的 Bean,包括查询角色绑定、角色及依赖等函数。 + +API 参考 [RoleService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/user/service/RoleService.java) + +### AttachmentService + +用于操作 Halo 附件的 Bean,包括上传、删除附件以及获取附件访问链接等函数。 + +API 参考 [AttachmentService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/extension/service/AttachmentService.java)。 + +### PostContentService + +在 Halo 中,文章内容具有版本管理的概念。第一个版本是完整的文章内容,称为 `baseSnapshot`。从第二个版本开始,每个版本都是基于 `baseSnapshot` 的增量内容。因此,要查询完整的文章内容,需要获取 `baseSnapshot` 以及对应的版本增量内容并合并。 + +![文章内容版本模型](/img/developer-guide/plugin/basic/server/post-content-version-generation.png) + +为了方便插件开发者获取文章内容,Halo 提供了 `PostContentService`,以简化这一过程的复杂性。 + +- getHeadContent:获取文章的最新版本内容(包括正在编辑的草稿)。 +- getReleaseContent:获取最新发布的文章内容。 +- getSpecifiedContent:获取指定 snapshotName 对应的文章内容。 +- listSnapshots:获取指定文章的所有版本的 Snapshot 对象的名称列表。 + +API 参考:[PostContentService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/content/PostContentService.java) +文章自定义模型定义参考 [Post](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/core/extension/content/Post.java) + +### NotificationReasonEmitter + +用于发送通知事件的 Bean。 + +#### 使用示例 + +假如有一个 `NEW_COMMENT_ON_POST` 文章有新评论的通知事件,你可以这样发送通知: + +```java +Mono emitNewCommentOnPostReason(/* 此示例省略参数 */) { + return notificationReasonEmitter.emit(NotificationReasonConst.NEW_COMMENT_ON_POST, + builder -> { + // 填充事件的数据 + var attributes = CommentOnPostReasonData.builder() + .postName(subjectRef.getName()) + .postOwner(post.getSpec().getOwner()) + .postTitle(post.getSpec().getTitle()) + .postUrl(postUrl) + .commenter(owner.getDisplayName()) + .content(comment.getSpec().getContent()) + .commentName(comment.getMetadata().getName()) + .build(); + builder.attributes(ReasonDataConverter.toAttributeMap(attributes)) + .author(identityFrom(owner)) + .subject(reasonSubject); + }) +} +``` + +API 参考:[NotificationReasonEmitter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/notification/NotificationReasonEmitter.java) + +### NotificationCenter + +用于管理通知的订阅和取消订阅。 + +API 参考:[NotificationCenter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/notification/NotificationCenter.java) + +### ExternalLinkProcessor + +用于将一个站内相对链接转换为绝对链接。 + +如配置了外部访问地址为 `https://example.com`,那么将 `/post/1` 转换为 `https://example.com/post/1`。 + +API 参考:[ExternalLinkProcessor](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/infra/ExternalLinkProcessor.java); + +### LoginHandlerEnhancer + +Halo 提供了登录增强机制,插件可以在登录成功或失败时调用登录增强器,使 Halo 可以执行额外的处理逻辑。 + +参考 [登录增强器](../../api-reference/server/login-handler-enhancer.md) 了解更多。 + +使用示例参考 [用户名密码登陆成功和失败的增强切入示例](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/application/src/main/java/run/halo/app/security/authentication/login/UsernamePasswordHandler.java#L106) + +### BackupRootGetter + +用于获取 Halo 备份文件的根目录。它是 `Supplier` 的子类。 + +### PluginsRootGetter + +用于获取 Halo 插件的根目录。它是 `Supplier` 的子类。 + +### ExtensionGetter + +用于获取扩展点实例(扩展)的 Bean。 + +例如,Halo 定义了 `AttachmentHandler` 这个扩展点,你可以通过 `ExtensionGetter` 获取到所有实现了 `AttachmentHandler` 接口的扩展。 + +有了它,插件中便可以定义自己的扩展点,然后由其他插件实现以达到插件扩展插件的目的。 + +API 参考 [ExtensionGetter](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/plugin/extensionpoint/ExtensionGetter.java) + +### ServerSecurityContextRepository + +用于获取操作用户的认证上下文信息,如登录成功后保存认证信息。 + +ServerSecurityContextRepository 被 [ReactorContextWebFilter](https://github.com/spring-projects/spring-security/blob/9d2ca3da6a285f31ebd2da5f019127e1527e5042/web/src/main/java/org/springframework/security/web/server/context/ReactorContextWebFilter.java) 使用来获取操作用户的认证上下文信息并填充到 ReactiveSecurityContextHolder 中。 +此过滤器的执行顺序在 [SecurityWebFiltersOrder](https://github.com/spring-projects/spring-security/blob/9d2ca3da6a285f31ebd2da5f019127e1527e5042/config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java#L47) 中定义。因此如果你的过滤器在此过滤器之前执行,那么你将无法从 ReactiveSecurityContextHolder 中获取到操作用户的认证上下文信息只能通过注入 ServerSecurityContextRepository 来获取。 + +API 参考:[ServerSecurityContextRepository](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/server/context/ServerSecurityContextRepository.html) + +### CryptoService + +Halo 根据用户名密码登录时,会先使用 CryptoService 的 `readPublicKey` 方法读取公钥,然后使用公钥加密密码,再发送给服务器。 + +当插件需要添加一些拦截器处理登录请求时可能需要获取原始密码,此时可以使用 CryptoService 的 `decrypt` 方法解密密码。 + +也可以复用它的公钥来作为一些加密算法的密钥。 + +API 参考 [CryptoService](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/security/authentication/CryptoService.java) + +### ExternalUrlSupplier + +`ExternalUrlSupplier` 是一个用于获取用户配置的 Halo 外部访问地址的 Bean。 + +API 参考:[ExternalUrlSupplier](https://github.com/halo-dev/halo/blob/25086ee3e63f0c8b6ed380140a068c44404ef2b2/api/src/main/java/run/halo/app/infra/ExternalUrlSupplier.java) + +### RateLimiterRegistry + +`RateLimiterRegistry` 是一个用于管理限流器的 Bean。 + +如果插件定义的某些 API 需要限流,可以使用 `RateLimiterRegistry` 来创建一个限流器,但是需要注意的是,**必须要在插件停止的生命周期方法里销毁你所创建的限流器**,否则会导致内存泄漏。 + +#### 使用示例 + +以下示例展示了如何使用 `RateLimiterRegistry` 创建一个限流器: + +```java +final Set limiterNames = new HashSet<>(); + +Mono sendEmailVerificationCode(String username, String email) { + return buildSendEmailRateLimiter(username, email) // step 1: 构建一个限流器 + .transformDeferred(rateLimiter -> rateLimiter.map(RateLimiterOperator::of)) // step 2: 返回一个经过变换的新 Mono + // step 3: 从这里开始的操作符都会受到限流的影响 + .flatMap(rateLimiter -> emailVerificationService.sendVerificationCode(username, email)) + // 转换 RequestNotPermitted 为 RateLimitExceededException 以使全局异常处理器能够处理 + .onErrorMap(RequestNotPermitted.class, RateLimitExceededException::new); +} + +RateLimiter buildSendEmailRateLimiter(String username, String email) { + var rateLimiterKey = "send-email-verification-code-" + username + ":" + email; + var rateLimiter = rateLimiterRegistry.rateLimiter(rateLimiterKey, new RateLimiterConfig.Builder() + // 频次限制为 1 次 + .limitForPeriod(1) + // 限制刷新周期为 60 秒, 即 60 秒内只能执行 1 次 + .limitRefreshPeriod(Duration.ofSeconds(60)) + .build()); + // 添加 limiter 到自己实现的 Registry 中保存起来以便在插件停止时清理 + limiters.add(rateLimiterKey); + return limiter; +} +``` + +在插件停止的生命周期方法里销毁你所创建的限流器: + +```java +@Override +public void stop() { + limiters.forEach(rateLimiterRegistry::remove); +} +``` + +`transformDeferred` 的作用是将 Mono 传入你提供的变换器中,返回一个经过变换的新 Mono。由于 RateLimiterOperator 是基于 Publisher 的装饰器(decorator),它会监视这个 Mono 的订阅和执行情况,从而对整个 Mono 的操作链进行限流。 + +换句话说,因为 `RateLimiterOperator` 装饰了这个 Mono,所以任何接在 `transformDeferred()` 之后的操作符都会受到限流的影响,直到整个流结束。