Closed Createsequence closed 7 months ago
你好,我是社区新人,如果可以的话,希望能把这个issue推给我借此熟悉项目大致内容,谢谢!
你好,我是社区新人,如果可以的话,希望能把这个issue推给我借此熟悉项目大致内容,谢谢!
欢迎!
项目地址:https://github.com/opengoofy/crane4j 欢迎大家积极star和提出issue和pr。 官方文档:https://createsequence.gitee.io/crane4j-doc/#/user_guide/getting_started/getting_started_with_springboot.html
在日常的开发中,我们经常会遇到“根据 A 的 key 值拿到 B,再把 B 的属性映射到 A”的需求。除了手动set之外,比较常见的就是利用Spring提供的BeanUtils.CopyProperties进行属性拷贝。虽然这也是一个不错的解决方法,但是遇到一个复杂对象的填充或者场景多样化时难免力不从心。因此Crane4j的出现就是用于自动查询接口并填充字段值。并且支持为MybatisPlus、Jackson、Redis提供了拓展插件,适应性广泛。
crane4j 的整体执行流程可大致分为两阶段:
Crane4j是一个插件,可以通过maven坐标直接安装,推荐与 spring/springboot 集成使用,不过在非 Spring 环境中也提供了很好的支持。样例如下:
<dependency>
<groupId>cn.crane4j</groupId>
<artifactId>crane4j-spring-boot-starter</artifactId>
<version>2.6.1</version>
</dependency>
maven坐标导入后,如果你使用的springboot版本在2.4.0及更高的版本,那么后续就不需要任何额外的配置来引入crane4j。如果是2.4.0以下, 那么你需要在启动类或者配置类上添加@EnableCrane4j或者 @EnableCrane4jFramework来引入自动配置。
@EnableCrane4j
@Configuration
public class Crane4jConfiguration{
}
至此Crane4j就已经安装并且配置完毕。(非Spring的配置方法请参考官方文档)
首先我们先做一个简单样例吧! 在开始自动填充之前,我们先准备一个数据源(Container),它们通过独一无二的命名空间(namespace)区分。为了简单,我们就使用Map集合创造数据源
//从Spring容器中获取全局配置
@Autowired
private Crane4jGlobalConfiguration configuration;
//基于Map集合创建一个数据源容器
Map<Integer,String> map = new HashMap<>();
map.put(1,"a");
map.put(2,"b");
map.put(3,"c");
Container<Integer> container = Containers.forMap("test",map);
//将数据源容器注册到全局配置中
configuration.registerContainer(container);
接着我们需要在实体类上面添加注解
@Data //使用lombok注解,可选择手动创建getter、setter方法
@RequireArgsConstructor
public static class Example{
//根据id填充字段
@Assemble(container = "test",props = @Mapping(ref = "name"))
private final Integer id;
private String name;
}
该配置表示,根据 id 值从容器中获取对应的数据源,并将其填充到 name 属性上。 最后的一步就是触发填充了:
//在方法上添加注解,表明需要自动填充其方法返回值
@Component
public static class Service{
@AutoOperate(type = Example.class) //为Example类自动填充
public List<Example> getExample(){
return Arrays.asList(new Example(1),new Example(2),new Example(3));
}
}
//注入Service,确保AOP能成功拦截
@AutoWired
private Service service;
//自动填入方法返回值
List<Example> examples = service.getExample();
System.out.print(examples);
当控制台输出相关内容时,至此你就已经完成快速入门案例了。
[QuickStartWithSpringBootTest.Example(id=1, name=a), QuickStartWithSpringBootTest.Example(id=2, name=b), QuickStartWithSpringBootTest.Example(id=3, name=c)]
接下来为了更贴近实际,我准备了一个SpringMVC的案例 首先我们假设有一个User接口用于根据id查询用户信息。首先来个正常写法。
@RequestMapping("/user")
@RestController
public class UserController{
@Autowired
private UserService userService;
@PostMapping
public List<UserVO>listUser(@RequestBody List<Integer> ids){
return userService.listByIds(ids);
}
}
//为了代码简单起见,省略Service接口,直接使用实现类
@Service
public class UserService{
p public List<UserVO> listUser(@RequestBody List<Integer> ids) {
List<UserVO> users = userService.listByIds(ids);
}
//填充性别
Map<Integer, String> genderMap = Stream.of(Gender.values())
.collect(Collectors.toMap(Gender::getCode, Gender::getName));
users.forEach(user -> {
Integer genderCode = user.getGenderCode();
user.setGenderName(orderTypeMap.get(genderCode));
});
return users;
}
我们可以使用 crane4j 进行优化。 首先,依然是在 UserVO 中使用注解对填充字段进行配置:
@Data
public class UserVO{
private Integer id;
//这里将Gender设置为枚举
@AssembleEnum{
type = Gender.class,enumKey = "code",
props = @Mapping(ref = "genderName")
}
private Integer genderCode;
private String genderName;
}
然后将 UserService 中原本的填充代码移除,并在 UserController 对应方法上添加 @AutoOperate 注解即可(有时候,我们会在 Controller 中显式的使用通用响应体包装返回值Result类,此时,我们真正需要填充的数据其实是 Result.data,则可以在 @AutoOperate 注解中通过 on 属性指定):
@RequestMapping("/user")
@RestController
public class UserController {
@Autowried
private UserService userService;
@AutoOperate(type = UserVO.class, on = "data")// 声明自动填充,这里的Result类似:
/**
* public class Result<T> {
private String msg = "ok";
private Integer code = 200;
private T data;
public Result(T data) {
this.data = data;
}
}
*/
@PostMapping
public List<UserVO> listUser(@RequestBody List<Integer> ids) {
return userService.listByIds(ids);
}
}
现在正式开始填充包装对象:
@PostMapping
public Result<List<UserVO>> listUser(@RequestBody List<Integer> ids) {
// 返回值被通用响应体包装
return new Result<>(userService.listByIds(ids));
}
综上不难看出使用了Crane4j后仅用几个注解就代替了原来几十行冗余的代码,极大提高了开发效率。并且情况越复杂,Crane4j的优势越明显!
相信到这里了大家都已经或多或少的了解到了Crane4j的基本原理和基本使用方法,详情请翻阅在文章开头的文档。最后再次希望大家动动手点star,你们的star是我们不断开发的动力!
在 1.1.0 发布以后,crane4j 的项目推广需要提上日程,不过在这之前,需要先好好整理一篇项目推广的文章,如果可以的话希望能在周五前肝出来。
在求助万能的 ChatGPT 后,目前得到了以下可以参考的建议:
关于推广文章的大纲:
关于如何突出项目的优点: