一、注解类
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFill {}
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DictBind {String code(); //字典分類編碼String[] kvs();//kvs={"a:A","b:B"} //a為本類屬性 A為字典屬性或者目標類屬性
}
实体关联注入
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldBind {String beanName();String methodName();String[] kvs();//kvs={"a:A","b:B"} //a為本類屬性 A為字典屬性或者目標類屬性}
二、注解拦截器
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import com.anyec.base.converter.DataConverter;@Component
@Aspect
public class DataFillAspect {private static final Logger log = LoggerFactory.getLogger(DataFillAspect.class);@Pointcut(value="@annotation(com.anyec.base.annotation.DataFill)")public void dataPointCut() {}@AfterReturning(pointcut = "dataPointCut()",returning = "value")public Object dataFill(JoinPoint joinPoint,Object value) throws Exception{return DataConverter.convert(value);}}
三、注解的实现
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;import com.anyec.base.annotation.DictBind;
import com.anyec.base.annotation.FieldBind;
import com.anyec.base.model.Dict;
import com.anyec.base.model.RT;
import com.anyec.base.utils.SpringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;public class DataConverter {private static final Logger log = LoggerFactory.getLogger(DataConverter.class);public static Object convert(Object value) throws Exception{if(value==null||ClassUtils.isPrimitiveWrapper(value.getClass())) {return value;}if(value instanceof List) {if(((List)value).size()<1) {return value;}convertList((List)value);}else if(value instanceof IPage) {if(((IPage)value).getRecords()==null||((IPage)value).getRecords().size()<1) {return value;}convertList(((IPage)value).getRecords());}else if(value instanceof Map) {Set<Map.Entry<Object,Object>> items = ((Map)value).entrySet();List<Object> list=new ArrayList<>();for(Map.Entry<Object,Object> item:items) {list.add(item.getValue());}convert(list);}else if(value instanceof RT) {Object data=((RT)value).getData();convert(data);}else {convertObject(value);}return value;}public static void convertObject(Object value) throws Exception{convertModelObject(value);convertDictObject(value);}public static void convertList(List<Object> value) throws Exception{convertModelList(value);convertDictList(value);}public static void convertDictObject(Object value) throws Exception {//1、解析出Field,DictTag相关信息Map<Field,DictBind> tags=getDictFields(value.getClass());Map<String,Field> valueFieldMap=mapFields(value.getClass());Set<Field> fields=tags.keySet();//获取所有字典类型得编码Set<String> dictTypes=fields.stream().map(f->tags.get(f).code()).filter(s->!StringUtils.isEmpty(s)).collect(Collectors.toSet());//通过字典类型编码获取所有得字典映射值Map<String,Map<String,Object>> dictsData=getDicts(dictTypes);String clazzName=value.getClass().getName();//通过每个关联Field获取需要赋值得字段for(Field field:fields) {//获取field上的注解信息DictBind tag=tags.get(field);String code=tag.code();//获取字典分类的编码String[] kvs=tag.kvs();//获取映射关系Map<String,String> stMap=new HashMap<>();for(String kv:kvs) {String[] kvitem=kv.split(":");if(kvitem==null||kvitem.length!=2) {log.error("{} dict code:{},kv is invalid",clazzName,code);continue;}stMap.put(kvitem[0], kvitem[1]);}Map<String,Object> dictValues=dictsData.getOrDefault(code, new HashMap<String,Object>());String one=(String) field.get(value);//获取主键的值if(Objects.isNull(one)||StringUtils.isEmpty(one)) {log.info("{} field {} value is null",clazzName,field.getName());continue;}Object dictValue=dictValues.get(one);if(Objects.isNull(dictValue)) {log.info("{} field {} value {} 's dict value is null",clazzName,field.getName(),one);continue;}Map<String,Field> dictFieldMap=mapFields(dictValue.getClass());Set<String> stkey=stMap.keySet();for(String key:stkey) {Field valuefield=valueFieldMap.get(key);if(valuefield==null) {log.info("{} valuefield :{} is not exists",clazzName,key);continue;}Field dictfield=dictFieldMap.get(stMap.get(key));if(dictfield==null) {log.info("{} valuefield :{} dictfield :{} is not exists",clazzName,key,stMap.get(key));continue;}valuefield.set(value, dictfield.get(dictValue));}}}public static void convertDictList(List<Object> list) throws Exception{if(list==null||list.size()<1) {return;}Object value=list.get(0);String clazzName=value.getClass().getName();if(value==null||ClassUtils.isPrimitiveWrapper(value.getClass())) {return ;}//1、解析出Field,DictTag相关信息Map<Field,DictBind> tags=getDictFields(value.getClass());if(tags==null||tags.size()<1)return;Map<String,Field> valueFieldMap=mapFields(value.getClass());Set<Field> fields=tags.keySet();//获取所有字典类型得编码Set<String> dictTypes=fields.stream().map(f->tags.get(f).code()).filter(s->!StringUtils.isEmpty(s)).collect(Collectors.toSet());//通过字典类型编码获取所有得字典映射值Map<String,Map<String,Object>> dictsData=getDicts(dictTypes);//通过每个关联Field获取需要赋值得字段for(Field field:fields) {//获取field上的注解信息DictBind tag=tags.get(field);String code=tag.code();//获取字典分类的编码String[] kvs=tag.kvs();//获取映射关系Map<String,String> stMap=new HashMap<>();for(String kv:kvs) {String[] kvitem=kv.split(":");if(kvitem==null||kvitem.length!=2) {log.error("{} dict code:{},kv is invalid",clazzName,code);continue;}stMap.put(kvitem[0], kvitem[1]);}for(Object item:list) {Map<String,Object> dictValues=dictsData.getOrDefault(code, new HashMap<String,Object>());String one=(String) field.get(item);//获取主键的值if(Objects.isNull(one)||StringUtils.isEmpty(one)) {log.info("{} field {} value is null",clazzName,field.getName());continue;}Object dictValue=dictValues.get(one);if(Objects.isNull(dictValue)) {log.info("{} field {} value {} 's dict value is null",clazzName,field.getName(),one);continue;}Map<String,Field> dictFieldMap=mapFields(dictValue.getClass());Set<String> stkey=stMap.keySet();for(String key:stkey) {Field valuefield=valueFieldMap.get(key);if(valuefield==null) {log.info("{} valuefield :{} is not exists",clazzName,key);continue;}Field dictfield=dictFieldMap.get(stMap.get(key));if(dictfield==null) {log.info("{} valuefield :{} dictfield :{} is not exists",clazzName,key,stMap.get(key));continue;}valuefield.set(item, dictfield.get(dictValue));}}}}public static void convertModelObject(Object value) throws Exception{if(value==null||ClassUtils.isPrimitiveWrapper(value.getClass())) {return ;}Map<Field,FieldBind> tags=getModelFields(value.getClass());if(tags==null||tags.size()<1) {return;}String clazzName=value.getClass().getName();Map<String,Set<Object>> idsMap=new HashMap<>();//ModelTag的 beanname和methodName 组合为key,包含的idsMap<String,List<Field>> fieldGroupSet=new HashMap<>();//同一个方法有几个FieldMap<String,FieldBind> tagMap=new HashMap<>();//ModelTag的 beanname和methodName 组合为key,映射的ModelTagSet<Field> tagKeys=tags.keySet();for(Field field:tagKeys) {FieldBind tag=tags.get(field);String key=tag.beanName()+"_"+tag.methodName();if(!idsMap.containsKey(key)) {idsMap.put(key, new HashSet<>());}if(!fieldGroupSet.containsKey(key)) {fieldGroupSet.put(key, new ArrayList<>());}Set<Object> idsSet=idsMap.get(key);List<Field> fieldGroup=fieldGroupSet.get(key);Object idValue=field.get(value);if(idValue==null) {continue;}idsSet.add(idValue);tagMap.put(key, tag);fieldGroup.add(field);}Set<String> serviceMethodKeys=idsMap.keySet();Map<String,Field> valueFieldsMap=mapFields(value.getClass());for(String key:serviceMethodKeys) {Set<Object> ids=idsMap.get(key);FieldBind ntag=tagMap.get(key);Map<Object,Object> targetValues=getModelData(ntag,ids);List<Field> fields=fieldGroupSet.get(key);for(Field field:fields) {Object id=field.get(value);if(id==null) {continue;}Object target=targetValues.get(id);if(target==null) {continue;}Map<String,Field> targetFieldsMap=mapFields(target.getClass());FieldBind tag=field.getAnnotation(FieldBind.class);String[] kvs=tag.kvs();for(String kv:kvs) {String[] kvitem=kv.split(":");if(kvitem==null||kvitem.length!=2) {log.info("{} code:{},kv is invalid",clazzName,key);continue;}Field sField=valueFieldsMap.get(kvitem[0]);if(sField==null) {log.error("{} key:{} source field:{} not exists",clazzName,key,kvitem[0]);}Field tField=targetFieldsMap.get(kvitem[1]);if(sField==null) {log.error("{} key:{} target field:{} not exists",clazzName,key,kvitem[1]);}sField.set(value, tField.get(target));}}}}public static void convertModelList(List<Object> list) throws Exception{if(list==null||list.size()<1) {return;}Object value=list.get(0);if(value==null||ClassUtils.isPrimitiveWrapper(value.getClass())) {return ;}Map<Field,FieldBind> tags=getModelFields(value.getClass());if(tags==null||tags.size()<1) {return;}Map<String,Set<Object>> idsMap=new HashMap<>();//ModelTag的 beanname和methodName 组合为key,包含的idsMap<String,List<Field>> fieldGroupSet=new HashMap<>();//同一个方法有几个FieldMap<String,FieldBind> tagMap=new HashMap<>();//ModelTag的 beanname和methodName 组合为key,映射的ModelTagSet<Field> tagKeys=tags.keySet();for(Field field:tagKeys) {FieldBind tag=tags.get(field);String key=tag.beanName()+"_"+tag.methodName();if(!idsMap.containsKey(key)) {idsMap.put(key, new HashSet<>());}if(!fieldGroupSet.containsKey(key)) {fieldGroupSet.put(key, new ArrayList<>());}Set<Object> idsSet=idsMap.get(key);List<Field> fieldGroup=fieldGroupSet.get(key);for(Object item:list) {Object idValue=field.get(item);if(idValue!=null) {idsSet.add(idValue);}}tagMap.put(key, tag);fieldGroup.add(field);}Set<String> serviceMethodKeys=idsMap.keySet();Map<String,Field> valueFieldsMap=mapFields(value.getClass());for(String key:serviceMethodKeys) {Set<Object> ids=idsMap.get(key);FieldBind ntag=tagMap.get(key);Map<Object,Object> targetValues=getModelData(ntag,ids);List<Field> fields=fieldGroupSet.get(key);for(Object item:list) {for(Field field:fields) {Object id=field.get(item);if(id==null) {continue;}Object target=targetValues.get(id);if(target==null) {continue;}Map<String,Field> targetFieldsMap=mapFields(target.getClass());FieldBind tag=field.getAnnotation(FieldBind.class);String[] kvs=tag.kvs();for(String kv:kvs) {String[] kvitem=kv.split(":");if(kvitem==null||kvitem.length!=2) {log.info("code:{},kv is invalid",key);continue;}Field sField=valueFieldsMap.get(kvitem[0]);if(sField==null) {log.error("key:{} source field:{} not exists",key,kvitem[0]);}Field tField=targetFieldsMap.get(kvitem[1]);if(sField==null) {log.error("key:{} target field:{} not exists",key,kvitem[1]);}sField.set(item, tField.get(target));}}}}}
//这本方法需要根据实际项目改成从数据库获取字典信息 todostatic Map<String,Map<String,Object>> getDicts(Set<String> dictTypes){Map<String,Map<String,Object>> dictsData=new HashMap<>();for(String key:dictTypes) {Map<String,Object> typeMap=new HashMap<>();dictsData.put(key, typeMap);for(int i=0;i<100;i++) {Dict dict=new Dict();dict.setCode(String.valueOf(i));dict.setValue1("v1"+i);dict.setValue2("v2"+i);typeMap.put(String.valueOf(i), dict);}}return dictsData;}static Map<Object,Object> getModelData(FieldBind tag,Set<Object> ids) throws Exception{String beanName=tag.beanName();String methodName=tag.methodName();Object service=SpringUtils.getBean(beanName);Class<?> serviceClass=service.getClass();Method method=serviceClass.getMethod(methodName, Set.class);return (Map<Object,Object>)method.invoke(service, ids);}private static Map<Field,DictBind> getDictFields(Class<?> clazz){Field[] fields=clazz.getDeclaredFields();Map<Field,DictBind> tags=new HashMap<>();for(Field field:fields) {field.setAccessible(true);DictBind tag=field.getAnnotation(DictBind.class);if(tag==null) {continue;}tags.put(field, tag);}return tags;}private static Map<Field,FieldBind> getModelFields(Class<?> clazz){Field[] fields=clazz.getDeclaredFields();Map<Field,FieldBind> tags=new HashMap<>();for(Field field:fields) {field.setAccessible(true);FieldBind tag=field.getAnnotation(FieldBind.class);if(tag==null) {continue;}tags.put(field, tag);}return tags;}// private static <T> Map<Field,T> getModelFields(Class<?> clazz,Class<T> tagClazz){
// Field[] fields=clazz.getDeclaredFields();
// Map<Field,T> tags=new HashMap<>();
// for(Field field:fields) {
// field.setAccessible(true);
// T tag=field.getDeclaredAnnotation((Class<T>) tagClazz);
// if(tag==null) {
// continue;
// }
// tags.put(field, tag);
// }
// return tags;
// }private static Map<String,Field> mapFields(Class<?> clazz){Field[] fields=clazz.getDeclaredFields();Map<String,Field> tags=new HashMap<>();for(Field field:fields) {field.setAccessible(true);tags.put(field.getName(), field);}return tags;}}
四、注解的使用
字典实体
package com.anyec.base.model;import io.swagger.annotations.ApiModel;@ApiModel
public class Dict {private String code;private String value1;private String value2;public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getValue1() {return value1;}public void setValue1(String value1) {this.value1 = value1;}public String getValue2() {return value2;}public void setValue2(String value2) {this.value2 = value2;}}
注解的实体
import com.anyec.base.annotation.DictBind;
import com.anyec.base.annotation.FieldBind;import io.swagger.annotations.ApiModel;@ApiModel
public class User {private Long id;@DictBind(code="code1",kvs= {"name:value1","addr:value2"})private String code;private String name;private String addr;@DictBind(code="code2",kvs= {"name2:value1","addr2:value2","addr22:value2"})private String code2;private String name2;private String addr2;private String addr22;@FieldBind(beanName="userService",methodName="mapTeatcherByIds",kvs= {"tname:tname","taddr:taddr"})private Long tid;private String tname;private String taddr;@FieldBind(beanName="userService",methodName="mapTeatcherByIds",kvs= {"tname2:tname","taddr2:taddr","taddr22:taddr"})private Long tid2;private String tname2;private String taddr2;private String taddr22;@FieldBind(beanName="userService",methodName="mapExtByIds",kvs= {"extName:extName","extAddr:extAddr"})private Long extId;private String extName;private String extAddr;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddr() {return addr;}public void setAddr(String addr) {this.addr = addr;}public String getCode2() {return code2;}public void setCode2(String code2) {this.code2 = code2;}public String getName2() {return name2;}public void setName2(String name2) {this.name2 = name2;}public String getAddr2() {return addr2;}public void setAddr2(String addr2) {this.addr2 = addr2;}public Long getTid() {return tid;}public void setTid(Long tid) {this.tid = tid;}public String getTname() {return tname;}public void setTname(String tname) {this.tname = tname;}public String getTaddr() {return taddr;}public void setTaddr(String taddr) {this.taddr = taddr;}public Long getTid2() {return tid2;}public void setTid2(Long tid2) {this.tid2 = tid2;}public String getTname2() {return tname2;}public void setTname2(String tname2) {this.tname2 = tname2;}public String getTaddr2() {return taddr2;}public void setTaddr2(String taddr2) {this.taddr2 = taddr2;}public String getAddr22() {return addr22;}public void setAddr22(String addr22) {this.addr22 = addr22;}public String getTaddr22() {return taddr22;}public void setTaddr22(String taddr22) {this.taddr22 = taddr22;}public Long getExtId() {return extId;}public void setExtId(Long extId) {this.extId = extId;}public String getExtName() {return extName;}public void setExtName(String extName) {this.extName = extName;}public String getExtAddr() {return extAddr;}public void setExtAddr(String extAddr) {this.extAddr = extAddr;}}
五、拦截注解的使用
import java.util.List;
import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.anyec.base.annotation.DataFill;
import com.anyec.base.model.RT;
import com.anyec.biz.service.UserService;
import com.anyec.biz.web.model.User;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;@Api
@Controller
@RequestMapping("/biz")
public class BizWeb {@Autowiredprivate UserService userService;@ApiOperation("/getObject")@GetMapping("/getObject")@ResponseBody@DataFillpublic User getObject() {return userService.getObject();}@ApiOperation("/getList")@GetMapping("/getList")@ResponseBody@DataFillpublic List<User> getList() {return userService.getList();}@ApiOperation("/getPage")@GetMapping("/getPage")@ResponseBody@DataFillpublic Page getPage() {Page page=new Page();page.setRecords(getList());return page;}@ApiOperation("/getRTPage")@GetMapping("/getRTPage")@ResponseBody@DataFillpublic RT<Page> getRTPage() {Page page=new Page();page.setRecords(getList());return RT.ok(page);}@ApiOperation("/getRT")@GetMapping("/getRT")@ResponseBody@DataFillpublic RT<User> getRT() {return userService.getRT();}@ApiOperation("/getMap")@GetMapping("/getMap")@ResponseBody@DataFillpublic Map<Long,User> getMap() {return userService.getMap();}@ApiOperation("/getRTList")@GetMapping("/getRTList")@ResponseBody@DataFillpublic RT<List<User>> getRTList() {return userService.getRTList();}}
UserService类
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import com.anyec.base.model.RT;
import com.anyec.biz.web.model.Teacher;
import com.anyec.biz.web.model.User;
import com.anyec.biz.web.model.UserExt;@Service
public class UserService {private static final Logger log = LoggerFactory.getLogger(UserService.class);public User getObject() {User u=new User();u.setId(1L);u.setCode("1");u.setCode2("2");u.setTid(1L);u.setTid2(2L);u.setExtId(3L);return u;}public List<User> getList() {List<User> list=new ArrayList<>();for(int i=1;i<10;i++) {User u=new User();u.setId(new Long(i));u.setCode(String.valueOf(i));u.setCode2(String.valueOf(i+2));u.setTid(new Long(i));u.setTid2(new Long(i+2));u.setExtId(new Long(i+3));list.add(u);}return list;}public RT<User> getRT() {return RT.ok(getObject());}public Map<Long, User> getMap() {Map<Long, User> map=new HashMap<>();List<User> list=getList();for(User u:list) {map.put(u.getId(), u);}return map;}public RT<List<User>> getRTList() {return RT.ok(getList());}public Map<Long,Teacher> mapTeatcherByIds(Set<Long> ids){log.info(" excute =========> mapTeatcherByIds");Map<Long,Teacher> map=new HashMap<Long, Teacher>();for(Long id:ids) {if(id%5==0) {continue;}Teacher t=new Teacher();t.setId(id);t.setTaddr("taddr-"+id);t.setTname("tname-"+id);map.put(id, t);}return map;}public Map<Long,UserExt> mapExtByIds(Set<Long> ids){log.info(" excute =========> mapExtByIds");Map<Long,UserExt> map=new HashMap<Long, UserExt>();for(Long id:ids) {UserExt t=new UserExt();t.setId(id);t.setExtAddr("extAddr-"+id);t.setExtName("ExtName-"+id);map.put(id, t);}return map;}}