feat: 提供更多配置项,减轻负担

This commit is contained in:
wangyu 2021-09-04 23:45:46 +08:00
parent da892f6bda
commit 2722a86949
10 changed files with 181 additions and 24 deletions

View File

@ -13,14 +13,9 @@ import java.lang.annotation.*;
public @interface Properties {
/**
* 需要映射的key
* @return 键们
* 属性们
*
* @return 结果
*/
String[] keys();
/**
* 需要映射的标题
* @return 标题们
*/
String[] titles();
Property[] value();
}

View File

@ -9,13 +9,22 @@ import java.lang.annotation.*;
*
* @author wangyu
*/
@Target({ElementType.FIELD})
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Properties.class)
public @interface Property {
/**
* 手动指定key用于覆盖模式
*
* @return 结果
*/
String key() default "";
/**
* 显示标题
*
* @return 结果
*/
@AliasFor("title")
@ -23,6 +32,7 @@ public @interface Property {
/**
* 显示标题别名
*
* @return 结果
*/
@AliasFor("value")
@ -30,19 +40,36 @@ public @interface Property {
/**
* 描述
*
* @return 结果
*/
String description() default "";
/**
* 被继承的用于父类自动拼接名称
*
* @return 结果
*/
boolean inherited() default false;
/**
* 是否只读
*
* @return 结果
*/
boolean readonly() default false;
/**
* 排序
*
* @return 结果
*/
int order() default 0;
/**
* 分组
*
* @return 结果
*/
String group() default "";
}

View File

@ -0,0 +1,24 @@
package com.flyfish.framework.annotations;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertyGroups.class)
public @interface PropertyGroup {
/**
* 分组名称
*
* @return 结果
*/
String name();
/**
* 分组编码
*
* @return 结果
*/
String code();
}

View File

@ -0,0 +1,15 @@
package com.flyfish.framework.annotations;
import java.lang.annotation.*;
/**
* 属性组定义
* @author wangyu
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertyGroups {
PropertyGroup[] value();
}

View File

@ -60,7 +60,10 @@ public final class DataUtils {
return IntStream.range(0, Math.min(keys.length, names.length))
.boxed()
.reduce(new ArrayList<>(), (result, index) -> {
result.add(mapper.apply(keys[index], names[index]));
R mapped = mapper.apply(keys[index], names[index]);
if (null != mapped) {
result.add(mapped);
}
return result;
}, (a, b) -> a);
}

View File

@ -1,10 +1,12 @@
package com.flyfish.framework.beans.meta;
import com.flyfish.framework.annotations.PropertyGroups;
import com.flyfish.framework.bean.Result;
import com.flyfish.framework.beans.resolver.DynamicRestBeanResolver;
import com.flyfish.framework.domain.base.Vo;
import com.flyfish.framework.utils.StringFormats;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -76,9 +79,22 @@ public class BeanController {
if (!Vo.class.equals(annotation.listViewClass())) {
info.setColumns(BeanProperty.from(annotation.listViewClass()));
}
if (ArrayUtils.isNotEmpty(annotation.meta())) {
Arrays.stream(annotation.meta()).forEach(meta -> {
String[] kv = meta.split("=");
if (kv.length == 2) {
info.set(kv[0], kv[1]);
}
});
}
} else {
info.setCode(StringFormats.camel2Line(ClassUtils.getShortClassName(clazz)));
}
if (clazz.isAnnotationPresent(PropertyGroups.class)) {
PropertyGroups groups = clazz.getAnnotation(PropertyGroups.class);
info.setGroups(Arrays.stream(groups.value()).map(group -> new BeanPropertyGroup(group.name(), group.code()))
.collect(Collectors.toList()));
}
info.setProperties(BeanProperty.from(clazz));
return info;
}

View File

@ -1,11 +1,14 @@
package com.flyfish.framework.beans.meta;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.Objects;
/**
* bean的属性们
*
* @author wangyu
*/
@Data
@ -17,6 +20,12 @@ public class BeanInfo {
// bean的显示名
private String name;
// bean的类型
private String type;
// 分组们
private List<BeanPropertyGroup> groups;
// bean的属性们
private List<BeanProperty> properties;
@ -25,4 +34,19 @@ public class BeanInfo {
// 表格查询属性
private List<BeanProperty> search;
/**
* 自由设置值
*
* @param key
* @param value
*/
public void set(String key, Object value) {
try {
Objects.requireNonNull(BeanUtils.getPropertyDescriptor(this.getClass(), key))
.getWriteMethod().invoke(this, value);
} catch (Exception ignored) {
}
}
}

View File

@ -5,7 +5,6 @@ import com.flyfish.framework.annotations.Properties;
import com.flyfish.framework.annotations.*;
import com.flyfish.framework.domain.base.Qo;
import com.flyfish.framework.domain.base.Vo;
import com.flyfish.framework.utils.DataUtils;
import com.flyfish.framework.utils.ReflectionUtils;
import com.flyfish.framework.utils.StringFormats;
import lombok.Data;
@ -57,6 +56,12 @@ public class BeanProperty {
// 类型为object时拥有子表单
private List<BeanProperty> children;
// 排序变量用于排序
private transient int order;
// 所属分组该分组必须在元数据中定义
private String group;
/**
* 来自属性解释器构造
* 支持对象嵌套
@ -85,6 +90,7 @@ public class BeanProperty {
property.setTitle(props.inherited() ? parentName + props.title() : props.title());
property.setDescription(props.description());
property.setReadonly(props.readonly());
property.setOrder(props.order());
} else if (strict) {
property.setReadonly(true);
return property;
@ -132,8 +138,9 @@ public class BeanProperty {
parseSubClass(field).ifPresent(subClazz -> property.setChildren(from(subClazz)));
} else if (field.isAnnotationPresent(DateRange.class)) {
property.setType(BeanPropertyType.DATE);
property.prop("type", "range");
property.prop("placeholder", Arrays.asList("开始时间", "结束时间"));
property
.prop("type", "range")
.prop("placeholder", Arrays.asList("开始时间", "结束时间"));
}
}
break;
@ -194,7 +201,9 @@ public class BeanProperty {
.map(descriptor -> BeanProperty.form(descriptor, clazz))
.filter(property -> !property.isReadonly())
.collect(Collectors.toList());
return ListUtils.union(parseExtras(clazz), properties);
List<BeanProperty> result = ListUtils.union(parseExtras(clazz, properties), properties);
result.sort(Comparator.comparingInt(a -> a.order));
return result;
}
/**
@ -210,21 +219,37 @@ public class BeanProperty {
/**
* 解析额外的注解
* 以该注解的优先级更高
*
* @param clazz
* @param clazz
* @param origin 原本的元数据
* @return 结果
*/
private static List<BeanProperty> parseExtras(Class<?> clazz) {
private static List<BeanProperty> parseExtras(Class<?> clazz, List<BeanProperty> origin) {
// 包含properties
if (clazz.isAnnotationPresent(Properties.class)) {
List<BeanProperty> result = new ArrayList<>();
Properties properties = clazz.getAnnotation(Properties.class);
return DataUtils.zip(properties.keys(), properties.titles(), (key, name) -> {
BeanProperty property = new BeanProperty();
property.setType(BeanPropertyType.STRING);
property.setName(key);
property.setTitle(name);
return property;
});
for (Property prop : properties.value()) {
String key = prop.key();
// 如果基础元数据已经包含了这部分相当于重载属性此时不会调整其他属性而是替换名称将来可能扩展更多
Optional<BeanProperty> found = origin.stream().filter(property -> property.name.equals(key))
.findFirst();
if (found.isPresent()) {
BeanProperty property = found.get();
property.title = prop.title();
if (prop.order() != 0) {
property.order = prop.order();
}
} else {
BeanProperty property = new BeanProperty();
property.setType(BeanPropertyType.STRING);
property.setName(key);
property.setTitle(prop.title());
result.add(property);
}
}
return result;
}
return Collections.emptyList();
}

View File

@ -0,0 +1,20 @@
package com.flyfish.framework.beans.meta;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 对象属性分组
*
* @author wangyu
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BeanPropertyGroup {
private String name;
private String code;
}

View File

@ -41,10 +41,18 @@ public @interface RestBean {
/**
* 排除的属性
*
* @return 结果
*/
String[] exclude() default {};
/**
* 元数据可以自由地指定一些值
*
* @return 结果
*/
String[] meta() default {};
/**
* 必须指定qo
*