业务中存在大量的request -> domin -> response的类型转换
由于懒,不想写这么多参数赋值,所以有了以下
为了方便写一个反射方法
public static <F, T> T reflectionAttr(F f, Class<T> t) {
try {
Field[] fields1 = f.getClass().getDeclaredFields();
T t1 = t.getDeclaredConstructor().newInstance();
Field[] fields2 = t1.getClass().getDeclaredFields();
for (Field f1 : fields1) {
for (Field f2 : fields2) {
if (f1.getName().equals(f2.getName())) {
handler(f1, f2, f, t1);
}
}
}
return t1;
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
return null;
}
private static <F, T> void handler(Field f1, Field f2, F f, T t1) throws Exception {
Class<?> type = f1.getType();
if (type.isEnum()) {
//处理枚举
Object[] enumConstants = f2.getType().getEnumConstants();
for (Object ob : enumConstants) {
if (ob.toString().equals(f1.get(f).toString())) {
f2.set(t1, ob);
}
}
} else if (type == ObjectId.class) {
//处理objectId
f2.set(t1, f1.get(f).toString());
} else {
f2.set(t1, f1.get(f));
}
}
优势:所有类中参数名一样的值都可以直接赋值
缺点:由于使用反射+大量for循环 在重复百万次时速度差10-20倍
考虑其它方案:
代码生成:通过模板生成对应的方法
核心组件velocity
流程:
1.创建模板
2.加载模块
3.加载数据
4.生成代码
记一个经验:******
在创建模板后,生成的代码的存在对不齐的问题。即,如何按自己的想法创建格式规范的代码;
在经过10多次调试之后~~
理论上来说,你在模板里怎么写就会生成对应格式的代码
但是在使用for循环,if判断时,要了解到,这些特殊字符前的符号也是站位的,而这些也是造成对不齐最大的原因,尽可能将for,if顶格写,需要追加的字符串前需要多少空格或者tab就直接加即可;
下面是一个包含增删改查的service模板
/**
* @author ${author}
*/
public class ${className}Service {
@Inject
Repository<${className}> ${classname}Repository;
public Create${className}Response create(Create${className}Request request) {
${className} ${classname} = new ${className}();
#foreach ($column in $columns)#if($column.attrType == "LocalDateTime")
${classname}.${column.attrname} = LocalDateTime.now();
#elseif($column.attrType == "LocalDate")
${classname}.${column.attrname} = LocalDate.now();
#elseif($column.extra == "auto_increment")
#elseif($column.dataType=="enum")
${classname}.${column.attrname} = Enum.valueOf(${column.attrName}.class, request.${column.attrname}.toString());
#else
${classname}.${column.attrname} = request.${column.attrname};
#end
#end
${classname}.id = ${classname}Repository.insert(${classname}).orElseThrow(() -> new RuntimeException("create ${classname} failed"));
Create${className}Response create${className}Response = new Create${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
create${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
create${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
return create${className}Response;
}
private ${className} get(Long id) {
return ${classname}Repository.get(id).orElseThrow(() -> new NotFoundException("${classname} not found"));
}
public Update${className}Response update(Long id, Update${className}Request request) {
${className} ${classname} = get(id);
#foreach ($column in $columns)#if($column.attrname.indexOf("created")!=-1)
#elseif($column.attrType == "LocalDate")
${classname}.${column.attrname} = LocalDate.now();
#elseif($column.extra == "auto_increment")
#elseif($column.attrType == "LocalDateTime")
${classname}.${column.attrname} = LocalDateTime.now();
#elseif($column.dataType=="enum")
${classname}.${column.attrname} = Enum.valueOf(${column.attrName}.class, request.${column.attrname}.toString());
#else
${classname}.${column.attrname} = request.${column.attrname};
#end
#end
${classname}Repository.update(${classname});
Update${className}Response update${className}Response = new Update${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
update${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
update${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
return update${className}Response;
}
public Get${className}Response getView(Long id) {
${className} ${classname} = get(id);
Get${className}Response get${className}Response = new Get${className}Response();
#foreach ($column in $columns)#if($column.dataType=="enum")
get${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
get${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
return get${className}Response;
}
public Search${className}Response search(Search${className}Request request) {
Query<${className}> query = ${classname}Repository.select();
query.skip(request.skip);
query.limit(request.limit);
Search${className}Response search${className}Response = new Search${className}Response();
search${className}Response.total = query.count();
search${className}Response.${tableName} = query.fetch()
.stream().map(${classname} -> {
Search${className}Response.${className} search${className} = new Search${className}Response.${className}();
#foreach ($column in $columns)#if($column.dataType=="enum")
Search${className}Response.${column.attrname} = Enum.valueOf(${column.attrName}View.class, ${classname}.${column.attrname}.toString());
#else
Search${className}Response.${column.attrname} = ${classname}.${column.attrname};
#end
#end
return search${className};
}).collect(Collectors.toList());
return search${className}Response;
}
public void delete(Long id) {
get(id);
${classname}Repository.delete(id);
}
}
经验2:刚开始调试模板的,总要重启项目才能重新加载,在idea中加如jrebel插件后,每次改完模板,点击build即可,不用重启项目,加快调式速度
网友评论