Bladeren bron

又一波重构

zhou-hao 5 jaren geleden
bovenliggende
commit
3b586cbbfd
51 gewijzigde bestanden met toevoegingen van 947 en 171 verwijderingen
  1. 1 0
      hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/FluxTestController.java
  2. 14 0
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java
  3. 1 1
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericEntity.java
  4. 1 1
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/PagerResult.java
  5. 7 0
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TransactionManagers.java
  6. 5 0
      hsweb-commons/hsweb-commons-crud/pom.xml
  7. 10 8
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java
  8. 33 45
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyOrmConfiguration.java
  9. 20 14
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java
  10. 33 0
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/JdbcSqlExecutorConfiguration.java
  11. 30 0
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/R2dbcSqlExecutorConfiguration.java
  12. 0 19
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/LogicalDeleteEntity.java
  13. 2 3
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/MD5Generator.java
  14. 2 4
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/SnowFlakeStringIdGenerator.java
  15. 6 1
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/CrudService.java
  16. 1 1
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/GenericCrudService.java
  17. 2 2
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java
  18. 1 0
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/sql/DefaultR2dbcExecutor.java
  19. 9 0
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/QueryController.java
  20. 3 1
      hsweb-commons/hsweb-commons-crud/src/main/resources/META-INF/spring.factories
  21. 5 0
      hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java
  22. 3 1
      hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java
  23. 10 0
      hsweb-core/pom.xml
  24. 6 5
      hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java
  25. 45 0
      hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java
  26. 38 0
      hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java
  27. 1 5
      hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java
  28. 0 24
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/User.java
  29. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/ActionEntity.java
  30. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java
  31. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java
  32. 0 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
  33. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
  34. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/OptionalField.java
  35. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/ParentPermission.java
  36. 0 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
  37. 16 7
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java
  38. 17 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java
  39. 15 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserCreatedEvent.java
  40. 21 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserModifiedEvent.java
  41. 0 27
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/reactive/ReactiveUserService.java
  42. 38 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/UserService.java
  43. 30 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java
  44. 45 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml
  45. 166 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java
  46. 144 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultUserService.java
  47. 60 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveUserServiceTest.java
  48. 27 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/ReactiveTestApplication.java
  49. 46 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/sync/DefaultUserServiceTest.java
  50. 21 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/sync/TestApplication.java
  51. 11 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/resources/application.yml

+ 1 - 0
hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/FluxTestController.java

@@ -13,6 +13,7 @@ public class FluxTestController {
 
     @GetMapping
     public Mono<Authentication> getUser() {
+
         return Authentication
                 .currentReactive()
                 .switchIfEmpty(Mono.error(UnAuthorizedException::new));

+ 14 - 0
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java

@@ -19,6 +19,9 @@
 package org.hswebframework.web.api.crud.entity;
 
 
+import org.hswebframework.web.bean.FastBeanCopier;
+import org.hswebframework.web.validator.ValidatorUtils;
+
 import java.io.Serializable;
 
 /**
@@ -29,5 +32,16 @@ import java.io.Serializable;
  */
 public interface Entity extends Serializable {
 
+    default void tryValidate(Class<?>... groups) {
+        ValidatorUtils.tryValidate(this, groups);
+    }
+
+    default <T> T copyTo(Class<T> target, String... ignoreProperties) {
+        return FastBeanCopier.copy(this, target, ignoreProperties);
+    }
 
+    @SuppressWarnings("all")
+    default <T> T copyFrom(Object target, String... ignoreProperties) {
+        return (T) FastBeanCopier.copy(target, this, ignoreProperties);
+    }
 }

+ 1 - 1
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericEntity.java

@@ -34,7 +34,7 @@ import javax.persistence.Id;
 @Setter
 public class GenericEntity<PK> implements Entity {
 
-    @Column(length = 32)
+    @Column(length = 32,updatable = false)
     @Id
     private PK id;
 

+ 1 - 1
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/PagerResult.java

@@ -16,7 +16,7 @@
  *
  */
 
-package org.hswebframework.web.crud.entity;
+package org.hswebframework.web.api.crud.entity;
 
 
 import lombok.Getter;

+ 7 - 0
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TransactionManagers.java

@@ -0,0 +1,7 @@
+package org.hswebframework.web.api.crud.entity;
+
+public interface TransactionManagers {
+
+    String r2dbcTransactionManager = "connectionFactoryTransactionManager";// System.getProperty("");
+
+}

+ 5 - 0
hsweb-commons/hsweb-commons-crud/pom.xml

@@ -84,6 +84,11 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aspects</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-commons-api</artifactId>

+ 10 - 8
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java

@@ -6,19 +6,20 @@ import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
+import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.ReactiveTransactionManager;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 import reactor.core.publisher.Flux;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Getter
 @Setter
 @Slf4j
-public class AutoDDLProcessor {
+public class AutoDDLProcessor implements InitializingBean {
 
     private Set<EntityInfo> entities = new HashSet<>();
 
@@ -36,7 +37,9 @@ public class AutoDDLProcessor {
 
     private boolean reactive;
 
-    public void init() {
+
+    @Override
+    public void afterPropertiesSet() {
         if(entityFactory instanceof MapperEntityFactory){
             MapperEntityFactory factory= ((MapperEntityFactory) entityFactory);
 
@@ -44,7 +47,6 @@ public class AutoDDLProcessor {
                 factory.addMapping(entity.getEntityType(),MapperEntityFactory.defaultMapper(entity.getRealType()));
             }
         }
-
         if (properties.isAutoDdl()) {
             List<Class> entities = this.entities.stream().map(EntityInfo::getRealType).collect(Collectors.toList());
             if(reactive){
@@ -64,7 +66,7 @@ public class AutoDDLProcessor {
                                 .commit()
                                 .sync();
                     } catch (Exception e) {
-                        log.error(e.getMessage(), e);
+                        log.warn(e.getMessage(), e);
                     }
                 }
             }

+ 33 - 45
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyOrmConfiguration.java

@@ -1,12 +1,10 @@
 package org.hswebframework.web.crud.configuration;
 
 
-import io.r2dbc.spi.ConnectionFactory;
 import lombok.SneakyThrows;
 import org.hswebframework.ezorm.core.meta.Feature;
 import org.hswebframework.ezorm.rdb.executor.SyncSqlExecutor;
 import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSqlExecutor;
-import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSyncSqlExecutor;
 import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping;
 import org.hswebframework.ezorm.rdb.mapping.EntityManager;
 import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType;
@@ -15,25 +13,23 @@ import org.hswebframework.ezorm.rdb.mapping.parser.EntityTableMetadataParser;
 import org.hswebframework.ezorm.rdb.metadata.RDBDatabaseMetadata;
 import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
 import org.hswebframework.ezorm.rdb.operator.DefaultDatabaseOperator;
+import org.hswebframework.web.api.crud.entity.EntityFactory;
+import org.hswebframework.web.crud.annotation.EnableEasyormRepository;
+import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
 import org.hswebframework.web.crud.generator.MD5Generator;
 import org.hswebframework.web.crud.generator.SnowFlakeStringIdGenerator;
-import org.hswebframework.web.crud.sql.DefaultJdbcExecutor;
-import org.hswebframework.web.crud.annotation.EnableEasyormRepository;
-import org.hswebframework.web.api.crud.entity.EntityFactory;
-import org.hswebframework.web.crud.sql.DefaultJdbcReactiveExecutor;
-import org.hswebframework.web.crud.sql.DefaultR2dbcExecutor;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
-import javax.sql.DataSource;
 import java.util.List;
+import java.util.Optional;
 
 @Configuration
 @EnableConfigurationProperties(EasyormProperties.class)
@@ -43,37 +39,10 @@ public class EasyOrmConfiguration {
     @Autowired
     private EasyormProperties properties;
 
-    @Configuration
-    @ConditionalOnBean(DataSource.class)
-    public static class JdbcSqlExecutorConfiguration {
-        @Bean
-        @ConditionalOnMissingBean
-        public SyncSqlExecutor syncSqlExecutor() {
-            return new DefaultJdbcExecutor();
-        }
-
-        @Bean
-        @ConditionalOnMissingBean
-        public ReactiveSqlExecutor reactiveSqlExecutor() {
-            return new DefaultJdbcReactiveExecutor();
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnClass(ConnectionFactory.class)
-    public static class R2dbcSqlExecutorConfiguration {
-        @Bean
-        @ConditionalOnMissingBean
-        public ReactiveSqlExecutor reactiveSqlExecutor() {
-            return new DefaultR2dbcExecutor();
-        }
-
-        @Bean
-        @ConditionalOnMissingBean
-        public SyncSqlExecutor syncSqlExecutor(ReactiveSqlExecutor reactiveSqlExecutor) {
-            return ReactiveSyncSqlExecutor.of(reactiveSqlExecutor);
-        }
+    @Bean
+    @ConditionalOnMissingBean
+    public EntityFactory entityFactory(){
+        return new MapperEntityFactory();
     }
 
     @Bean
@@ -121,17 +90,36 @@ public class EasyOrmConfiguration {
 
     @Bean
     @ConditionalOnMissingBean
-    public RDBDatabaseMetadata databaseMetadata(){
-        return properties.createDatabaseMetadata();
+    @SuppressWarnings("all")
+    public RDBDatabaseMetadata databaseMetadata(Optional<SyncSqlExecutor> syncSqlExecutor,
+                                                Optional<ReactiveSqlExecutor> reactiveSqlExecutor) {
+        RDBDatabaseMetadata metadata = properties.createDatabaseMetadata();
+        syncSqlExecutor.ifPresent(metadata::addFeature);
+        reactiveSqlExecutor.ifPresent(metadata::addFeature);
+
+        return metadata;
     }
 
     @Bean
     @ConditionalOnMissingBean
-    public DatabaseOperator databaseOperator(RDBDatabaseMetadata metadata, List<Feature> features) {
-        features.forEach(metadata::addFeature);
+    public DatabaseOperator databaseOperator(RDBDatabaseMetadata metadata) {
+
         return DefaultDatabaseOperator.of(metadata);
     }
 
+    @Bean
+    public BeanPostProcessor autoRegisterFeature(RDBDatabaseMetadata metadata) {
+        return new BeanPostProcessor() {
+            @Override
+            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+                if (bean instanceof Feature) {
+                    metadata.addFeature(((Feature) bean));
+                }
+                return bean;
+            }
+        };
+    }
+
     @Bean
     public MD5Generator md5Generator(){
         return new MD5Generator();

+ 20 - 14
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java

@@ -44,6 +44,13 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
         Map<String, Object> attr = importingClassMetadata.getAnnotationAttributes(EnableEasyormRepository.class.getName());
         if (attr == null) {
             return;
+        }
+        boolean reactivePrecent = false;
+        try {
+            Class.forName("io.r2dbc.spi.ConnectionFactory");
+            reactivePrecent = true;
+        } catch (Exception e) {
+
         }
         String[] arr = (String[]) attr.get("value");
         String path = Arrays.stream(arr)
@@ -94,19 +101,19 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
                 idType = implementFor.idType();
             }
 
-            EntityInfo entityInfo = new EntityInfo(genericType, entityType, idType, reactive == null || reactive.enable());
+            EntityInfo entityInfo = new EntityInfo(genericType, entityType, idType, reactivePrecent && (reactive == null || reactive.enable()));
             if (!entityInfos.contains(entityInfo) || implementFor != null) {
                 entityInfos.add(entityInfo);
             }
 
         }
-        boolean reactive=false;
+        boolean reactive = false;
         for (EntityInfo entityInfo : entityInfos) {
             Class entityType = entityInfo.getEntityType();
             Class idType = entityInfo.getIdType();
             Class realType = entityInfo.getRealType();
             if (entityInfo.isReactive()) {
-                reactive=true;
+                reactive = true;
                 log.debug("register ReactiveRepository<{},{}>", entityType.getName(), idType.getSimpleName());
 
                 ResolvableType repositoryType = ResolvableType.forClassWithGenerics(DefaultReactiveRepository.class, entityType, idType);
@@ -117,18 +124,18 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
                 definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
                 definition.getPropertyValues().add("entityType", realType);
                 registry.registerBeanDefinition(realType.getSimpleName().concat("ReactiveRepository"), definition);
-            } else {
-                log.debug("register SyncRepository<{},{}>", entityType.getName(), idType.getSimpleName());
+            }
 
-                ResolvableType repositoryType = ResolvableType.forClassWithGenerics(DefaultSyncRepository.class, entityType, idType);
+            log.debug("register SyncRepository<{},{}>", entityType.getName(), idType.getSimpleName());
 
-                RootBeanDefinition definition = new RootBeanDefinition();
-                definition.setTargetType(repositoryType);
-                definition.setBeanClass(SyncRepositoryFactoryBean.class);
-                definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
-                definition.getPropertyValues().add("entityType", realType);
-                registry.registerBeanDefinition(realType.getSimpleName().concat("SyncRepository"), definition);
-            }
+            ResolvableType repositoryType = ResolvableType.forClassWithGenerics(DefaultSyncRepository.class, entityType, idType);
+
+            RootBeanDefinition definition = new RootBeanDefinition();
+            definition.setTargetType(repositoryType);
+            definition.setBeanClass(SyncRepositoryFactoryBean.class);
+            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
+            definition.getPropertyValues().add("entityType", realType);
+            registry.registerBeanDefinition(realType.getSimpleName().concat("SyncRepository"), definition);
         }
 
         RootBeanDefinition definition = new RootBeanDefinition();
@@ -137,7 +144,6 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
         definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
         definition.getPropertyValues().add("entities", entityInfos);
         definition.getPropertyValues().add("reactive", reactive);
-        definition.setInitMethodName("init");
         registry.registerBeanDefinition(AutoDDLProcessor.class.getName(), definition);
 
     }

+ 33 - 0
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/JdbcSqlExecutorConfiguration.java

@@ -0,0 +1,33 @@
+package org.hswebframework.web.crud.configuration;
+
+import org.hswebframework.ezorm.rdb.executor.SyncSqlExecutor;
+import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSqlExecutor;
+import org.hswebframework.web.crud.sql.DefaultJdbcExecutor;
+import org.hswebframework.web.crud.sql.DefaultJdbcReactiveExecutor;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+@AutoConfigureAfter(DataSourceAutoConfiguration.class)
+@ConditionalOnBean(DataSource.class)
+public class JdbcSqlExecutorConfiguration {
+    @Bean
+    @ConditionalOnMissingBean
+    public SyncSqlExecutor syncSqlExecutor() {
+        return new DefaultJdbcExecutor();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public ReactiveSqlExecutor reactiveSqlExecutor() {
+        return new DefaultJdbcReactiveExecutor();
+    }
+
+}

+ 30 - 0
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/R2dbcSqlExecutorConfiguration.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.crud.configuration;
+
+import io.r2dbc.spi.ConnectionFactory;
+import org.hswebframework.ezorm.rdb.executor.SyncSqlExecutor;
+import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSqlExecutor;
+import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSyncSqlExecutor;
+import org.hswebframework.web.crud.sql.DefaultR2dbcExecutor;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@AutoConfigureAfter(name = "org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryAutoConfiguration")
+@ConditionalOnBean(ConnectionFactory.class)
+public class R2dbcSqlExecutorConfiguration {
+    @Bean
+    @ConditionalOnMissingBean
+    public ReactiveSqlExecutor reactiveSqlExecutor() {
+        return new DefaultR2dbcExecutor();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public SyncSqlExecutor syncSqlExecutor(ReactiveSqlExecutor reactiveSqlExecutor) {
+        return ReactiveSyncSqlExecutor.of(reactiveSqlExecutor);
+    }
+}

+ 0 - 19
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/LogicalDeleteEntity.java

@@ -1,19 +0,0 @@
-package org.hswebframework.web.crud.entity;
-
-/**
- * 逻辑删除
- *
- * @author zhouhao
- * @since 3.0.6
- */
-public interface LogicalDeleteEntity {
-
-    Boolean getDeleted();
-
-    void setDeleted(boolean deleted);
-
-    Long getDeleteTime();
-
-    void setDeleteTime(Long deleteTime);
-
-}

+ 2 - 3
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/MD5Generator.java

@@ -1,6 +1,5 @@
 package org.hswebframework.web.crud.generator;
 
-import org.hswebframework.ezorm.core.DefaultValue;
 import org.hswebframework.ezorm.core.DefaultValueGenerator;
 import org.hswebframework.ezorm.core.RuntimeDefaultValue;
 import org.hswebframework.web.id.IDGenerator;
@@ -12,8 +11,8 @@ public class MD5Generator implements DefaultValueGenerator {
     }
 
     @Override
-    public DefaultValue generate() {
-        return (RuntimeDefaultValue) IDGenerator.MD5::generate;
+    public RuntimeDefaultValue generate() {
+        return IDGenerator.MD5::generate;
     }
 
     @Override

+ 2 - 4
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/SnowFlakeStringIdGenerator.java

@@ -1,10 +1,8 @@
 package org.hswebframework.web.crud.generator;
 
-import org.hswebframework.ezorm.core.DefaultValue;
 import org.hswebframework.ezorm.core.DefaultValueGenerator;
 import org.hswebframework.ezorm.core.RuntimeDefaultValue;
 import org.hswebframework.web.id.IDGenerator;
-import org.springframework.stereotype.Component;
 
 public class SnowFlakeStringIdGenerator implements DefaultValueGenerator {
     @Override
@@ -13,8 +11,8 @@ public class SnowFlakeStringIdGenerator implements DefaultValueGenerator {
     }
 
     @Override
-    public DefaultValue generate() {
-        return (RuntimeDefaultValue) IDGenerator.SNOW_FLAKE_STRING::generate;
+    public RuntimeDefaultValue generate() {
+        return IDGenerator.SNOW_FLAKE_STRING::generate;
     }
 
     @Override

+ 6 - 1
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/CrudService.java

@@ -1,15 +1,17 @@
 package org.hswebframework.web.crud.service;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.hswebframework.ezorm.core.param.QueryParam;
 import org.hswebframework.ezorm.rdb.mapping.SyncDelete;
 import org.hswebframework.ezorm.rdb.mapping.SyncQuery;
 import org.hswebframework.ezorm.rdb.mapping.SyncRepository;
 import org.hswebframework.ezorm.rdb.mapping.SyncUpdate;
 import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
-import org.hswebframework.web.crud.entity.PagerResult;
+import org.hswebframework.web.api.crud.entity.PagerResult;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -36,6 +38,9 @@ public interface CrudService<E, K> {
 
     @Transactional(readOnly = true)
     default List<E> findById(Collection<K> id) {
+        if (CollectionUtils.isEmpty(id)) {
+            return Collections.emptyList();
+        }
         return getRepository()
                 .findById(id);
     }

+ 1 - 1
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/GenericCrudService.java

@@ -3,7 +3,7 @@ package org.hswebframework.web.crud.service;
 import org.hswebframework.ezorm.rdb.mapping.SyncRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 
-public class GenericCrudService<E,K> implements CrudService<E,K> {
+public abstract class GenericCrudService<E,K> implements CrudService<E,K> {
 
     @Autowired
     private SyncRepository<E, K> repository;

+ 2 - 2
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java

@@ -6,9 +6,9 @@ import org.hswebframework.ezorm.rdb.mapping.ReactiveQuery;
 import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
 import org.hswebframework.ezorm.rdb.mapping.ReactiveUpdate;
 import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
-import org.hswebframework.web.crud.entity.PagerResult;
-import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.api.crud.entity.PagerResult;
 import org.reactivestreams.Publisher;
+import org.springframework.transaction.ReactiveTransactionManager;
 import org.springframework.transaction.annotation.Transactional;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;

+ 1 - 0
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/sql/DefaultR2dbcExecutor.java

@@ -10,6 +10,7 @@ import org.hswebframework.web.datasource.R2dbcDataSource;
 import org.reactivestreams.Publisher;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.r2dbc.connectionfactory.ConnectionFactoryUtils;
+import org.springframework.transaction.NoTransactionException;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import reactor.core.publisher.Flux;

+ 9 - 0
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/QueryController.java

@@ -0,0 +1,9 @@
+package org.hswebframework.web.crud.web;
+
+import org.hswebframework.web.crud.service.CrudService;
+
+public interface QueryController<E,K> {
+
+    CrudService<E,K> getService();
+
+}

+ 3 - 1
hsweb-commons/hsweb-commons-crud/src/main/resources/META-INF/spring.factories

@@ -1,3 +1,5 @@
 # Auto Configure
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.hswebframework.web.crud.configuration.EasyOrmConfiguration
+org.hswebframework.web.crud.configuration.EasyOrmConfiguration,\
+org.hswebframework.web.crud.configuration.JdbcSqlExecutorConfiguration,\
+org.hswebframework.web.crud.configuration.R2dbcSqlExecutorConfiguration

+ 5 - 0
hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java

@@ -18,9 +18,14 @@ public class CrudTests  {
     @Autowired
     private TestEntityService service;
 
+    @Autowired
+    private TestEntityService service2;
+
     @Test
     public void test(){
+
         TestEntity entity = TestEntity.of("test",100);
+
         Mono.just(entity)
                 .as(service::insert)
                 .as(StepVerifier::create)

+ 3 - 1
hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java

@@ -3,10 +3,12 @@ package org.hswebframework.web.crud;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
 import org.hswebframework.web.crud.entity.factory.MapperEntityFactory;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
 
-@SpringBootApplication
+@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
 @Configuration
 public class TestApplication {
 

+ 10 - 0
hsweb-core/pom.xml

@@ -74,6 +74,16 @@
             <version>${hsweb.expands.version}</version>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aspects</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish</groupId>
+            <artifactId>javax.el</artifactId>
+            <version>3.0.0</version>
+        </dependency>
 
     </dependencies>
 </project>

+ 6 - 5
hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java

@@ -36,7 +36,8 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
 
     private Map<String, BiFunction<Object, ConvertConfig, Object>> converts;
 
-    private Function<Object, String> coverStringConvert = (o) -> coverString(String.valueOf(o), 50);
+    private Function<Object, String> coverStringConvert = (o) -> coverString(String.valueOf(o), 80);
+
 
     private Function<Class, BiFunction<Object, ConvertConfig, Object>> simpleConvertBuilder = type -> {
         if (Date.class.isAssignableFrom(type)) {
@@ -46,7 +47,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
         }
     };
 
-    Predicate<Class> simpleTypePredicate = ((Predicate<Class>) String.class::isAssignableFrom)
+    private Predicate<Class> simpleTypePredicate = ((Predicate<Class>) String.class::isAssignableFrom)
             .or(Class::isEnum)
             .or(Class::isPrimitive)
             .or(Date.class::isAssignableFrom)
@@ -115,7 +116,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
             try {
                 Field field = ReflectionUtils.findField(targetType, descriptor.getName());
                 if (null == field) {
-                    log.warn("无法获取字段{},该字段将不会被打码!", descriptor.getName());
+                    log.debug("无法获取字段{},该字段将不会被打码!", descriptor.getName());
                 }
                 propertyIgnore = field.getAnnotation(ToString.Ignore.class);
                 features = AnnotationUtils.getAnnotation(field, ToString.Features.class);
@@ -128,7 +129,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
                     propertyFeature = ToString.Feature.createFeatures(features.value());
                 }
             } catch (Exception e) {
-                log.warn("无法获取字段{},该字段将不会被打码!", descriptor.getName());
+                log.debug("无法获取字段{},该字段将不会被打码!", descriptor.getName());
             }
             //是否设置了打码
             boolean cover = (propertyIgnore == null && defaultCover) || (propertyIgnore != null && propertyIgnore.cover());
@@ -232,7 +233,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
     }
 
     class ConvertConfig {
-        long        features;
+        long features;
         Set<String> ignoreProperty;
 
     }

+ 45 - 0
hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java

@@ -0,0 +1,45 @@
+package org.hswebframework.web.exception;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.ConstraintViolation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@Getter
+@Setter
+public class ValidationException extends BusinessException {
+
+    private List<Detail> details;
+
+    public ValidationException(String message) {
+        super(message);
+    }
+
+    public ValidationException(String message, List<Detail> details) {
+        super(message);
+        this.details = details;
+    }
+
+    public ValidationException(String message, Set<? extends ConstraintViolation> violations) {
+        super(message);
+        if (null != violations && !violations.isEmpty()) {
+            details = new ArrayList<>();
+            for (ConstraintViolation<?> violation : violations) {
+                details.add(new Detail(violation.getPropertyPath().toString(), violation.getMessage()));
+            }
+        }
+    }
+
+    @Getter
+    @Setter
+    @AllArgsConstructor
+    public static class Detail {
+        String property;
+
+        String message;
+    }
+}

+ 38 - 0
hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java

@@ -0,0 +1,38 @@
+package org.hswebframework.web.validator;
+
+import org.hswebframework.web.exception.ValidationException;
+
+import javax.el.ExpressionFactory;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import java.util.Set;
+
+public final class ValidatorUtils {
+
+    private ValidatorUtils() {
+    }
+
+    static volatile Validator validator;
+
+    public static Validator getValidator() {
+        if (validator == null) {
+            synchronized (ValidatorUtils.class) {
+                ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+                return validator = factory.getValidator();
+            }
+        }
+        return validator;
+    }
+
+    public static <T> T tryValidate(T bean, Class... group) {
+        Set<ConstraintViolation<T>> violations = getValidator().validate(bean, group);
+        if (!violations.isEmpty()) {
+            throw new ValidationException(violations.iterator().next().getMessage(), violations);
+        }
+
+        return bean;
+    }
+
+}

+ 1 - 5
hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java

@@ -10,9 +10,5 @@ import org.springframework.context.annotation.Configuration;
 public class HswebAutoConfiguration  {
 
 
-    @Bean
-    @ConditionalOnMissingBean
-    public EntityFactory entityFactory(){
-        return new MapperEntityFactory();
-    }
+
 }

+ 0 - 24
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/User.java

@@ -1,24 +0,0 @@
-package org.hswebframework.web.system.authorization.api;
-
-
-
-import lombok.Getter;
-import lombok.Setter;
-
-import java.io.Serializable;
-
-
-@Getter
-@Setter
-public class User implements Serializable {
-
-    private String id;
-
-    private String username;
-
-    private String type;
-
-    private Byte status;
-
-
-}

hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/ActionEntity.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/ActionEntity.java


hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java


hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DataAccessEntity.java


+ 0 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java

@@ -17,7 +17,6 @@ import java.util.Map;
 @Getter
 @Setter
 @Table(name = "s_dimension",indexes = {
-        @Index(name = "idx_dims_ass_id",columnList = "association_relation,association_id"),
         @Index(name = "idx_dims_path",columnList = "path")
 })
 public class DimensionEntity extends GenericTreeSortSupportEntity<String> {

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java

@@ -48,7 +48,7 @@ public class DimensionUserEntity extends GenericEntity<String> {
     private String relationName;
 
     @Column(name = "features")
-    @ColumnType(jdbcType = JDBCType.NUMERIC)
+    @ColumnType(jdbcType = JDBCType.NUMERIC, javaType = Long.class)
     @EnumCodec(toMask = true)
     private DimensionUserFeature[] features;
 

hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/OptionalField.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/OptionalField.java


hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/ParentPermission.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/ParentPermission.java


hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java → hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java


+ 16 - 7
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java

@@ -1,39 +1,43 @@
 package org.hswebframework.web.system.authorization.api.entity;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Getter;
 import lombok.Setter;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
 import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
 import org.hswebframework.web.bean.ToString;
+import org.hswebframework.web.validator.CreateGroup;
 
 import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
 import javax.persistence.Index;
 import javax.persistence.Table;
 import javax.validation.constraints.NotBlank;
 
 @Getter
 @Setter
-@Table(name = "s_user", indexes =
-@Index(name = "user_username_idx", columnList = "username", unique = true)
+@Table(name = "s_user",
+        indexes = @Index(name = "user_username_idx", columnList = "username", unique = true)
 )
-public class UserEntity  extends GenericEntity<String> implements RecordCreationEntity {
+public class UserEntity extends GenericEntity<String> implements RecordCreationEntity {
 
     @Column(length = 128, nullable = false)
-    @NotBlank(message = "姓名不能为空")
+    @NotBlank(message = "姓名不能为空", groups = CreateGroup.class)
     private String name;
 
     @Column(length = 128, nullable = false, updatable = false)
+    @NotBlank(message = "用户名不能为空", groups = CreateGroup.class)
     private String username;
 
     @Column(nullable = false)
     @ToString.Ignore(cover = false)
-    @JsonIgnore
+    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+    @NotBlank(message = "密码不能为空", groups = CreateGroup.class)
     private String password;
 
     @Column(nullable = false)
     @ToString.Ignore(cover = false)
-    @JsonIgnore
+    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
     private String salt;
 
     @Column
@@ -48,4 +52,9 @@ public class UserEntity  extends GenericEntity<String> implements RecordCreation
     @Column(name = "create_time", updatable = false)
     private Long createTime;
 
+    @Override
+    @GeneratedValue(generator = "md5")
+    public String getId() {
+        return super.getId();
+    }
 }

+ 17 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.system.authorization.api.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author zhouhao
+ * @see org.springframework.context.event.EventListener
+ * @since 3.0.0-RC
+ */
+@AllArgsConstructor
+@Getter
+public class ClearUserAuthorizationCacheEvent {
+    private String userId;
+
+    private boolean all;
+}

+ 15 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserCreatedEvent.java

@@ -0,0 +1,15 @@
+package org.hswebframework.web.system.authorization.api.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+
+/**
+ * @author zhouhao
+ * @since 3.0.4
+ */
+@Getter
+@AllArgsConstructor
+public class UserCreatedEvent {
+    UserEntity userEntity;
+}

+ 21 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserModifiedEvent.java

@@ -0,0 +1,21 @@
+package org.hswebframework.web.system.authorization.api.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+
+/**
+ * 用户密码发生修改时事件
+ *
+ * @author zhouhao
+ * @see org.springframework.context.event.EventListener
+ * @see org.springframework.context.ApplicationEventPublisher
+ * @since 3.0
+ */
+@AllArgsConstructor
+@Getter
+public class UserModifiedEvent {
+    private UserEntity userEntity;
+
+    private boolean passwordModified;
+}

+ 0 - 27
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/reactive/ReactiveUserService.java

@@ -1,27 +0,0 @@
-package org.hswebframework.web.system.authorization.api.reactive;
-
-import org.hswebframework.ezorm.core.param.QueryParam;
-import org.hswebframework.web.system.authorization.api.User;
-import org.hswebframework.web.system.authorization.api.request.SaveUserRequest;
-import org.reactivestreams.Publisher;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-
-public interface ReactiveUserService {
-
-    Flux<User> save(Publisher<SaveUserRequest> userEntity);
-
-    Mono<User> getByUsername(String username);
-
-    Mono<User> getByUsernameAndPassword(String username, String plainPassword);
-
-    Mono<Integer> changeState(Publisher<String> userId, byte state);
-
-    Mono<Boolean> updatePassword(String userId, String oldPassword, String newPassword);
-
-    Flux<User> findUser(QueryParam queryParam);
-
-    Mono<Long> countUser(QueryParam queryParam);
-
-}

+ 38 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/UserService.java

@@ -0,0 +1,38 @@
+package org.hswebframework.web.system.authorization.api.service;
+
+import org.hswebframework.ezorm.core.param.QueryParam;
+import org.hswebframework.web.api.crud.entity.PagerResult;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+
+public interface UserService {
+
+    boolean saveUser(UserEntity userEntity);
+
+    Optional<UserEntity> findByUsername(@NotEmpty String username);
+
+    Optional<UserEntity> findByUsernameAndPassword(@NotEmpty String username, @NotEmpty String plainPassword);
+
+    Optional<UserEntity> findById(String id);
+
+    List<UserEntity> findById(Collection<String> ids);
+
+    boolean changeState(String userId, byte state);
+
+    void changePassword(String userId, String oldPassword, String newPassword);
+
+    List<UserEntity> findUser(QueryParam queryParam);
+
+    long countUser(QueryParam queryParam);
+
+    PagerResult<UserEntity> findUserPager(QueryParam param);
+}

+ 30 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.system.authorization.api.service.reactive;
+
+import org.hswebframework.ezorm.core.param.QueryParam;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+
+public interface ReactiveUserService {
+
+    Mono<UserEntity> newUserInstance();
+
+    Mono<Boolean> saveUser(Mono<UserEntity> userEntity);
+
+    Mono<UserEntity> findByUsername(String username);
+
+    Mono<UserEntity> findById(String id);
+
+    Mono<UserEntity> findByUsernameAndPassword(String username, String plainPassword);
+
+    Mono<Integer> changeState(Publisher<String> userId, byte state);
+
+    Mono<Boolean> changePassword(String userId, String oldPassword, String newPassword);
+
+    Flux<UserEntity> findUser(QueryParam queryParam);
+
+    Mono<Integer> countUser(QueryParam queryParam);
+
+}

+ 45 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml

@@ -12,6 +12,7 @@
     <artifactId>hsweb-system-authorization-default</artifactId>
 
     <dependencies>
+
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-system-authorization-api</artifactId>
@@ -23,6 +24,50 @@
             <artifactId>hsweb-commons-crud</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot.experimental</groupId>
+            <artifactId>spring-boot-starter-data-r2dbc</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+            <version>3.4.1</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.r2dbc</groupId>
+            <artifactId>r2dbc-h2</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 166 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java

@@ -0,0 +1,166 @@
+package org.hswebframework.web.system.authorization.defaults.service;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.hswebframework.ezorm.core.param.QueryParam;
+import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
+import org.hswebframework.web.api.crud.entity.TransactionManagers;
+import org.hswebframework.web.crud.service.GenericReactiveCrudService;
+import org.hswebframework.web.exception.NotFoundException;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.system.authorization.api.PasswordEncoder;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.hswebframework.web.system.authorization.api.event.UserCreatedEvent;
+import org.hswebframework.web.system.authorization.api.event.UserModifiedEvent;
+import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService;
+import org.hswebframework.web.validator.CreateGroup;
+import org.reactivestreams.Publisher;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.validation.ValidationException;
+
+
+public class DefaultReactiveUserService extends GenericReactiveCrudService<UserEntity, String> implements ReactiveUserService {
+
+    @Autowired
+    private ReactiveRepository<UserEntity, String> repository;
+
+    @Autowired(required = false)
+    private PasswordEncoder passwordEncoder = (password, salt) -> DigestUtils.md5Hex(String.format("hsweb.%s.framework.%s", password, salt));
+
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+
+    @Override
+    public Mono<UserEntity> newUserInstance() {
+        return getRepository().newInstance();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class, transactionManager = TransactionManagers.r2dbcTransactionManager)
+    public Mono<Boolean> saveUser(Mono<UserEntity> request) {
+        return request
+                .flatMap(userEntity -> {
+                    if (StringUtils.isEmpty(userEntity.getId())) {
+                        return doAdd(userEntity);
+                    }
+                    return findById(userEntity.getId())
+                            .flatMap(ignore -> doUpdate(userEntity))
+                            .switchIfEmpty(doAdd(userEntity));
+                }).thenReturn(true);
+    }
+
+    protected Mono<UserEntity> doAdd(UserEntity userEntity) {
+
+        return Mono.defer(() -> {
+            userEntity.setSalt(IDGenerator.RANDOM.generate());
+            userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword(), userEntity.getSalt()));
+            return Mono.just(userEntity)
+                    .doOnNext(e -> e.tryValidate(CreateGroup.class))
+                    .filterWhen(e -> createQuery()
+                            .where(userEntity::getUsername)
+                            .count().map(i -> i == 0))
+                    .switchIfEmpty(Mono.error(() -> new ValidationException("用户名已存在")))
+                    .as(getRepository()::insert)
+                    .thenReturn(userEntity)
+                    .doOnSuccess(e -> eventPublisher.publishEvent(new UserCreatedEvent(e)));
+        });
+
+    }
+
+
+    protected Mono<UserEntity> doUpdate(UserEntity userEntity) {
+        return Mono.defer(() -> {
+            boolean passwordChanged = StringUtils.hasText(userEntity.getPassword());
+            if (passwordChanged) {
+                userEntity.setSalt(IDGenerator.RANDOM.generate());
+                userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword(), userEntity.getSalt()));
+            }
+            return getRepository()
+                    .createUpdate()
+                    .set(userEntity)
+                    .where(userEntity::getId)
+                    .execute()
+                    .doOnSuccess(__ -> eventPublisher.publishEvent(new UserModifiedEvent(userEntity, passwordChanged)))
+                    .thenReturn(userEntity);
+        });
+
+    }
+
+
+    @Override
+    @Transactional(readOnly = true, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<UserEntity> findById(String id) {
+        return getRepository().findById(Mono.just(id));
+    }
+
+    @Override
+    @Transactional(readOnly = true, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<UserEntity> findByUsername(String username) {
+        return Mono.justOrEmpty(username)
+                .flatMap(_name -> repository.createQuery()
+                        .where(UserEntity::getUsername, _name)
+                        .fetchOne());
+    }
+
+    @Override
+    @Transactional(readOnly = true, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<UserEntity> findByUsernameAndPassword(String username, String plainPassword) {
+        return Mono.justOrEmpty(username)
+                .flatMap(_name -> repository
+                        .createQuery()
+                        .where(UserEntity::getUsername, _name)
+                        .fetchOne())
+                .filter(user -> passwordEncoder.encode(plainPassword, user.getSalt())
+                        .equals(user.getPassword()));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<Integer> changeState(Publisher<String> userId, byte state) {
+        return Flux.from(userId)
+                .collectList()
+                .flatMap(list -> repository
+                        .createUpdate()
+                        .set(UserEntity::getStatus, state)
+                        .where()
+                        .in(UserEntity::getId, list)
+                        .execute());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<Boolean> changePassword(String userId, String oldPassword, String newPassword) {
+        return findById(userId)
+                .switchIfEmpty(Mono.error(NotFoundException::new))
+                .filter(user -> passwordEncoder.encode(oldPassword, user.getSalt()).equals(user.getPassword()))
+                .switchIfEmpty(Mono.error(() -> new ValidationException("密码错误")))
+                .flatMap(user -> repository.createUpdate()
+                        .set(UserEntity::getPassword, passwordEncoder.encode(newPassword, user.getSalt()))
+                        .where(user::getId)
+                        .execute())
+                .map(i -> i > 0);
+    }
+
+    @Override
+    @Transactional(readOnly = true, transactionManager = "connectionFactoryTransactionManager")
+    public Flux<UserEntity> findUser(QueryParam queryParam) {
+        return repository
+                .createQuery()
+                .setParam(queryParam)
+                .fetch();
+    }
+
+    @Override
+    @Transactional(readOnly = true, transactionManager = "connectionFactoryTransactionManager")
+    public Mono<Integer> countUser(QueryParam queryParam) {
+        return repository
+                .createQuery()
+                .setParam(queryParam)
+                .count();
+    }
+}

+ 144 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultUserService.java

@@ -0,0 +1,144 @@
+package org.hswebframework.web.system.authorization.defaults.service;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.hswebframework.ezorm.core.param.QueryParam;
+import org.hswebframework.web.api.crud.entity.PagerResult;
+import org.hswebframework.web.crud.service.GenericCrudService;
+import org.hswebframework.web.exception.NotFoundException;
+import org.hswebframework.web.id.IDGenerator;
+import org.hswebframework.web.system.authorization.api.PasswordEncoder;
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.hswebframework.web.system.authorization.api.event.UserCreatedEvent;
+import org.hswebframework.web.system.authorization.api.event.UserModifiedEvent;
+import org.hswebframework.web.system.authorization.api.service.UserService;
+import org.hswebframework.web.validator.CreateGroup;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import reactor.core.publisher.Mono;
+
+import javax.validation.ValidationException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+@Transactional(rollbackFor = Exception.class)
+public class DefaultUserService extends GenericCrudService<UserEntity, String> implements UserService {
+
+    @Autowired(required = false)
+    private PasswordEncoder passwordEncoder = (password, salt) -> DigestUtils.md5Hex(String.format("hsweb.%s.framework.%s", password, salt));
+
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+
+    @Override
+    public boolean saveUser(UserEntity userEntity) {
+        if (StringUtils.isEmpty(userEntity.getId())) {
+            return doAdd(userEntity);
+        }
+        UserEntity old = findById(userEntity.getId()).orElse(null);
+        if (old == null) {
+            return doAdd(userEntity);
+        }
+
+        return doUpdate(userEntity);
+    }
+
+    protected boolean doAdd(UserEntity userEntity) {
+        userEntity.tryValidate(CreateGroup.class);
+        userEntity.setStatus((byte)1);
+
+        userEntity.setSalt(IDGenerator.RANDOM.generate());
+        userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword(), userEntity.getSalt()));
+        if (createQuery()
+                .where(userEntity::getUsername)
+                .count() > 0) {
+            throw new ValidationException("用户名已存在");
+        }
+        getRepository().insert(userEntity);
+        eventPublisher.publishEvent(new UserCreatedEvent(userEntity));
+        return true;
+    }
+
+
+    protected boolean doUpdate(UserEntity userEntity) {
+        boolean passwordChanged = StringUtils.hasText(userEntity.getPassword());
+        if (passwordChanged) {
+            userEntity.setSalt(IDGenerator.RANDOM.generate());
+            userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword(), userEntity.getSalt()));
+        }
+        getRepository()
+                .createUpdate()
+                .set(userEntity)
+                .where(userEntity::getId)
+                .execute();
+
+        eventPublisher.publishEvent(new UserModifiedEvent(userEntity, passwordChanged));
+        return true;
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public List<UserEntity> findById(Collection<String> id) {
+        return super.findById(id);
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public Optional<UserEntity> findById(String id) {
+        return super.findById(id);
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public Optional<UserEntity> findByUsername(String username) {
+        return createQuery()
+                .where(UserEntity::getUsername, username)
+                .fetchOne();
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public Optional<UserEntity> findByUsernameAndPassword(String username, String plainPassword) {
+        return findByUsername(username)
+                .filter(user -> passwordEncoder.encode(plainPassword, user.getSalt()).equals(user.getPassword()));
+    }
+
+    @Override
+    public boolean changeState(String userId, byte state) {
+        return createUpdate()
+                .where(UserEntity::getId, userId)
+                .set(UserEntity::getStatus, state)
+                .execute() > 0;
+    }
+
+    @Override
+    public void changePassword(String userId, String oldPassword, String newPassword) {
+        Mono.justOrEmpty(findById(userId))
+                .switchIfEmpty(Mono.error(NotFoundException::new))
+                .filter(user -> passwordEncoder.encode(oldPassword, user.getSalt()).equals(user.getPassword()))
+                .switchIfEmpty(Mono.error(() -> new ValidationException("密码错误")))
+                .map(user -> createUpdate()
+                        .set(UserEntity::getPassword, passwordEncoder.encode(newPassword, user.getSalt()))
+                        .where(user::getId).execute())
+                .block();
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public List<UserEntity> findUser(QueryParam queryParam) {
+        return createQuery().setParam(queryParam).fetch();
+    }
+
+    @Override
+    @Transactional(readOnly = true)
+    public long countUser(QueryParam queryParam) {
+        return createQuery().setParam(queryParam).count();
+    }
+
+    @Override
+    public PagerResult<UserEntity> findUserPager(QueryParam param) {
+        return queryPager(param);
+    }
+}

+ 60 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveUserServiceTest.java

@@ -0,0 +1,60 @@
+package org.hswebframework.web.system.authorization.defaults.service.reactive;
+
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ReactiveTestApplication.class)
+public class DefaultReactiveUserServiceTest {
+
+    @Autowired
+    private ReactiveUserService userService;
+
+    @Test
+    public void testCrud() {
+        UserEntity userEntity = userService.newUserInstance().blockOptional().orElseThrow(NullPointerException::new);
+        userEntity.setName("test");
+        userEntity.setUsername("admin");
+        userEntity.setPassword("admin");
+
+        userService.saveUser(Mono.just(userEntity))
+                .as(StepVerifier::create)
+                .expectNext(true)
+                .verifyComplete();
+
+        Assert.assertNotNull(userEntity.getId());
+
+        userEntity.setUsername("admin2");
+        userEntity.setPassword("admin2");
+        userService.saveUser(Mono.just(userEntity))
+                .as(StepVerifier::create)
+                .expectNext(true)
+                .verifyComplete();
+
+        userService.changeState(Mono.just(userEntity.getId()), (byte) 1)
+                .as(StepVerifier::create)
+                .expectNext(1)
+                .verifyComplete();
+
+        userService.changePassword(userEntity.getId(), "admin2", "admin")
+                .as(StepVerifier::create)
+                .expectNext(true)
+                .verifyComplete();
+
+         userService.findByUsernameAndPassword("admin", "admin")
+                .as(StepVerifier::create)
+                 .expectNextCount(1)
+                .verifyComplete();
+
+
+    }
+
+}

+ 27 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/ReactiveTestApplication.java

@@ -0,0 +1,27 @@
+package org.hswebframework.web.system.authorization.defaults.service.reactive;
+
+import org.hswebframework.web.crud.configuration.JdbcSqlExecutorConfiguration;
+import org.hswebframework.web.system.authorization.defaults.service.DefaultReactiveUserService;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
+import org.springframework.boot.autoconfigure.transaction.reactive.ReactiveTransactionAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@SpringBootApplication(exclude = {
+         //TransactionAutoConfiguration.class,
+        JdbcSqlExecutorConfiguration.class
+})
+@ImportAutoConfiguration(ReactiveTransactionAutoConfiguration.class)
+public class ReactiveTestApplication {
+
+
+    @Bean
+    public DefaultReactiveUserService defaultReactiveUserService(){
+
+        return new DefaultReactiveUserService();
+    }
+
+}

+ 46 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/sync/DefaultUserServiceTest.java

@@ -0,0 +1,46 @@
+package org.hswebframework.web.system.authorization.defaults.service.sync;
+
+import org.hswebframework.web.system.authorization.api.entity.UserEntity;
+import org.hswebframework.web.system.authorization.api.service.UserService;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class)
+public class DefaultUserServiceTest {
+
+    @Autowired
+    private UserService userService;
+
+    @Test
+    public void testCrud() {
+        UserEntity userEntity = new UserEntity();
+        userEntity.setName("test");
+        userEntity.setUsername("admin");
+        userEntity.setPassword("admin");
+
+        Assert.assertTrue(userService.saveUser(userEntity));
+
+        Assert.assertNotNull(userEntity.getId());
+
+        userEntity.setUsername("admin2");
+        userEntity.setPassword("admin2");
+        userService.saveUser(userEntity);
+
+        userService.changeState(userEntity.getId(), (byte) 1);
+
+        userService.changePassword(userEntity.getId(),"admin2","admin");
+
+        UserEntity entity = userService.findByUsernameAndPassword("admin", "admin").orElseThrow(NullPointerException::new);
+
+        Assert.assertEquals(entity.getName(), userEntity.getName());
+
+        Assert.assertEquals(entity.getStatus().byteValue(), (byte) 1);
+
+    }
+
+}

+ 21 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/sync/TestApplication.java

@@ -0,0 +1,21 @@
+package org.hswebframework.web.system.authorization.defaults.service.sync;
+
+import org.hswebframework.web.crud.configuration.R2dbcSqlExecutorConfiguration;
+import org.hswebframework.web.system.authorization.defaults.service.DefaultUserService;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication(exclude = {
+        R2dbcSqlExecutorConfiguration.class
+})
+public class TestApplication {
+
+
+    @Bean
+    public DefaultUserService defaultUserService(){
+
+        return new DefaultUserService();
+    }
+
+}

+ 11 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/resources/application.yml

@@ -0,0 +1,11 @@
+logging:
+  level:
+    org.hswebframework: debug
+    org.springframework.transaction: debug
+    org.springframework.data.r2dbc.connectionfactory: debug
+#spring:
+#  r2dbc:
+
+easyorm:
+  default-schema: PUBLIC
+  dialect: h2