背景 Web 后台开发中,对于一个实体的操作会衍生出多个类似的对象进行操作(避免直接使用实体),由此出现相关名词
持久化对象,即实体 PO(Persistent Object) 传输对象 DTO(Data Transfer Object) 业务对象 BO(Business Object) 展示对象 VO(View Object) 等等…… 这些对象大多数直接从实体里面裁剪几个字段,比如,在一次创建订单请求中以订单实体(OrderEntity)为例,经历如下流程: 1. 接收请求体 CreateOrderRequest 2. 根据 OrderQuery 构造查询对象查询订单 3. 构造 OrderEntity 进行持久化操作 4. 构造 OrderBO 进行下游消费 5. 返回响应体 CreateOrderResponse 可见,从 OrderEntity 衍生出 4 个对象,仅仅是对订单的实体的部分裁剪,但是要编写很多重复的代码(复制也行)。当然,如果是新增字段的话可以使用继承解决。
在 Kotlin Web 后台开发中,data class 的语法特性带来很多优势,但还是避免不了创建类似的重复对象。 所以 Konverter 诞生于此,解决实体对象裁剪问题。还有另一个功能那就是自动生成两个实体间的转换方法。
注意:目前只支持 Kotlin,并且生成的转换方法是通过扩展函数实现
是什么 通过 KAPT(Kotlin Annotation Processing Tool 注解处理以及 Kotlin Poet 代码生成,实现自动生成对实体的相关裁剪的对象。 主要有两个注解:
@Konvertable 生成裁剪的实体以及对应的转换方法 @Konvert 单独针对某个类生成转换方法 废话不多说来看怎么使用。
怎么用 1. 引入依赖 // for build.gradle.kts repositories { maven("https://jitpack.io") } dependencies { kapt("com.github.lexcao:konverter:master-SNAPSHOT") implementation("com.github.lexcao:konverter-annotation:master-SNAPSHOT") } // for build.gradle repositories { maven { url 'https://jitpack.io' } } dependencies { kapt 'com.github.lexcao:konverter:master-SNAPSHOT' implementation 'com.github.lexcao:konverter-annotation:master-SNAPSHOT' } 2. 在需要转换的类上加上注解 @Konvertable( To(name = "LoginDTO", pick = ["username", "password"]), To(name = "UserListDTO", omit = ["password"]) ) @Konvert(to = UserVO::class) data class UserEntity( val id: Long, @Konvert.Field("name") val username: String, val password: String, @Konvert.By(GenderEnumConverter::class) val gender: Int ) 3. 生成的代码如下: // @Konvertable /** * Auto generated code by @Konvertable */ data class LoginDTO( val username: String, val password: String ) /** * Auto generated code by @Konvertable */ data class UserListDTO( val id: Long, val username: String, val gender: Int ) /** * Auto generated code by @Konvert */ fun UserEntity.toLoginDTO(username: String = [email protected], password: String = [email protected]): LoginDTO = LoginDTO(username=username,password=password) /** * Auto generated code by @Konvert */ fun LoginDTO.toUserEntity( id: Long = 0L, username: String = [email protected], password: String = [email protected], gender: Int = 0 ): UserEntity = UserEntity(id=id,username=username,password=password,gender=gender) /** * Auto generated code by @Konvert */ fun UserEntity.toUserListDTO( id: Long = [email protected], username: String = [email protected], gender: Int = [email protected] ): UserListDTO = UserListDTO(id=id,username=username,gender=gender) /** * Auto generated code by @Konvert */ fun UserListDTO.toUserEntity( id: Long = [email protected], username: String = [email protected], password: String = "", gender: Int = [email protected] ): UserEntity = UserEntity(id=id,username=username,password=password,gender=gender) /** * Auto generated code by @Konvert */ fun UserEntity.toRegisterDTO( username: String = [email protected], password: String = [email protected], gender: Int = [email protected] ): RegisterDTO = RegisterDTO(username=username,password=password,gender=gender) /** * Auto generated code by @Konvert */ fun RegisterDTO.toUserEntity( id: Long = 0L, username: String = [email protected], password: String = [email protected], gender: Int = [email protected] ): UserEntity = UserEntity(id=id,username=username,password=password,gender=gender) // @Konvert // 转换为如下对象 data class UserVO( val id: String, val name: String, val gender: GenderEnum ) enum class GenderEnum { MALE, FEMALE; } object GenderEnumConverter : Konvert.KonvertBy<Int, GenderEnum> { override fun Int.forward(): GenderEnum { return GenderEnum.values()[this] } override fun GenderEnum.backward(): Int { return this.ordinal } } // 生成的代码 ** * Auto generated code by @Konvert */ fun UserEntity.toUserVO( id: String = [email protected](), name: String = [email protected], gender: GenderEnum = with(GenderEnumConverter) { [email protected]() } ): UserVO = UserVO(id=id,name=name,gender=gender) /** * Auto generated code by @Konvert */ fun UserVO.toUserEntity( id: Long = [email protected](), username: String = [email protected], password: String = "", gender: Int = with(GenderEnumConverter) { [email protected]() } ): UserEntity = UserEntity(id=id,username=username,password=password,gender=gender) 相关 API 说明 转换规则
...