Browse Source

优化说明

zhouhao 7 years ago
parent
commit
70fe5a0df3

+ 22 - 5
README.md

@@ -9,7 +9,25 @@
 
  [贡献代码](CONTRIBUTING.md)  [开发手册](https://github.com/hs-web/hsweb-framework/wiki/开发手册)
 
-本项目是hsweb的核心,不推荐将其直接clone后修改,运行.推荐使用maven依赖的方式使用hsweb.你可以参照[demo](https://github.com/hs-web/hsweb3-demo)进行使用.
+## 应用场景
+1. 后台管理系统.
+2. 完全开源的后台管理系统.
+3. 细粒度权限控制的后台管理系统.
+4. 模块化的后台管理系统.
+5. 功能可拓展的后台管理系统.
+6. 集成各种常用功能的后台管理系统.
+7. 前后分离的后台管理系统.
+
+注意:
+项目主要基于`spring-boot`,`mybatis`. 在使用`hsweb`之前,你应该对`spring-boot`有一定的了解.
+
+项目模块太多?不要被吓到.我们不推荐将本项目直接`clone`后修改,运行.而是使用maven依赖的方式使用`hsweb`. 
+选择自己需要的模块进行依赖,正式版发布后,所有模块都将发布到maven中央仓库.
+你可以参照[demo](https://github.com/hs-web/hsweb3-demo)进行使用.
+
+##文档
+各个模块的使用方式查看对应模块下的 `README.md`,在使用之前,
+你可以先粗略浏览一下各个模块,对每个模块的作用有大致的了解.
 
 ## 模块简介
 
@@ -18,12 +36,11 @@
 |[hsweb-authorization](hsweb-authorization)|权限控制| 90%|
 |[hsweb-commons](hsweb-commons) |基础通用功能| 90%|
 |[hsweb-concurrent](hsweb-concurrent)|并发包,缓存,锁,计数器等| 80%|
-|[hsweb-core](hsweb-core)|框架核心| 90%|
+|[hsweb-core](hsweb-core)|框架核心,基础工具类| 90%|
 |[hsweb-datasource](hsweb-datasource)|数据源| 90%|
 |[hsweb-examples](hsweb-examples)|例子,演示| 10%|
-|[hsweb-i18n](hsweb-i18n)|国际化| 0%|
-|[hsweb-logging](hsweb-logging)| 日志|  80%|
+|[hsweb-logging](hsweb-logging)| 日志|  100%|
 |[hsweb-message](hsweb-message)|mq,websocket...| 80%|
 |[hsweb-starter](hsweb-starter)|模块启动器| 90%|
-|[hsweb-system](hsweb-system)|**系统功能**| 40%|
+|[hsweb-system](hsweb-system)|**系统常用功能**| 60%|
 |[hsweb-tests](hsweb-tests)|测试| 80%|

+ 62 - 0
hsweb-core/README.md

@@ -0,0 +1,62 @@
+# 系统核心,通用工具等
+
+
+### bean 复制工具
+`FastBeanCopier`类. 提供高效的bean复制.支持复杂结构,类型转换,集合泛型,支持bean到map,map到bean的复制.
+
+原理: 使用工具类`Proxy`,通过`javassist`去动态构造一个类,通过原生的方式调用get set方法.而不是通过低效的反射.
+
+```java
+ //将source对象中的属性复制到target中.
+ FastBeanCopier.copy(source,target);
+
+ //将source对象中的属性复制到target中.不复制id字段
+ FastBeanCopier.copy(source,target,"id");
+
+```
+约定: 如果属性类实现了`Cloneable`接口,在复制的时候将调用`clone`方法.所以如果你实现了`Cloneable`接口,就必须重写`clone`方法并且为`public`修饰的.
+
+### 数据字典
+
+可通过枚举来定义数据字典,定义一个枚举,并实现`EnumDict`接口:
+```java
+@AllArgsConstructor
+@Getter
+@Dict(id="data-status") //定义一个id,默认为 DataStatusEnum.class.getSimpleName();
+public enum DataStatusEnum implements EnumDict<Byte> {
+    ENABLED((byte) 1, "正常"),
+    DISABLED((byte) 0, "禁用"),
+    LOCK((byte) -1, "锁定"),
+    DELETED((byte) -10, "删除");
+
+    private Byte value;
+
+    private String text;
+}
+```
+
+在实体类中使用:
+```java
+@Data
+public class User  {
+    private String id;
+    
+    //单选
+    private DataStatusEnum status;
+    
+    //多选
+    private DataStatusEnum[] statusArr;
+}
+```
+
+作用: 
+1. 当值为单选,在持久化到数据库时,将自动存储字典的value值. 因此数据库字段的类型应该与value字段的类型一致.
+2. 当值为多选,并且枚举选项数量小于`64`个,则会将值进行位运算(`EnumDict.toBit`)后存储.在查询的时候也使用位运算进行查询.
+因此数据库字段的类型应该为数字类型。
+如: `where().in("statusArr",0,-1);` 则将生成sql : `where status_arr & {bit} != {bit}` 。
+在java中可以通过`EnumDict`中的静态方法进行判断,如 `in` 和 `anyIn`. 
+3. 当枚举选项数量大于等于`64`个的时候,需要自行实现存储和查询逻辑,可以使用中间表的方式,也可以使用hsweb自带的实现,模块:`hsweb-system/hsweb-system-dictionary`。
+
+注意: 1,2的功能由`hsweb-commons-dao`模块去实现,如果你不没有使用hsweb自带的dao实现,可能无法使用此功能.
+
+所有的字典都会注册到:`DictDefineRepository`,可通过此类去获取字典,以提供给前端或者其他地方使用.

+ 8 - 8
hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java

@@ -451,13 +451,6 @@ public final class FastBeanCopier {
                     return (T) new Date(((Date) source).getTime());
                 }
             }
-            org.apache.commons.beanutils.Converter converter = BeanUtilsBean
-                    .getInstance()
-                    .getConvertUtils()
-                    .lookup(targetClass);
-            if (null != converter) {
-                return converter.convert(targetClass, source);
-            }
             if (Collection.class.isAssignableFrom(targetClass)) {
                 Collection collection = newCollection(targetClass);
                 Collection sourceCollection;
@@ -473,6 +466,7 @@ public final class FastBeanCopier {
                         sourceCollection = Arrays.asList(source);
                     }
                 }
+                //转换泛型
                 if (genericType != null && genericType.length > 0 && genericType[0] != Object.class) {
                     for (Object sourceObj : sourceCollection) {
                         collection.add(convert(sourceObj, genericType[0], null));
@@ -486,7 +480,6 @@ public final class FastBeanCopier {
             if (targetClass.isEnum()) {
                 if (EnumDict.class.isAssignableFrom(targetClass)) {
                     Object val = EnumDict.find((Class) targetClass, String.valueOf(source)).orElse(null);
-
                     if (targetClass.isInstance(val)) {
                         return ((T) val);
                     }
@@ -501,6 +494,13 @@ public final class FastBeanCopier {
                 return null;
             }
             try {
+                org.apache.commons.beanutils.Converter converter = BeanUtilsBean
+                        .getInstance()
+                        .getConvertUtils()
+                        .lookup(targetClass);
+                if (null != converter) {
+                    return converter.convert(targetClass, source);
+                }
 
                 T newTarget = targetClass == Map.class ? (T) new HashMap<>() : targetClass.newInstance();
                 copy(source, newTarget);

+ 1 - 0
hsweb-core/src/test/java/org/hswebframework/web/bean/Target.java

@@ -1,6 +1,7 @@
 package org.hswebframework.web.bean;
 
 import lombok.Data;
+import org.springframework.validation.annotation.Validated;
 
 import java.util.ArrayList;
 import java.util.Date;