Quellcode durchsuchen

Merge remote-tracking branch 'origin/master'

zhou-hao vor 6 Jahren
Ursprung
Commit
d7bce6c64e
17 geänderte Dateien mit 212 neuen und 67 gelöschten Zeilen
  1. 62 23
      hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/DefaultExcelImporter.java
  2. 30 2
      hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/Excel.java
  3. 15 1
      hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/ExcelImporter.java
  4. 5 0
      hsweb-boost/hsweb-boost-excel/src/test/java/org/hswebframework/web/excel/DefaultExcelImporterTest.java
  5. BIN
      hsweb-boost/hsweb-boost-excel/src/test/resources/test.xls
  6. 3 0
      hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/QueryController.java
  7. 9 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/AbstractService.java
  8. 12 6
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/AbstractTreeSortService.java
  9. 23 5
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/DefaultLogicPrimaryKeyValidator.java
  10. 12 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/EnableCacheAllEvictTreeSortService.java
  11. 2 5
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericEntityService.java
  12. 4 4
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/DefaultLogicPrimaryKeyValidatorTest.java
  13. 6 5
      hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/ApplicationContextHolder.java
  14. 7 7
      hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java
  15. 1 1
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/README.md
  16. 3 4
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-local/src/main/java/org/hswebframework/web/service/organizational/simple/SimpleDistrictService.java
  17. 18 4
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/DistrictController.java

+ 62 - 23
hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/DefaultExcelImporter.java

@@ -3,8 +3,12 @@ package org.hswebframework.web.excel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Getter;
 import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.expands.office.excel.ExcelIO;
+import org.hswebframework.web.ApplicationContextHolder;
 import org.hswebframework.web.bean.FastBeanCopier;
+import org.hswebframework.web.dict.EnumDict;
+import org.hswebframework.web.dict.ItemDefine;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.ReflectionUtils;
 
@@ -19,11 +23,29 @@ import java.util.function.Supplier;
  * @author zhouhao
  * @since 3.0.0-RC
  */
+@Slf4j
+@SuppressWarnings("all")
 public class DefaultExcelImporter implements ExcelImporter {
 
     protected static Map<Class, Map<Class, HeaderMapper>> headerMappings = new ConcurrentHashMap<>();
 
-    @SuppressWarnings("all")
+    protected static ExcelCellConverter DEFAULT_CONVERTER = new ExcelCellConverter() {
+        @Override
+        public Object convertFromCell(Object from) {
+            return from;
+        }
+
+        @Override
+        public Object convertToCell(Object from) {
+            if (from instanceof EnumDict) {
+                return ((EnumDict) from).getText();
+            }
+            return from;
+        }
+    };
+
+    protected ExcelCellConverter defaultConvert = DEFAULT_CONVERTER;
+
     protected Map<Class, HeaderMapper> createHeaderMapping(Class type) {
         //一些基本类型不做处理
         if (type == String.class
@@ -47,8 +69,7 @@ public class DefaultExcelImporter implements ExcelImporter {
             HeaderMapping mapping = new HeaderMapping();
             mapping.header = header;
             mapping.field = field.getName();
-            mapping.index = excel == null || excel.sheetIndex() == -1 ? index.getAndAdd(1) : excel.sheetIndex();
-            mapping.converter = createConvert(field.getType());
+            mapping.index = excel == null || excel.exportOrder() == -1 ? index.getAndAdd(1) : excel.exportOrder();
             if (null != excel) {
                 mapping.enableImport = excel.enableImport();
                 mapping.enableExport = excel.enableExport();
@@ -58,7 +79,9 @@ public class DefaultExcelImporter implements ExcelImporter {
                             .mappings
                             .add(mapping);
                 }
+                mapping.converter = createConvert(excel.converter(), field.getType());
             } else {
+                mapping.converter = createConvert(ExcelCellConverter.class, field.getType());
                 mapping.children = () -> getHeaderMapper(field.getType());
                 headerMapperMap.computeIfAbsent(Void.class, DefaultHeaderMapper::new)
                         .mappings
@@ -70,19 +93,17 @@ public class DefaultExcelImporter implements ExcelImporter {
         return (Map) headerMapperMap;
     }
 
-    protected <T> ExcelCellConverter<T> createConvert(Class<T> type) {
-        // TODO: 18-6-12
-        return new ExcelCellConverter<T>() {
-            @Override
-            public T convertFromCell(Object from) {
-                return type.cast(from);
-            }
-
-            @Override
-            public Object convertToCell(T from) {
-                return from;
+    @SneakyThrows
+    protected <T> ExcelCellConverter<T> createConvert(Class<ExcelCellConverter> converterClass, Class<T> type) {
+        if (converterClass != ExcelCellConverter.class) {
+            try {
+                return ApplicationContextHolder.get().getBean(converterClass);
+            } catch (Exception e) {
+                log.warn("can not get bean ({}) from spring context.", converterClass, e);
+                return converterClass.newInstance();
             }
-        };
+        }
+        return defaultConvert;
     }
 
     @Getter
@@ -147,11 +168,15 @@ public class DefaultExcelImporter implements ExcelImporter {
         @Override
         public Optional<HeaderMapping> getMapping(String key) {
             return Optional.ofNullable(fastMapping.computeIfAbsent(key, k -> {
+                //尝试获取嵌套的属性
                 for (HeaderMapping mapping : mappings) {
                     String newKey = key;
+                    //字段嵌套
                     if (newKey.startsWith(mapping.field)) {
                         newKey = newKey.substring(mapping.field.length());
-                    } else if (newKey.startsWith(mapping.header)) {
+                    }
+                    //表头嵌套
+                    else if (newKey.startsWith(mapping.header)) {
                         newKey = newKey.substring(mapping.header.length());
                     } else {
                         continue;
@@ -162,6 +187,7 @@ public class DefaultExcelImporter implements ExcelImporter {
                         if (map != null) {
                             map = map.copy();
                             map.field = mapping.field.concat(".").concat(map.field);
+                            map.header = mapping.header.concat(map.header);
                             return map;
                         }
                     }
@@ -191,7 +217,7 @@ public class DefaultExcelImporter implements ExcelImporter {
 
     @Override
     @SneakyThrows
-    public <T> Result<T> doImport(InputStream inputStream, Class<T> type, Function<T, Error> validator, Class... group) {
+    public <T> Result<T> doImport(InputStream inputStream, Class<T> type, Function<T, Error> afterParsed, Class... group) {
         AtomicInteger counter = new AtomicInteger(0);
         AtomicInteger errorCounter = new AtomicInteger(0);
         List<T> data = new ArrayList<>();
@@ -208,31 +234,44 @@ public class DefaultExcelImporter implements ExcelImporter {
 
             for (Map.Entry<String, Object> entry : mapValue.entrySet()) {
                 String key = entry.getKey();
-                Object value = entry.getValue();
-
                 HeaderMapping mapping = headerMapper.getMapping(key).orElse(null);
 
                 if (mapping == null || !mapping.enableImport) {
                     continue;
                 }
+                Object value = mapping.getConverter().convertFromCell(entry.getValue());
 
-                String field = mapping.field;
+                String field = mapping.getField();
                 //嵌套的字段
                 if (field.contains(".")) {
                     String tmpField = field;
                     Map<String, Object> nestMapValue = newValue;
+
                     while (tmpField.contains(".")) {
+
+                        // nest.obj.name => [nest,obj.name]
                         String[] nestFields = tmpField.split("[.]", 2);
+
+                        //nest
+                        String nestField = nestFields[0];
+
+                        //obj.name
                         tmpField = nestFields[1];
-                        Object nestValue = nestMapValue.get(nestFields[0]);
+
+                        Object nestValue = nestMapValue.get(nestField);
+                        //构造嵌套对象为map
                         if (nestValue == null) {
-                            nestMapValue.put(nestFields[0], nestMapValue = new HashMap<>());
+                            nestMapValue.put(nestField, nestMapValue = new HashMap<>());
                         } else {
                             if (nestValue instanceof Map) {
                                 nestMapValue = ((Map) nestValue);
+                            } else {
+                                //这里几乎不可能进入...
+                                nestMapValue.put(nestField, nestMapValue = FastBeanCopier.copy(nestValue, new HashMap<>()));
                             }
                         }
                     }
+                    //最后nestMapValue就为最里层嵌套的对象了
                     nestMapValue.put(tmpField, value);
                 } else {
                     newValue.put(field, value);
@@ -245,7 +284,7 @@ public class DefaultExcelImporter implements ExcelImporter {
 
             data.add(instance);
 
-            Error error = validator.apply(instance);
+            Error error = afterParsed.apply(instance);
             if (null != error) {
                 errorCounter.getAndAdd(1);
                 error.setRowIndex(counter.get());

+ 30 - 2
hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/Excel.java

@@ -1,5 +1,7 @@
 package org.hswebframework.web.excel;
 
+import io.swagger.annotations.ApiModelProperty;
+
 import java.lang.annotation.*;
 
 /**
@@ -11,22 +13,48 @@ import java.lang.annotation.*;
 @Documented
 public @interface Excel {
 
+    /**
+     * @return EXCEL表头
+     * @see ApiModelProperty#value()
+     */
     String value() default "";
 
+    /**
+     * @return 读取指定的工作薄,-1为默认
+     */
     int sheetIndex() default -1;
 
+    /**
+     * @return 是否取消EXCEL导入导出功能
+     */
     boolean ignore() default false;
 
+    /**
+     * @return 是否开启导入, 开启后的字段才能进行导入
+     */
     boolean enableImport() default true;
 
+    /**
+     * @return 是否开启导出, 开启后的字段才能进行导出
+     */
     boolean enableExport() default true;
 
+    /**
+     * @return 导出时, 表头的顺序
+     */
     int exportOrder() default -1;
 
+    /**
+     * @return 导出分组, 可通过分组导入导出不同的字段信息
+     */
     Class[] group() default Void.class;
 
+    /**
+     * 自定义单元格转换器, 用于对数据字典等字段进行自定义转换
+     *
+     * @return 实例必须注入到spring容器中
+     * @see org.springframework.context.ApplicationContext#getBean(Class)
+     */
     Class<ExcelCellConverter> converter() default ExcelCellConverter.class;
 
-    Class<ExcelImporter> importer() default ExcelImporter.class;
-
 }

+ 15 - 1
hsweb-boost/hsweb-boost-excel/src/main/java/org/hswebframework/web/excel/ExcelImporter.java

@@ -3,6 +3,7 @@ package org.hswebframework.web.excel;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Setter;
+import org.hswebframework.web.bean.FastBeanCopier;
 
 import java.io.InputStream;
 import java.util.List;
@@ -16,7 +17,20 @@ public interface ExcelImporter {
 
     ExcelImporter instance = new DefaultExcelImporter();
 
-    <T> Result<T> doImport(InputStream inputStream, Class<T> type, Function<T, Error> validator, Class... group);
+    /**
+     * 解析excel为指定的class对象,并返回解析结果.类上的属性需要注解{@link Excel}或者{@link io.swagger.annotations.ApiModelProperty}.
+     *
+     * @param inputStream excel文件流,支持xls和xlsx
+     * @param type        要解析为的类型
+     * @param afterParsed 每解析完一个对象都会调用此接口,用于自定义操作,如: 数据校验
+     * @param group       导入的分组 {@link Excel#group()},如果不指定则为 {@link Void#getClass()}
+     * @param <T>         泛型
+     * @return 导入结果, 包含了成功, 失败信息
+     * @see Excel
+     * @see FastBeanCopier#getBeanFactory()
+     * @see ExcelImporter#instance 默认的实现
+     */
+    <T> Result<T> doImport(InputStream inputStream, Class<T> type, Function<T, Error> afterParsed, Class... group);
 
     @Builder
     @Getter

+ 5 - 0
hsweb-boost/hsweb-boost-excel/src/test/java/org/hswebframework/web/excel/DefaultExcelImporterTest.java

@@ -6,6 +6,7 @@ import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
 import org.hswebframework.web.commons.bean.Bean;
+import org.hswebframework.web.commons.entity.DataStatusEnum;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -26,6 +27,7 @@ public class DefaultExcelImporterTest {
         Assert.assertEquals(result.success, 1);
         System.out.println(JSON.toJSONString(result.getData(), SerializerFeature.PrettyFormat));
         TestBean bean = result.getData().get(0);
+        Assert.assertNotNull(bean.status);
         Assert.assertNotNull(bean.nest);
         Assert.assertNotNull(bean.nest.nest);
 
@@ -44,6 +46,9 @@ public class DefaultExcelImporterTest {
         @Excel("年龄")
         private int age;
 
+        @Excel("状态")
+        private DataStatusEnum status;
+
         @Excel("嵌套-")
         private TestBean nest;
     }

BIN
hsweb-boost/hsweb-boost-excel/src/test/resources/test.xls


+ 3 - 0
hsweb-commons/hsweb-commons-controller/src/main/java/org/hswebframework/web/controller/QueryController.java

@@ -77,6 +77,9 @@ public interface QueryController<E, PK, Q extends Entity> {
     @GetMapping("/no-paging")
     @ApiOperation(value = "不分页动态查询", responseReference = "get")
     default ResponseMessage<List<E>> listNoPaging(Q param) {
+        if (param instanceof QueryParamEntity) {
+            ((QueryParamEntity) param).setPaging(false);
+        }
         return ok(getService().select(param));
     }
 

+ 9 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/AbstractService.java

@@ -6,10 +6,12 @@ import org.hswebframework.web.commons.entity.Entity;
 import org.hswebframework.web.commons.entity.factory.EntityFactory;
 import org.hswebframework.web.validate.SimpleValidateResults;
 import org.hswebframework.web.validate.ValidationException;
+import org.hswebframework.web.validator.LogicPrimaryKeyValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import javax.annotation.PostConstruct;
 import javax.validation.ConstraintViolation;
 import javax.validation.Validator;
 import java.util.Set;
@@ -29,6 +31,8 @@ public abstract class AbstractService<E extends Entity, PK> implements CreateEnt
 
     protected EntityFactory entityFactory;
 
+    protected LogicPrimaryKeyValidator logicPrimaryKeyValidator;
+
     @Autowired(required = false)
     public void setValidator(Validator validator) {
         this.validator = validator;
@@ -39,6 +43,11 @@ public abstract class AbstractService<E extends Entity, PK> implements CreateEnt
         this.entityFactory = entityFactory;
     }
 
+    @Autowired(required = false)
+    public void setLogicPrimaryKeyValidator(LogicPrimaryKeyValidator logicPrimaryKeyValidator) {
+        this.logicPrimaryKeyValidator = logicPrimaryKeyValidator;
+    }
+
     protected Class<E> entityType;
 
     protected Class<PK> primaryKeyType;

+ 12 - 6
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/AbstractTreeSortService.java

@@ -44,14 +44,19 @@ public abstract class AbstractTreeSortService<E extends TreeSortSupportEntity<PK
         assertNotNull(parentId);
         E old = selectByPk(parentId);
         assertNotNull(old);
-        return createQuery().where().like$(TreeSupportEntity.path, old.getPath()).noPaging().list();
+        return createQuery()
+                .where()
+                .like$(TreeSupportEntity.path, old.getPath())
+                .listNoPaging();
     }
 
     @Override
     @Transactional(readOnly = true)
     public List<E> selectChildNode(PK parentId) {
         assertNotNull(parentId);
-        return createQuery().where(TreeSupportEntity.parentId, parentId).noPaging().list();
+        return createQuery()
+                .where(TreeSupportEntity.parentId, parentId)
+                .listNoPaging();
     }
 
     //当父节点不存在时,创建parentId
@@ -67,6 +72,7 @@ public abstract class AbstractTreeSortService<E extends TreeSortSupportEntity<PK
         if (StringUtils.isEmpty(entity.getParentId())) {
             entity.setSortIndex(0L);
             entity.setParentId(createParentIdOnExists());
+            entity.setLevel(0);
             entity.setPath(RandomUtil.randomChar(4));
             return;
         }
@@ -80,10 +86,12 @@ public abstract class AbstractTreeSortService<E extends TreeSortSupportEntity<PK
                 entity.setSortIndex(0L);
             entity.setParentId(createParentIdOnExists());
             entity.setPath(RandomUtil.randomChar(4));
+            entity.setLevel(0);
         } else {
-            if (entity.getSortIndex() == null&&parent.getSortIndex()!=null)
+            if (entity.getSortIndex() == null && parent.getSortIndex() != null)
                 entity.setSortIndex(parent.getSortIndex() * 10);
             entity.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4));
+            entity.setLevel(entity.getPath().split("[-]").length);
         }
     }
 
@@ -119,13 +127,11 @@ public abstract class AbstractTreeSortService<E extends TreeSortSupportEntity<PK
         assertNotNull(entity);
         List<E> childrenList = new ArrayList<>();
         TreeSupportEntity.expandTree2List(entity, childrenList, getIDGenerator());
-//        this.saveOrUpdateForSingle(entity);
-//        childrenList.remove(entity);
         childrenList.forEach(this::saveOrUpdateForSingle);
         return childrenList.size() + 1;
     }
 
-    public PK saveOrUpdateForSingle(E entity) {
+    protected PK saveOrUpdateForSingle(E entity) {
         assertNotNull(entity);
         PK id = entity.getId();
         if (null == id || this.selectByPk(id) == null) {

+ 23 - 5
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/DefaultLogicPrimaryKeyValidator.java

@@ -28,12 +28,21 @@ public class DefaultLogicPrimaryKeyValidator implements LogicPrimaryKeyValidator
     private static final Map<Class, Map<Class, Validator>> validatorCache = new HashMap<>();
 
 
-    private static final Validator EMPTY_VALIDATOR = bean -> {
+    private static final DefaultLogicPrimaryKeyValidator instrance = new DefaultLogicPrimaryKeyValidator();
+
+    protected DefaultLogicPrimaryKeyValidator() {
+    }
+
+    public static DefaultLogicPrimaryKeyValidator getInstrance() {
+        return instrance;
+    }
+
+    private static final Validator ALWAYS_PASSED_VALIDATOR = bean -> {
         return Result.passed();
     };
 
-    public <T> void registerQuerySuppiler(Class<T> type, Function<T, Query<T, QueryParamEntity>> querySupplier) {
-        validatorCache.computeIfAbsent(type, this::createValidator)
+    public static <T> void registerQuerySuppiler(Class<T> type, Function<T, Query<T, QueryParamEntity>> querySupplier) {
+        validatorCache.computeIfAbsent(type, instrance::createValidator)
                 .values()
                 .stream()
                 .filter(DefaultValidator.class::isInstance)
@@ -50,7 +59,7 @@ public class DefaultLogicPrimaryKeyValidator implements LogicPrimaryKeyValidator
             result = Arrays.stream(groups)
                     .map(group ->
                             validatorCache.computeIfAbsent(target, this::createValidator)
-                                    .getOrDefault(group, EMPTY_VALIDATOR)
+                                    .getOrDefault(group, ALWAYS_PASSED_VALIDATOR)
                                     .doValidate(bean))
                     .filter(Result::isError)
                     .findFirst()
@@ -58,7 +67,7 @@ public class DefaultLogicPrimaryKeyValidator implements LogicPrimaryKeyValidator
 
         } else {
             result = validatorCache.computeIfAbsent(target, this::createValidator)
-                    .getOrDefault(Void.class, EMPTY_VALIDATOR)
+                    .getOrDefault(Void.class, ALWAYS_PASSED_VALIDATOR)
                     .doValidate(bean);
         }
         return result;
@@ -134,6 +143,7 @@ public class DefaultLogicPrimaryKeyValidator implements LogicPrimaryKeyValidator
                                 Collectors.mapping(Function.identity(), Collectors.toSet())
                                 , list -> DefaultValidator.builder()
                                         .infos(list)
+                                        .targetType(target)
                                         .build())
                         )
                 );
@@ -148,10 +158,18 @@ public class DefaultLogicPrimaryKeyValidator implements LogicPrimaryKeyValidator
     static class DefaultValidator<T> implements Validator<T> {
         private Set<LogicPrimaryKeyField> infos = new HashSet<>();
 
+        private Class<T> targetType;
+
         private volatile Function<T, Query<T, QueryParamEntity>> querySupplier;
 
         public Result doValidate(T bean) {
             if (querySupplier == null) {
+                log.warn("未设置查询函数," +
+                                "你可以在服务初始化的时候通过调用" +
+                                "DefaultLogicPrimaryKeyValidator" +
+                                ".registerQuerySuppiler({},bean -> this.createQuery().not(\"id\", bean.getId()))" +
+                                "进行设置"
+                        , targetType);
                 return Result.passed();
             }
 

+ 12 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/EnableCacheAllEvictTreeSortService.java

@@ -14,6 +14,18 @@ import java.util.List;
 public abstract class EnableCacheAllEvictTreeSortService<E extends TreeSortSupportEntity<PK>, PK>
         extends AbstractTreeSortService<E, PK> {
 
+    @Override
+    @Cacheable(key = "'chidlren:'+#parentId")
+    public List<E> selectChildNode(PK parentId) {
+        return super.selectChildNode(parentId);
+    }
+
+    @Override
+    @Cacheable(key = "'all-chidlren:'+#parentId")
+    public List<E> selectAllChildNode(PK parentId) {
+        return super.selectAllChildNode(parentId);
+    }
+
     @Override
     @CacheEvict(allEntries = true)
     public int updateBatch(Collection<E> data) {

+ 2 - 5
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericEntityService.java

@@ -57,14 +57,10 @@ public abstract class GenericEntityService<E extends GenericEntity<PK>, PK>
      */
     protected abstract IDGenerator<PK> getIDGenerator();
 
-    @Autowired(required = false)
-    public LogicPrimaryKeyValidator logicPrimaryKeyValidator;
-
     @PostConstruct
     public void init() {
         if (null != logicPrimaryKeyValidator && logicPrimaryKeyValidator instanceof DefaultLogicPrimaryKeyValidator) {
-            ((DefaultLogicPrimaryKeyValidator) logicPrimaryKeyValidator)
-                    .registerQuerySuppiler(getEntityInstanceType(), bean -> this.createQuery().not("id", bean.getId()));
+            DefaultLogicPrimaryKeyValidator.registerQuerySuppiler(getEntityInstanceType(), bean -> this.createQuery().not("id", bean.getId()));
         }
     }
 
@@ -80,6 +76,7 @@ public abstract class GenericEntityService<E extends GenericEntity<PK>, PK>
         Assert.notNull(entity, "entity can not be null");
         entity.setId(pk);
         tryValidate(entity, UpdateGroup.class);
+
         return createUpdate(entity)
                 //如果是RecordCreationEntity则不修改creator_id和creator_time
                 .when(entity instanceof RecordCreationEntity,

+ 4 - 4
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/DefaultLogicPrimaryKeyValidatorTest.java

@@ -19,7 +19,7 @@ public class DefaultLogicPrimaryKeyValidatorTest {
 
     @Test
     public void testSimple() {
-        validator.registerQuerySuppiler(TestBean.class, bean ->
+        DefaultLogicPrimaryKeyValidator.registerQuerySuppiler(TestBean.class, bean ->
                 Query.<TestBean, QueryParamEntity>empty(QueryParamEntity.empty())
                         .setSingleExecutor(param -> {
                             Assert.assertNotNull(param.getTerms());
@@ -34,7 +34,7 @@ public class DefaultLogicPrimaryKeyValidatorTest {
 
     @Test
     public void testClassAnn() {
-        validator.registerQuerySuppiler(ClassAnnTestBean.class, bean ->
+        DefaultLogicPrimaryKeyValidator.registerQuerySuppiler(ClassAnnTestBean.class, bean ->
                 Query.<ClassAnnTestBean, QueryParamEntity>empty(QueryParamEntity.empty())
                         .setSingleExecutor(param -> {
                             Assert.assertNotNull(param.getTerms());
@@ -49,7 +49,7 @@ public class DefaultLogicPrimaryKeyValidatorTest {
 
     @Test
     public void testGroupAnn() {
-        validator.registerQuerySuppiler(GroupAnnTestBean.class, bean ->
+        DefaultLogicPrimaryKeyValidator.registerQuerySuppiler(GroupAnnTestBean.class, bean ->
                 Query.<GroupAnnTestBean, QueryParamEntity>empty(QueryParamEntity.empty())
                         .setSingleExecutor(param -> {
                             Assert.assertNotNull(param.getTerms());
@@ -68,7 +68,7 @@ public class DefaultLogicPrimaryKeyValidatorTest {
     public void testNestProperty() {
         NestTestBean nestTestBean=new NestTestBean(new TestBean("test","1"),"test");
 
-        validator.registerQuerySuppiler(NestTestBean.class, bean ->
+        DefaultLogicPrimaryKeyValidator.registerQuerySuppiler(NestTestBean.class, bean ->
                 Query.<NestTestBean, QueryParamEntity>empty(QueryParamEntity.empty())
                         .setSingleExecutor(param -> {
                             Assert.assertNotNull(param.getTerms());

+ 6 - 5
hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/ApplicationContextHolder.java

@@ -1,14 +1,15 @@
 package org.hswebframework.web;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
 import org.springframework.stereotype.Component;
 
 /**
  * @author zhouhao
+ * @since 2.0
  */
 @Component
-public class ApplicationContextHolder {
+public class ApplicationContextHolder implements ApplicationContextAware {
     private static ApplicationContext context;
 
     public static ApplicationContext get() {
@@ -18,10 +19,10 @@ public class ApplicationContextHolder {
         return context;
     }
 
-    @Autowired
-    public void setContext(ApplicationContext context) {
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) {
         if (null == ApplicationContextHolder.context) {
-            ApplicationContextHolder.context = context;
+            ApplicationContextHolder.context = applicationContext;
         }
     }
 }

+ 7 - 7
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java

@@ -24,12 +24,12 @@ import com.alibaba.fastjson.parser.ParserConfig;
 import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
 import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
 import com.alibaba.fastjson.serializer.SerializerFeature;
+import org.hswebframework.web.ApplicationContextHolder;
 import org.hswebframework.web.ThreadLocalUtils;
 import org.hswebframework.web.bean.FastBeanCopier;
 import org.hswebframework.web.commons.entity.factory.EntityFactory;
 import org.hswebframework.web.commons.entity.factory.MapperEntityFactory;
 import org.hswebframework.web.convert.CustomMessageConverter;
-import org.hswebframework.web.dict.EnumDict;
 import org.hswebframework.web.service.DefaultLogicPrimaryKeyValidator;
 import org.hswebframework.web.starter.convert.FastJsonGenericHttpMessageConverter;
 import org.hswebframework.web.starter.convert.FastJsonHttpMessageConverter;
@@ -47,7 +47,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@@ -59,9 +58,6 @@ import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.sql.DataSource;
-import javax.validation.Validation;
-import javax.validation.Validator;
-import javax.validation.ValidatorFactory;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Type;
 import java.util.List;
@@ -70,7 +66,6 @@ import java.util.List;
  * @author zhouhao
  */
 @Configuration
-//@ComponentScan("org.hswebframework.web")
 @EnableConfigurationProperties(EntityProperties.class)
 @ImportAutoConfiguration(EntityFactoryInitConfiguration.class)
 public class HswebAutoConfiguration {
@@ -184,7 +179,7 @@ public class HswebAutoConfiguration {
     @Bean
     @ConditionalOnMissingBean(LogicPrimaryKeyValidator.class)
     public LogicPrimaryKeyValidator logicPrimaryKeyValidator() {
-        return new DefaultLogicPrimaryKeyValidator();
+        return DefaultLogicPrimaryKeyValidator.getInstrance();
     }
 
     @Bean
@@ -203,6 +198,11 @@ public class HswebAutoConfiguration {
         }
     }
 
+    @Bean
+    public ApplicationContextHolder applicationContextHolder() {
+        return new ApplicationContextHolder();
+    }
+
     @Bean
     public RestControllerExceptionTranslator restControllerExceptionTranslator() {
         return new RestControllerExceptionTranslator();

+ 1 - 1
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/README.md

@@ -4,7 +4,7 @@
 ### 获取当前用户对应的人员信息
 
 ```java
-   PersonnelAuthorization person= PersonnelAuthorization.current().orElse(null);
+   PersonnelAuthentication person= PersonnelAuthentication.current().orElse(null);
     
     //人员基本信息
    person.getPersonnel();

+ 3 - 4
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-local/src/main/java/org/hswebframework/web/service/organizational/simple/SimpleDistrictService.java

@@ -9,6 +9,7 @@ import org.hswebframework.web.entity.organizational.DistrictEntity;
 import org.hswebframework.web.entity.organizational.OrganizationalEntity;
 import org.hswebframework.web.service.AbstractTreeSortService;
 import org.hswebframework.web.service.DefaultDSLQueryService;
+import org.hswebframework.web.service.EnableCacheAllEvictTreeSortService;
 import org.hswebframework.web.service.GenericEntityService;
 import org.hswebframework.web.id.IDGenerator;
 import org.hswebframework.web.service.organizational.DistrictService;
@@ -34,7 +35,7 @@ import static org.hswebframework.web.service.DefaultDSLQueryService.*;
  */
 @Service("districtService")
 @CacheConfig(cacheNames = "district")
-public class SimpleDistrictService extends AbstractTreeSortService<DistrictEntity, String>
+public class SimpleDistrictService extends EnableCacheAllEvictTreeSortService<DistrictEntity, String>
         implements DistrictService {
     @Autowired
     private DistrictDao districtDao;
@@ -84,9 +85,7 @@ public class SimpleDistrictService extends AbstractTreeSortService<DistrictEntit
     @Override
     @CacheEvict(allEntries = true)
     public int deleteByPk(String id) {
-        if (DefaultDSLQueryService.createQuery(organizationalDao)
-                .where(OrganizationalEntity.orgId, id)
-                .total() > 0) {
+        if (DefaultDSLQueryService.createQuery(organizationalDao).where(OrganizationalEntity.districtId, id).total() > 0) {
             throw new BusinessException("行政区域下存在机构信息,无法删除!");
         }
         publisher.publishEvent(new ClearPersonCacheEvent());

+ 18 - 4
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/DistrictController.java

@@ -17,14 +17,14 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 /**
- * 表单发布日志
+ * 行政区划管理
  *
  * @author hsweb-generator-online
  */
 @RestController
 @RequestMapping("${hsweb.web.mappings.district:district}")
 @Authorize(permission = "district", description = "行政区划管理")
-@Api(value = "行政区划管理",tags = "组织架构-行政区划管理")
+@Api(value = "行政区划管理", tags = "组织架构-行政区划管理")
 public class DistrictController implements SimpleGenericEntityController<DistrictEntity, String, QueryParamEntity> {
 
     private DistrictService districtService;
@@ -46,6 +46,20 @@ public class DistrictController implements SimpleGenericEntityController<Distric
         return ResponseMessage.ok(districtService.selectByCode(code));
     }
 
+    @GetMapping("/children/{parentId}")
+    @Authorize(action = Permission.ACTION_QUERY)
+    @ApiOperation("获取子级行政区划")
+    public ResponseMessage<List<DistrictEntity>> getByParentId(@PathVariable String parentId) {
+        return ResponseMessage.ok(districtService.selectChildNode(parentId));
+    }
+
+    @GetMapping("/children/{parentId}/all")
+    @Authorize(action = Permission.ACTION_QUERY)
+    @ApiOperation("获取所有子级行政区划")
+    public ResponseMessage<List<DistrictEntity>> getAllByParentId(@PathVariable String parentId) {
+        return ResponseMessage.ok(districtService.selectAllChildNode(parentId));
+    }
+
     @GetMapping("/all")
     @Authorize(action = Permission.ACTION_QUERY)
     @ApiOperation("获取全部行政区划")
@@ -63,7 +77,7 @@ public class DistrictController implements SimpleGenericEntityController<Distric
 
     @PutMapping("/{id}/disable")
     @Authorize(action = Permission.ACTION_DISABLE)
-    @ApiOperation("禁用机构")
+    @ApiOperation("禁用行政区划")
     public ResponseMessage<Boolean> disable(@PathVariable String id) {
         districtService.disable(id);
         return ResponseMessage.ok();
@@ -71,7 +85,7 @@ public class DistrictController implements SimpleGenericEntityController<Distric
 
     @PutMapping("/{id}/enable")
     @Authorize(action = Permission.ACTION_ENABLE)
-    @ApiOperation("启用机构")
+    @ApiOperation("启用行政区划")
     public ResponseMessage<Boolean> enable(@PathVariable String id) {
         districtService.enable(id);
         return ResponseMessage.ok();