Skip to content

Commit

Permalink
doc: add example (GitHub #231)
Browse files Browse the repository at this point in the history
  • Loading branch information
Createsequence committed Mar 19, 2024
1 parent 9b8424b commit e0e5b27
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 167 deletions.
7 changes: 5 additions & 2 deletions website/docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ const sidebarConfig = [
{
title: '场景示例',
children: [
{ title: "字典值自动转换", path: "/use_case/example_auto_fill_controller.md" },
{ title: "填充一个复杂对象", path: "/use_case/example_multi_datasource.md" },
{ title: "示例:如何基于枚举进行填充", path: "/use_case/example_fill_enum.md" },
{ title: "示例:如何在填充后进行附加操作", path: "/use_case/example_additional_action.md" },
{ title: "示例:如何基于方法填充", path: "/use_case/example_fill_method.md" },
{ title: "示例:如何填充被包装的返回值", path: "/use_case/example_fill_wrapped_return_value.md" },
{ title: "示例: 如何填充一个复杂对象", path: "/use_case/example_multi_datasource.md" },
]
},
{ title: "常见问题", path: "/user_guide/faq.md" },
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 34 additions & 17 deletions website/docs/basic/trigger_operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,41 +95,58 @@ public List<T> getFooList() {

### 2.3.包装类提取

有时候,`Controller`中的方法返回值会使用通用响应体进行包装,例如
有时候,我们会在 `Controller` 中显式的使用通用响应体包装返回值,比如

~~~java
public class Result<T> {
private Integer code;
private T data;
@PostMapping
public Result<List<UserVO>> listUser(@RequestBody List<Integer> ids) {
// 返回值被通用响应体包装
return new Result<>(userService.listByIds(ids));
}

@AutoOperate(type = Foo.class)
public Result<List<Foo>> getFooList() {
// do nothing
// 通用响应体
@AllArgsConstructor
@Data
public class Result<T> {
private String msg = "ok";
private Integer code = 200;
private T data;
public Result(T data) {
this.data = data;
}
}
~~~

实际上,需要填充的对象并不是`Result`本身,而是`Result`中的`data`字段,此时我们可以直接通过`on`属性对被包装的返回值进行提取
此时,我们真正需要填充的数据其实是 `Result.data`,则可以在 `@AutoOperate` 注解中通过 `on` 属性指定

~~~java
@AutoOperate(type = Foo.class, on = "data")
public Result<List<Foo>> getFooList() {
// do nothing
@AutoOperate(type = UserVO.class, on = "data") // 声明自动填充
@PostMapping
public Result<List<UserVO>> listUser(@RequestBody List<Integer> ids) {
// 返回值被通用响应体包装
return new Result<>(userService.listByIds(ids));
}
~~~

`on`属性默认支持链式操作符,即通过`xx.xx.xx`的方式访问内部对象的属性,比如:
![image-20231013231124968](./image-20231013231124968-0813973.png)

**多级包装**

在特定情况下,我们会存在多级包装的情况。比如通用响应体包装了分页对象,然后分页对象里面才是需要填充的数据。

对于常见的`Result<PageInfo<Foo>>` 结构,你可以使用这种方式来从被多层包装的对象中提取特定的属性值
由于 `on` 属性默认支持链式操作符,即可以通过`xx.xx.xx`的方式访问内部对象的属性,因此你可以使用这种方式来从被多层包装的对象中提取特定的属性值

~~~java
Result.data -> PageInfo.list -> Foo
@AutoOperate(type = Foo.class, on = "data.list")
public Result<PageInfo<Foo>> getFooList() {
// do nothing
@AutoOperate(type = UserVO.class, on = "data.list") // 声明自动填充
@PostMapping
public Result<Page<List<UserVO>>> listUser(@RequestBody List<Integer> ids, @RequestParam PageDTO pageDTO) {
// Result.data -> Page.list -> List<UserVo>
return new Result<>(userService.pageByIds(ids, pageDTO));
}
~~~

![image-20231013230948877](./image-20231013230948877-0813989.png)

:::tip

如果未指定类型,而是让 crane4j 在运行时自动推断类型,那么类型推断时将以提取出的字段值为准。
Expand Down
37 changes: 37 additions & 0 deletions website/docs/use_case/example_additional_action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 示例:如何在填充后进行附加操作

本示例将指导你如何配置填充后的附加操作,在这之前,请先确保你已经阅读过[快速开始](./../user_guide/getting_started/getting_started_abstract.md),并且成功将 crane4j 引入你的项目。

有时候,我们会希望在填充后,再进行一些附加操作,这些操作光靠 crane4j 提供的数据源机制无法很好的解决。

比如,在上一个示例中,我们[基于枚举填充了用户的性别字段](./example_fill_enum.md),现在我们有了一个新的需求:

- 如果用户的年龄小于等于 10 岁,那么用户名需要拼接上 "小朋友";
- 如果用户的年龄大于 10 岁且小于 18 岁,那么用户名需要拼接上 "同学";
- 如果用户的年龄大于 18 岁,那么用户名需要根据性别拼接上 "先生" 或者 "女士";

此时,你可以令你的待填充对象实现 `OperationAwareBean` 接口,并在对应回调方法中添加逻辑:

~~~java
@Acccessor(chain = true)
@Data
public class Student implements OperationAwareBean {
private Integer age;
private String name;
private Integer genderCode;
private String genderName;

@Override
public void afterOperationsCompletion() { // 该回调方法会在所有操作完成后调用
if (age <= 10) {
name = name + "小朋友";
} else if (age <= 18) {
name = name + "同学";
} else {
name = name + genderName;
}
}
}
~~~

具体内容可参见:[组件的回调方法](./../advanced/callback_of_component.md) 一节。
137 changes: 0 additions & 137 deletions website/docs/use_case/example_auto_fill_controller.md

This file was deleted.

58 changes: 49 additions & 9 deletions website/docs/use_case/example_fill_enum.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 示例:如何基于枚举进行填充

本示例将指导你如何配置基于枚举配置填充操作,在这之前,请先确保你已经阅读过[快速开始](./../user_guide/getting_started/getting_started_abstract.md),并且成功将 crane4j 引入你的项目。
本示例将指导你如何使用枚举作为数据源,去配置一个填充操作,在这之前,请先确保你已经阅读过[快速开始](./../user_guide/getting_started/getting_started_abstract.md),并且成功将 crane4j 引入你的项目。

## 1.准备

Expand Down Expand Up @@ -36,7 +36,7 @@ public class Student {

## 2.使用

要做到这个效果,最简单的方式就是在 `genderCode` 上通过 `@AssembleEnum` 注解声明一个装配操作:
首先,你需要在 `genderCode` 字段上通过 `@AssembleEnum` 注解声明一个装配操作:

~~~java
@Acccessor(chain = true)
Expand All @@ -45,8 +45,8 @@ public class Student {
@AssembleEnum(
type = Gender.class, // 指定数据源为 Gender 枚举类
enums = @ContainerEnum(
key = "code", // key 为 Gender.code 字段值
value = "value" // value 为 Gender.value 字段值
key = "code", // key 为 Gender.code 字段值
value = "value" // value 为 Gender.value 字段值
),
props = @Mapping(ref = "genderName") // 将 value 映射到 genderName 字段上
)
Expand All @@ -58,11 +58,12 @@ public class Student {
此后通过不同的方式触发填充即可,这里我们选择直接基于 AOP 切面触发:

~~~java
public class ServiceImpl {
@Component
public class ServiceImpl { // 你的 service 接口,确保 Spring 可以代理它

@AutoOperate(type = Student.class) // 声明自动填充该方法的返回值
public List<Student> getStudents(Collection<Integer> ids) {
return ids.stream()
return ids.stream() // 模拟返回数据
.map(id -> {
int genderCode = id % 2; // 随机设置一个性别编码
return new Student().setGenderCode(genderCode)
Expand All @@ -77,6 +78,45 @@ service.getStudents(Arrays.asList(1, 2));
// 执行结果为:[{genderCode=1, genderName="男"}, {genderCode=0, genderName="女"}]
~~~

> - 关于如何指定字段映射,具体内容可以参见:[字段映射](./../basic/property_mapping.md) 一节;
> - 你可以基于更多的配置项和不同的声明方式来配置基于枚举的填充操作,具体内容可以参见:[枚举填充](./../basic/container/enum_container.md) 一节;
> - 除了基于 AOP,crane4j 还支持更多的触发方式,具体内容可以参见:[触发填充操作](./../basic/trigger_operation.md) 一节;
- 关于如何指定字段映射,具体内容可以参见:[字段映射](./../basic/property_mapping.md) 一节;
- 你可以基于更多的配置项和不同的声明方式来配置基于枚举的填充操作,具体内容可以参见:[枚举填充](./../basic/container/enum_container.md) 一节;
- 除了基于 AOP 自动触发,crane4j 还支持更多的触发方式,具体内容可以参见:[触发填充操作](./../basic/trigger_operation.md) 一节;

## 3.组合式配置

上述写法被称为选项式,即所有的配置集成在一个注解中,作为不同的选项。

如果你希望数据源与操作的配置分离开,那么你可以先将枚举的数据源配置分离到枚举上:

~~~java
@ContainerEnum(
key = "code", // key 为 Gender.code 字段值
value = "value" // value 为 Gender.value 字段值
)
@Getter
@RequiredArgsConstructor
private enum Gender {
FEMALE(0, "", "female"),
MALE(1, "", "male");

private final Integer code;
private final String value;
}
~~~

然后在 Student 中不必再进行数据源配置,直接引用即可:

~~~java
@Acccessor(chain = true)
@Data
public class Student {
@AssembleEnum(
type = Gender.class, // 指定数据源为 Gender 枚举类
props = @Mapping(ref = "genderName") // 将 value 映射到 genderName 字段上
)
private Integer genderCode;
private String genderName;
}
~~~

其他部分与之前完全一样。
Loading

0 comments on commit e0e5b27

Please sign in to comment.