+Accept注解支持非同名字段拷贝

This commit is contained in:
mazhicheng 2020-06-04 20:37:51 +08:00
parent 8239b57580
commit db1113aa9d
8 changed files with 145 additions and 4 deletions

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2015-2020, www.dibo.ltd (service@dibo.ltd).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.diboot.core.binding.copy;
import java.lang.annotation.*;
/**
* 拷贝字段时的非同名字段处理
* @author mazc@dibo.ltd
* @version v2.1
* @date 2020/06/04
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface Accept {
/**
* 接收来源对象的属性名
* @return
*/
String name();
/**
* source该字段有值时是否覆盖
* @return
*/
boolean override() default false;
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2015-2020, www.dibo.ltd (service@dibo.ltd).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.diboot.core.binding.copy;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.V;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Accept注解拷贝器
* @author mazc@dibo.ltd
* @version v1.0
* @date 2020/06/04
*/
@Slf4j
public class AcceptAnnoCopier {
/**
* 注解缓存
*/
private static Map<String, List<String[]>> CLASS_ACCEPT_ANNO_CACHE_MAP = new ConcurrentHashMap<>();
// 下标
private static final int IDX_TARGET_FIELD = 0, IDX_SOURCE_FIELD = 1, IDX_OVERRIDE = 2;
/**
* 基于注解拷贝属性
* @param source
* @param target
*/
public static void copyAcceptProperties(Object source, Object target){
String key = target.getClass().getName();
// 初始化
if(!CLASS_ACCEPT_ANNO_CACHE_MAP.containsKey(key)){
List<Field> annoFieldList = BeanUtils.extractFields(target.getClass(), Accept.class);
if(V.isEmpty(annoFieldList)){
CLASS_ACCEPT_ANNO_CACHE_MAP.put(key, Collections.EMPTY_LIST);
}
else{
List<String[]> annoDefList = new ArrayList<>(annoFieldList.size());
for(Field fld : annoFieldList){
Accept accept = fld.getAnnotation(Accept.class);
String[] annoDef = {fld.getName(), accept.name(), accept.override()? "1":"0"};
annoDefList.add(annoDef);
}
CLASS_ACCEPT_ANNO_CACHE_MAP.put(key, annoDefList);
}
}
// 解析copy
List<String[]> acceptAnnos = CLASS_ACCEPT_ANNO_CACHE_MAP.get(key);
if(V.isEmpty(acceptAnnos)){
return;
}
for(String[] annoDef : acceptAnnos){
boolean override = !"0".equals(annoDef[IDX_OVERRIDE]);
if(!override){
Object targetValue = BeanUtils.getProperty(target, annoDef[IDX_TARGET_FIELD]);
if(targetValue != null){
log.debug("目标对象{}已有值{}copyAcceptProperties将忽略.", key, targetValue);
continue;
}
}
Object sourceValue = BeanUtils.getProperty(source, annoDef[IDX_SOURCE_FIELD]);
if(sourceValue != null){
BeanUtils.setProperty(target, annoDef[IDX_TARGET_FIELD], sourceValue);
}
}
}
}

View File

@ -210,7 +210,7 @@ public interface BaseService<T> {
/**
* 获取符合条件的一个Entity实体
* @param queryWrapper 主键
* @param queryWrapper
* @return entity
*/
T getSingleEntity(Wrapper queryWrapper);

View File

@ -16,6 +16,7 @@
package com.diboot.core.util;
import com.diboot.core.binding.copy.AcceptAnnoCopier;
import com.diboot.core.config.Cons;
import com.diboot.core.entity.BaseEntity;
import com.diboot.core.exception.BusinessException;
@ -71,6 +72,8 @@ public class BeanUtils {
public static Object copyProperties(Object source, Object target){
// 链式调用无法使用BeanCopier拷贝换用BeanUtils
org.springframework.beans.BeanUtils.copyProperties(source, target);
// 处理Accept注解标识的不同字段名拷贝
AcceptAnnoCopier.copyAcceptProperties(source, target);
return target;
}

View File

@ -16,6 +16,7 @@
package diboot.core.test.binder.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.diboot.core.binding.copy.Accept;
import com.diboot.core.entity.BaseEntity;
import lombok.Getter;
import lombok.Setter;
@ -38,6 +39,7 @@ public class User extends BaseEntity {
@TableField
private String username;
@Accept(name = "itemName")
@TableField
private String gender;

View File

@ -44,11 +44,11 @@ public class DepartmentVO {
@TableField
private Long orgId;
// 通过中间表关联Entity
// 关联Entity
@BindEntity(entity = Department.class, condition = "this.parent_id=id") // AND ...
private Department department;
// 通过中间表关联Entity
// 关联Entity赋值给VO
@BindEntity(entity = Organization.class, condition = "this.org_id=id") // AND ...
private OrganizationVO organizationVO;

View File

@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.vo.DictionaryVO;
import diboot.core.test.binder.entity.User;
import org.junit.Assert;
import org.junit.Test;
@ -57,6 +58,14 @@ public class BeanUtilsTest {
Assert.assertTrue(dictionary3.getItemName().equals(itemName));
Assert.assertTrue(dictionary3.isEditable() == true);
Assert.assertTrue(dictionary3.getCreateTime() != null);
// Accept注解拷贝
User user = new User();
BeanUtils.copyProperties(dictionary3, user);
Assert.assertTrue(user.getGender().equals(dictionary3.getItemName()));
user.setGender("123");
BeanUtils.copyProperties(dictionary3, user);
Assert.assertTrue(user.getGender().equals("123"));
}
@Test

View File

@ -51,11 +51,13 @@ public class DTest {
JsonResult j2 = new JsonResult(token, "申请token成功");
JsonResult j3 = new JsonResult(Status.OK, token);
JsonResult j4 = new JsonResult(Status.OK, token, "申请token成功");
JsonResult j5 = new JsonResult(Status.OK);
JsonResult j5 = JsonResult.OK();
JsonResult j6 = JsonResult.FAIL_VALIDATION("xxx验证错误");
System.out.println(j1.getData());
System.out.println(j2.getData());
System.out.println(j3.getData());
System.out.println(j4.getData());
System.out.println(j5.getData());
Assert.assertTrue(j6.getMsg().contains("xxx验证错误"));
}
}