Browse Source

Merge pull request #117 from hs-web/3.0.x

3.0.7
zhōuhào 6 năm trước cách đây
mục cha
commit
c7c7a7b8fb
100 tập tin đã thay đổi với 1345 bổ sung153 xóa
  1. 1 1
      hsweb-authorization/hsweb-authorization-api/pom.xml
  2. 1 1
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Authorize.java
  3. 1 1
      hsweb-authorization/hsweb-authorization-basic/pom.xml
  4. 1 1
      hsweb-authorization/hsweb-authorization-jwt/pom.xml
  5. 1 1
      hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-auth-server/pom.xml
  6. 1 1
      hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-client/pom.xml
  7. 1 1
      hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-core/pom.xml
  8. 1 1
      hsweb-authorization/hsweb-authorization-oauth2/pom.xml
  9. 1 1
      hsweb-authorization/pom.xml
  10. 1 1
      hsweb-boost/hsweb-boost-aop/pom.xml
  11. 1 1
      hsweb-boost/hsweb-boost-excel/pom.xml
  12. 1 1
      hsweb-boost/hsweb-boost-ftp/pom.xml
  13. 1 1
      hsweb-boost/pom.xml
  14. 1 1
      hsweb-commons/hsweb-commons-bean/pom.xml
  15. 1 1
      hsweb-commons/hsweb-commons-controller/pom.xml
  16. 1 1
      hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-api/pom.xml
  17. 1 1
      hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/pom.xml
  18. 4 0
      hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/java/org/hswebframework/web/dao/crud/TestCrud.java
  19. 5 0
      hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/resources/org/hswebframework/web/dao/test/TestDao.xml
  20. 1 1
      hsweb-commons/hsweb-commons-dao/pom.xml
  21. 1 1
      hsweb-commons/hsweb-commons-entity/pom.xml
  22. 15 0
      hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/events/EntityCreatedEvent.java
  23. 20 0
      hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/events/EntityModifyEvent.java
  24. 1 1
      hsweb-commons/hsweb-commons-model/pom.xml
  25. 1 1
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-api/pom.xml
  26. 1 1
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-oauth2/pom.xml
  27. 1 1
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/pom.xml
  28. 37 4
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericEntityService.java
  29. 49 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericsPayloadApplicationEvent.java
  30. 2 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/EnableCacheTests.java
  31. 2 1
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/GenericEntityServiceTest.java
  32. 85 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/ModifyEventTests.java
  33. 9 1
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestEntity.java
  34. 37 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntity.java
  35. 37 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntity2.java
  36. 44 0
      hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntityService.java
  37. 1 1
      hsweb-commons/hsweb-commons-service/pom.xml
  38. 6 1
      hsweb-commons/hsweb-commons-utils/pom.xml
  39. 31 6
      hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/ModuleUtils.java
  40. 22 2
      hsweb-commons/hsweb-commons-utils/src/test/java/org/hswebframework/web/ExpressionUtilsTests.java
  41. 8 0
      hsweb-commons/hsweb-commons-utils/src/test/resources/logback.xml
  42. 1 1
      hsweb-commons/pom.xml
  43. 1 1
      hsweb-concurrent/hsweb-concurrent-async-job/pom.xml
  44. 1 1
      hsweb-concurrent/hsweb-concurrent-cache/pom.xml
  45. 1 1
      hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/pom.xml
  46. 1 1
      hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-redis/pom.xml
  47. 1 1
      hsweb-concurrent/hsweb-concurrent-counter/pom.xml
  48. 1 1
      hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-api/pom.xml
  49. 1 1
      hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-redis/pom.xml
  50. 1 1
      hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-starter/pom.xml
  51. 1 1
      hsweb-concurrent/hsweb-concurrent-lock/pom.xml
  52. 1 1
      hsweb-concurrent/hsweb-concurrent-rate-limiter/hsweb-concurrent-rate-limiter-api/pom.xml
  53. 1 1
      hsweb-concurrent/hsweb-concurrent-rate-limiter/hsweb-concurrent-rate-limiter-starter/pom.xml
  54. 1 1
      hsweb-concurrent/hsweb-concurrent-rate-limiter/pom.xml
  55. 1 1
      hsweb-concurrent/pom.xml
  56. 1 1
      hsweb-core/pom.xml
  57. 31 0
      hsweb-core/src/main/java/org/hswebframework/web/audit/Audit.java
  58. 20 0
      hsweb-core/src/main/java/org/hswebframework/web/audit/AuditFieldMeta.java
  59. 28 0
      hsweb-core/src/main/java/org/hswebframework/web/audit/AuditMeta.java
  60. 12 0
      hsweb-core/src/main/java/org/hswebframework/web/audit/AuditMetaParser.java
  61. 11 0
      hsweb-core/src/main/java/org/hswebframework/web/audit/Strategy.java
  62. 268 0
      hsweb-core/src/main/java/org/hswebframework/web/bean/CompareUtils.java
  63. 49 0
      hsweb-core/src/main/java/org/hswebframework/web/bean/Diff.java
  64. 179 0
      hsweb-core/src/test/java/org/hswebframework/web/bean/CompareUtilsTest.java
  65. 31 0
      hsweb-core/src/test/java/org/hswebframework/web/bean/DiffTest.java
  66. 1 1
      hsweb-datasource/hsweb-datasource-api/pom.xml
  67. 1 1
      hsweb-datasource/hsweb-datasource-jta/pom.xml
  68. 1 1
      hsweb-datasource/hsweb-datasource-web/pom.xml
  69. 1 1
      hsweb-datasource/pom.xml
  70. 1 1
      hsweb-logging/hsweb-access-logging-aop/pom.xml
  71. 1 1
      hsweb-logging/hsweb-access-logging-api/pom.xml
  72. 1 1
      hsweb-logging/pom.xml
  73. 1 1
      hsweb-starter/hsweb-spring-boot-starter/pom.xml
  74. 72 9
      hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsAutoConfiguration.java
  75. 85 0
      hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsProperties.java
  76. 2 2
      hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/init/simple/SimpleDependencyInstaller.java
  77. 3 3
      hsweb-starter/hsweb-spring-boot-starter/src/test/resources/hsweb-starter.js
  78. 1 1
      hsweb-starter/pom.xml
  79. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml
  80. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-local/pom.xml
  81. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-local/src/main/resources/hsweb-module.json
  82. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/pom.xml
  83. 9 2
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/pom.xml
  84. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/src/main/java/org/hswebframework/web/authorization/controller/UserSettingController.java
  85. 9 0
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/src/main/resources/hsweb-module.json
  86. 1 1
      hsweb-system/hsweb-system-authorization/pom.xml
  87. 1 1
      hsweb-system/hsweb-system-config/hsweb-system-config-api/pom.xml
  88. 1 1
      hsweb-system/hsweb-system-config/hsweb-system-config-local/pom.xml
  89. 1 1
      hsweb-system/hsweb-system-config/hsweb-system-config-starter/pom.xml
  90. 1 1
      hsweb-system/hsweb-system-config/hsweb-system-config-web/pom.xml
  91. 1 1
      hsweb-system/hsweb-system-config/pom.xml
  92. 1 1
      hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-api/pom.xml
  93. 1 1
      hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-local/pom.xml
  94. 1 1
      hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-starter/pom.xml
  95. 1 1
      hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-web/pom.xml
  96. 1 1
      hsweb-system/hsweb-system-dashboard/pom.xml
  97. 1 1
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/pom.xml
  98. 9 2
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/pom.xml
  99. 49 55
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/src/main/java/org/hswebframework/web/datasource/manager/simple/DefaultLocalTransactionExecutor.java
  100. 0 0
      hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/src/main/resources/hsweb-module.json

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Authorize.java

@@ -76,7 +76,7 @@ public @interface Authorize {
      *
      * @return 验证失败提示的消息
      */
-    String message() default "{unauthorized}";
+    String message() default "无权限";
 
     /**
      * 是否合并类上的注解

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-jwt/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-auth-server/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-authorization-oauth2</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-client/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-authorization-oauth2</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-oauth2/hsweb-authorization-oauth2-core/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-authorization-oauth2</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <!--<relativePath>../../pom.xml</relativePath>-->
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-authorization/hsweb-authorization-oauth2/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-boost/hsweb-boost-aop/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-boost</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-boost/hsweb-boost-excel/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-boost</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-boost/hsweb-boost-ftp/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-boost</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-boost/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-commons/hsweb-commons-bean/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-commons/hsweb-commons-controller/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-api/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons-dao</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons-dao</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 4 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/java/org/hswebframework/web/dao/crud/TestCrud.java

@@ -3,6 +3,7 @@ package org.hswebframework.web.dao.crud;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.hswebframework.ezorm.core.param.QueryParam;
 import org.hswebframework.ezorm.rdb.executor.SqlExecutor;
+import org.hswebframework.web.commons.entity.param.DeleteParamEntity;
 import org.hswebframework.web.commons.entity.param.QueryParamEntity;
 import org.hswebframework.web.datasource.DataSourceHolder;
 import org.hswebframework.web.dict.EnumDict;
@@ -80,6 +81,9 @@ public class TestCrud extends AbstractTransactionalJUnit4SpringContextTests {
 
 //        testDao.query(entity);
 
+        DeleteParamEntity.newDelete()
+                .where("id","1234")
+                .exec(testDao::delete);
         System.out.println(entities);
     }
 

+ 5 - 0
hsweb-commons/hsweb-commons-dao/hsweb-commons-dao-mybatis/src/test/resources/org/hswebframework/web/dao/test/TestDao.xml

@@ -28,6 +28,11 @@
         <include refid="BasicMapper.buildUpdateSql"/>
     </update>
 
+    <update id="delete" parameterType="org.hswebframework.web.commons.entity.Entity">
+        <include refid="config"/>
+        <include refid="BasicMapper.buildDeleteSql"/>
+    </update>
+
     <select id="query" parameterType="org.hswebframework.web.commons.entity.Entity" resultMap="TestResultMap">
         <include refid="config"/>
         <include refid="BasicMapper.buildSelectSql"/>

+ 1 - 1
hsweb-commons/hsweb-commons-dao/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-commons/hsweb-commons-entity/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 15 - 0
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/events/EntityCreatedEvent.java

@@ -0,0 +1,15 @@
+package org.hswebframework.web.commons.entity.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.io.Serializable;
+
+@AllArgsConstructor
+@Getter
+public class EntityCreatedEvent<E> implements Serializable {
+
+    private E entity;
+
+    private Class<E> entityType;
+}

+ 20 - 0
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/events/EntityModifyEvent.java

@@ -0,0 +1,20 @@
+package org.hswebframework.web.commons.entity.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.io.Serializable;
+
+@AllArgsConstructor
+@Getter
+public class EntityModifyEvent<E> implements Serializable{
+
+    private static final long serialVersionUID = -7158901204884303777L;
+
+    private E before;
+
+    private E after;
+
+    private Class<E> entityType;
+
+}

+ 1 - 1
hsweb-commons/hsweb-commons-model/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-commons/hsweb-commons-service/hsweb-commons-service-api/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons-service</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-commons/hsweb-commons-service/hsweb-commons-service-oauth2/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-commons-service</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons-service</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
 
     </parent>

+ 37 - 4
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericEntityService.java

@@ -22,13 +22,13 @@ import org.hswebframework.web.commons.entity.GenericEntity;
 import org.hswebframework.web.commons.entity.LogicalDeleteEntity;
 import org.hswebframework.web.commons.entity.RecordCreationEntity;
 import org.hswebframework.web.commons.entity.RecordModifierEntity;
-import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.commons.entity.events.EntityCreatedEvent;
+import org.hswebframework.web.commons.entity.events.EntityModifyEvent;
 import org.hswebframework.web.id.IDGenerator;
-import org.hswebframework.web.validator.DuplicateKeyException;
-import org.hswebframework.web.validator.LogicPrimaryKeyValidator;
 import org.hswebframework.web.validator.group.CreateGroup;
 import org.hswebframework.web.validator.group.UpdateGroup;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
@@ -61,6 +61,13 @@ public abstract class GenericEntityService<E extends GenericEntity<PK>, PK>
      */
     protected abstract IDGenerator<PK> getIDGenerator();
 
+    protected ApplicationEventPublisher eventPublisher;
+
+    @Autowired(required = false)
+    public void setEventPublisher(ApplicationEventPublisher eventPublisher) {
+        this.eventPublisher = eventPublisher;
+    }
+
     @PostConstruct
     public void init() {
         if (logicPrimaryKeyValidator instanceof DefaultLogicPrimaryKeyValidator) {
@@ -84,18 +91,40 @@ public abstract class GenericEntityService<E extends GenericEntity<PK>, PK>
                     .where(GenericEntity.id, pk)
                     .exec();
         } else {
-            getDao().deleteByPk(pk);
+            if (!physicalDeleteByPk(pk)) {
+                logger.warn("物理删除数据失败,主键:{}", pk);
+            }
         }
         return old;
     }
 
+    protected boolean physicalDeleteByPk(PK pk) {
+        //createDelete().where(GenericEntity.id,pk).exec()>0;
+
+        return getDao().deleteByPk(pk) > 0;
+    }
+
+    protected boolean pushModifyEvent() {
+        return RecordModifierEntity.class.isAssignableFrom(entityType);
+    }
+
+    protected boolean pushCreatedEvent() {
+        return RecordCreationEntity.class.isAssignableFrom(entityType);
+    }
+
     @Override
     public int updateByPk(PK pk, E entity) {
         Assert.notNull(pk, "primary key can not be null");
         Assert.hasText(String.valueOf(pk), "primary key can not be null");
         Assert.notNull(entity, "entity can not be null");
         entity.setId(pk);
+
         tryValidate(entity, UpdateGroup.class);
+        //尝试推送 EntityModifyEvent 事件.
+        if (eventPublisher != null && pushModifyEvent()) {
+            E old = selectByPk(pk);
+            eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, new EntityModifyEvent<>(old, entity, getEntityType()), getEntityType()));
+        }
         return createUpdate(entity)
                 //如果是RecordCreationEntity则不修改creator_id和creator_time
                 .when(entity instanceof RecordCreationEntity,
@@ -152,6 +181,10 @@ public abstract class GenericEntityService<E extends GenericEntity<PK>, PK>
         }
         tryValidate(entity, CreateGroup.class);
         getDao().insert(entity);
+
+        if (eventPublisher != null && pushCreatedEvent()) {
+            eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, new EntityCreatedEvent<>(entity, getEntityType()), getEntityType()));
+        }
         return entity.getId();
     }
 

+ 49 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/main/java/org/hswebframework/web/service/GenericsPayloadApplicationEvent.java

@@ -0,0 +1,49 @@
+package org.hswebframework.web.service;
+
+import org.springframework.context.PayloadApplicationEvent;
+import org.springframework.core.ResolvableType;
+
+/**
+ * 动态泛型事件,用于动态发布支持泛型的事件
+ * <pre>
+ *     //相当于发布事件: EntityModifyEvent&lt;UserEntity&gt;
+ *     eventPublisher
+ *          .publishEvent(new GenericsPayloadApplicationEvent&lt;&gt;(this, new EntityModifyEvent<>(oldEntity, newEntity), UserEntity.class));
+ *
+ *      //只监听相同泛型事件
+ *      &#064;EventListener
+ *      public handleEvent(EntityModifyEvent&lt;UserEntity&gt; event){
+ *
+ *      }
+ * </pre>
+ *
+ * @author zhouhao
+ * @since 3.0.7
+ */
+public class GenericsPayloadApplicationEvent<E> extends PayloadApplicationEvent<E> {
+
+    private static final long serialVersionUID = 3745888943307798710L;
+
+    //泛型列表
+    private transient Class[] generics;
+
+    //事件类型
+    private transient Class eventType;
+
+    /**
+     * @param source   事件源
+     * @param payload  事件,不能使用匿名内部类
+     * @param generics 泛型列表
+     */
+    public GenericsPayloadApplicationEvent(Object source, E payload, Class... generics) {
+        super(source, payload);
+        this.generics = generics;
+        this.eventType = payload.getClass();
+    }
+
+    @Override
+    public ResolvableType getResolvableType() {
+        return ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class
+                , ResolvableType.forClassWithGenerics(eventType, generics));
+    }
+}

+ 2 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/EnableCacheTests.java

@@ -106,6 +106,8 @@ public class EnableCacheTests {
         doTest(enableCacheAllEvictTreeTestService);
     }
 
+
+
     public void doTest(CrudService<TestEntity, String> service) {
         service.selectByPk("testId"); //db 1
         service.selectByPk("testId");//cache

+ 2 - 1
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/GenericEntityServiceTest.java

@@ -13,6 +13,8 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.mockito.stubbing.Answer;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationEventPublisher;
 
 import javax.validation.Validation;
 import java.util.ArrayList;
@@ -40,7 +42,6 @@ public class GenericEntityServiceTest {
     public void init() {
         entityService.setEntityFactory(new MapperEntityFactory());
         entityService.setValidator(Validation.buildDefaultValidatorFactory().getValidator());
-
         TestEntity entity = TestEntity.builder()
                 .age((byte) 10)
                 .enabled(true)

+ 85 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/ModifyEventTests.java

@@ -0,0 +1,85 @@
+package org.hswebframework.web.service;
+
+import org.hswebframework.web.commons.entity.events.EntityModifyEvent;
+import org.hswebframework.web.commons.entity.factory.MapperEntityFactory;
+import org.hswebframework.web.dao.CrudDao;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@SpringBootTest(classes = SpringTestApplication.class)
+@RunWith(value = SpringRunner.class)
+@Component
+public class ModifyEventTests {
+
+    @Autowired
+    private TestModifyEntityService modifyEntityService;
+
+    private AtomicInteger counter = new AtomicInteger();
+
+    @Before
+    public void init() {
+        CrudDao<TestModifyEntity, String> dao = Mockito.mock(CrudDao.class);
+        modifyEntityService.setEntityFactory(new MapperEntityFactory());
+        modifyEntityService.setDao(dao);
+        TestModifyEntity entity = TestModifyEntity.builder()
+                .age((byte) 10)
+                .enabled(true)
+                .name("test")
+                .build();
+        entity.setId("testId");
+
+        when(dao.query(any()))
+                .then((Answer<List<TestModifyEntity>>) invocationOnMock -> {
+                    //模拟命中数据库
+                    counter.incrementAndGet();
+                    return new ArrayList<>(Arrays.asList(entity));
+                });
+
+        when(dao.count(any())).then((Answer<Integer>) invocationOnMock -> {
+            //模拟命中数据库
+            counter.incrementAndGet();
+            return 1;
+        });
+
+        when(dao.update(any())).thenReturn(1);
+
+        when(dao.delete(any())).thenReturn(1);
+        when(dao.deleteByPk(anyString())).thenReturn(1);
+
+        doNothing().when(dao).insert(anyObject());
+
+    }
+
+
+    @Test
+    public void modifyTest() {
+        TestModifyEntity entity = new TestModifyEntity();
+        entity.setId("testId");
+        entity.setAge((byte) 10);
+
+        modifyEntityService.updateByPk("test", entity);
+        Assert.assertTrue(TestModifyEntityService.eventCounter.get() != 0);
+    }
+
+
+}

+ 9 - 1
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestEntity.java

@@ -2,6 +2,7 @@ package org.hswebframework.web.service;
 
 import lombok.*;
 import org.hibernate.validator.constraints.NotBlank;
+import org.hswebframework.web.commons.entity.RecordModifierEntity;
 import org.hswebframework.web.commons.entity.SimpleGenericEntity;
 import org.hswebframework.web.commons.entity.SimpleTreeSortSupportEntity;
 import org.hswebframework.web.validator.LogicPrimaryKey;
@@ -18,7 +19,9 @@ import java.util.List;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class TestEntity extends SimpleTreeSortSupportEntity<String> {
+public class TestEntity extends SimpleTreeSortSupportEntity<String>
+//        implements RecordModifierEntity
+{
 
     @NotBlank(groups = CreateGroup.class)
     private String name;
@@ -28,4 +31,9 @@ public class TestEntity extends SimpleTreeSortSupportEntity<String> {
     private Boolean enabled;
 
     private List<TestEntity> children;
+
+    private String modifierId;
+
+    private Long modifyTime;
+
 }

+ 37 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntity.java

@@ -0,0 +1,37 @@
+package org.hswebframework.web.service;
+
+import lombok.*;
+import org.hibernate.validator.constraints.NotBlank;
+import org.hswebframework.web.commons.entity.RecordModifierEntity;
+import org.hswebframework.web.commons.entity.SimpleTreeSortSupportEntity;
+import org.hswebframework.web.validator.group.CreateGroup;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 1.0
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TestModifyEntity extends SimpleTreeSortSupportEntity<String>
+        implements RecordModifierEntity
+{
+
+    @NotBlank(groups = CreateGroup.class)
+    private String name;
+
+    private Byte age;
+
+    private Boolean enabled;
+
+    private List<TestModifyEntity> children;
+
+    private String modifierId;
+
+    private Long modifyTime;
+
+}

+ 37 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntity2.java

@@ -0,0 +1,37 @@
+package org.hswebframework.web.service;
+
+import lombok.*;
+import org.hibernate.validator.constraints.NotBlank;
+import org.hswebframework.web.commons.entity.RecordModifierEntity;
+import org.hswebframework.web.commons.entity.SimpleTreeSortSupportEntity;
+import org.hswebframework.web.validator.group.CreateGroup;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 1.0
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TestModifyEntity2 extends SimpleTreeSortSupportEntity<String>
+        implements RecordModifierEntity
+{
+
+    @NotBlank(groups = CreateGroup.class)
+    private String name;
+
+    private Byte age;
+
+    private Boolean enabled;
+
+    private List<TestModifyEntity2> children;
+
+    private String modifierId;
+
+    private Long modifyTime;
+
+}

+ 44 - 0
hsweb-commons/hsweb-commons-service/hsweb-commons-service-simple/src/test/java/org/hswebframework/web/service/TestModifyEntityService.java

@@ -0,0 +1,44 @@
+package org.hswebframework.web.service;
+
+import org.hswebframework.web.commons.entity.RecordModifierEntity;
+import org.hswebframework.web.commons.entity.events.EntityModifyEvent;
+import org.hswebframework.web.dao.CrudDao;
+import org.hswebframework.web.id.IDGenerator;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+@Service
+public class TestModifyEntityService extends GenericEntityService<TestModifyEntity, String> {
+
+    private CrudDao<TestModifyEntity, String> dao;
+
+    public static AtomicLong eventCounter = new AtomicLong();
+
+    @Override
+    protected IDGenerator<String> getIDGenerator() {
+        return IDGenerator.MD5;
+    }
+
+    @Override
+    public CrudDao<TestModifyEntity, String> getDao() {
+        return dao;
+    }
+
+    public void setDao(CrudDao<TestModifyEntity, String> dao) {
+        this.dao = dao;
+    }
+
+    @EventListener
+    public void handleEvent(EntityModifyEvent<TestModifyEntity> modifyEvent){
+        eventCounter.incrementAndGet();
+        System.out.println(modifyEvent);
+    }
+
+}

+ 1 - 1
hsweb-commons/hsweb-commons-service/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 6 - 1
hsweb-commons/hsweb-commons-utils/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -85,5 +85,10 @@
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
         </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>

+ 31 - 6
hsweb-commons/hsweb-commons-utils/src/main/java/org/hswebframework/web/ModuleUtils.java

@@ -9,6 +9,8 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.StringUtils;
 
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -34,7 +36,7 @@ public abstract class ModuleUtils {
             log.info("init module info");
             Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:/hsweb-module.json");
             for (Resource resource : resources) {
-                String classPath = getClassPath(resource.getURL().getPath(), "hsweb-module.json");
+                String classPath = getClassPath(resource.getURL().toString(), "hsweb-module.json");
                 ModuleInfo moduleInfo = JSON.parseObject(resource.getInputStream(), ModuleInfo.class);
                 moduleInfo.setClassPath(classPath);
                 ModuleUtils.register(moduleInfo);
@@ -49,13 +51,36 @@ public abstract class ModuleUtils {
     }
 
     public static String getClassPath(Class type) {
-        String path = type.getResource("").getPath();
-        String packages = type.getPackage().getName();
-        return getClassPath(path, packages);
+        ProtectionDomain domain = type.getProtectionDomain();
+        CodeSource codeSource = domain.getCodeSource();
+        if (codeSource == null) {
+            return getClassPath(type.getResource("").getPath(), type.getPackage().getName());
+        }
+        String path = codeSource.getLocation().toString();
+
+        boolean isJar = path.contains("!/") && path.contains(".jar");
+
+        if (isJar) {
+            return path.substring(0, path.lastIndexOf(".jar") + 4);
+        }
+
+        if (path.endsWith("/")) {
+            return path.substring(0, path.length() - 1);
+        }
+        return path;
     }
 
     public static String getClassPath(String path, String packages) {
-        int pos = path.contains("!/") ? 3 : path.endsWith("/") ? 2 : 1;
+        if (path.endsWith(".jar")) {
+            return path;
+        }
+        boolean isJar = path.contains("!/") && path.contains(".jar");
+
+        if (isJar) {
+            return path.substring(0, path.lastIndexOf(".jar") + 4);
+        }
+
+        int pos = path.endsWith("/") ? 2 : 1;
         return path.substring(0, path.length() - packages.length() - pos);
     }
 
@@ -102,7 +127,7 @@ public abstract class ModuleUtils {
 
         public String getGitLocation() {
             String gitCommitHash = this.gitCommitHash;
-            if (gitCommitHash.contains("$")) {
+            if (gitCommitHash == null || gitCommitHash.contains("$")) {
                 gitCommitHash = "master";
             }
             return gitRepository + "/blob/" + gitCommitHash + "/" + path + "/";

+ 22 - 2
hsweb-commons/hsweb-commons-utils/src/test/java/org/hswebframework/web/ExpressionUtilsTests.java

@@ -1,9 +1,11 @@
 package org.hswebframework.web;
 
+import lombok.SneakyThrows;
 import org.junit.Assert;
 import org.junit.Test;
 
 import java.util.Collections;
+import java.util.Map;
 
 import static org.junit.Assert.*;
 
@@ -11,11 +13,29 @@ public class ExpressionUtilsTests {
 
     @Test
     public void testAnalytical() throws Exception {
-        String result = ExpressionUtils.analytical("test${1+2}", "spel");
+        String result = ExpressionUtils.analytical("test${1+2} ${''} ${1+4+5}", "spel");
 
-        Assert.assertEquals(result, "test3");
+        Assert.assertEquals(result, "test3  10");
 
         result = ExpressionUtils.analytical("test${#param}", Collections.singletonMap("param", "3"), "spel");
         Assert.assertEquals(result, "test3");
     }
+
+    @Test
+    @SneakyThrows
+    public void benchmark() {
+
+        String expression = "test${1+2}  ${1+4+5}";
+
+        ExpressionUtils.analytical(expression, Collections.emptyMap(), "spel");
+
+        long time = System.currentTimeMillis();
+        for (int i = 0; i < 100000; i++) {
+            ExpressionUtils.analytical(expression, Collections.emptyMap(), "spel");
+        }
+
+        System.out.println(System.currentTimeMillis() - time);
+    }
+
+
 }

+ 8 - 0
hsweb-commons/hsweb-commons-utils/src/test/resources/logback.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:noNamespaceSchemaLocation="http://www.padual.com/java/logback.xsd"
+               debug="false" scan="true" scanPeriod="30 second">
+    <root level="warn">
+
+    </root>
+</configuration>

+ 1 - 1
hsweb-commons/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-async-job/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-cache/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-api/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-concurrent-counter</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-counter/hsweb-concurrent-counter-redis/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-counter</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-counter/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-lock</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-redis/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-lock</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-lock/hsweb-concurrent-lock-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-lock</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-lock/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-rate-limiter/hsweb-concurrent-rate-limiter-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-rate-limiter</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-rate-limiter/hsweb-concurrent-rate-limiter-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent-rate-limiter</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/hsweb-concurrent-rate-limiter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-concurrent/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 31 - 0
hsweb-core/src/main/java/org/hswebframework/web/audit/Audit.java

@@ -0,0 +1,31 @@
+package org.hswebframework.web.audit;
+
+import java.lang.annotation.*;
+
+/**
+ * 审计信息注解,用于在修改更新数据的时候记录被修改的内容.
+ * @since 3.0.7
+ *
+ */
+@Target({ElementType.FIELD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Audit {
+
+    //审计信息简介,如功能,字段.
+    String value();
+
+    //审计信息的说明
+    String comment() default "";
+
+    //是否忽略审计
+    boolean ignore() default false;
+
+    //字段生效策略,如果为MANUAL,修改数据时,字段将不会立即修改,而是需要手动审核通过后生效.
+    Strategy strategy() default Strategy.AUTO;
+
+    //如果设置了审核权限,当进行审核或者回退的时候将进行权限验证.
+    //如: permission:user:audit
+    //role:admin
+    String auditPermission() default "";
+}

+ 20 - 0
hsweb-core/src/main/java/org/hswebframework/web/audit/AuditFieldMeta.java

@@ -0,0 +1,20 @@
+package org.hswebframework.web.audit;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author zhouhao
+ * @since 3.0.7
+ */
+@Getter
+@Setter
+public class AuditFieldMeta {
+    private String field;
+
+    private String comment;
+
+    private String type;
+
+    private Strategy strategy;
+}

+ 28 - 0
hsweb-core/src/main/java/org/hswebframework/web/audit/AuditMeta.java

@@ -0,0 +1,28 @@
+package org.hswebframework.web.audit;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * 审计信息注解,用于在修改更新数据的时候记录被修改的内容.
+ *
+ * @since 3.0.7
+ */
+@Getter
+@Setter
+public class AuditMeta {
+
+    private String type;
+
+    private String comment;
+
+    private List<AuditFieldMeta> fields;
+
+    public boolean isEmpty() {
+        return CollectionUtils.isEmpty(fields);
+    }
+}

+ 12 - 0
hsweb-core/src/main/java/org/hswebframework/web/audit/AuditMetaParser.java

@@ -0,0 +1,12 @@
+package org.hswebframework.web.audit;
+
+import java.util.Optional;
+
+/**
+ * @author zhouhao
+ * @since 3.0.7
+ */
+public interface AuditMetaParser {
+
+    Optional<AuditMeta> parse(Class<?> type);
+}

+ 11 - 0
hsweb-core/src/main/java/org/hswebframework/web/audit/Strategy.java

@@ -0,0 +1,11 @@
+package org.hswebframework.web.audit;
+
+/**
+ * 生效策略
+ *
+ * @since 3.0.7
+ */
+public enum Strategy {
+    AUTO,
+    MANUAL;
+}

+ 268 - 0
hsweb-core/src/main/java/org/hswebframework/web/bean/CompareUtils.java

@@ -0,0 +1,268 @@
+package org.hswebframework.web.bean;
+
+import org.hswebframework.utils.time.DateFormatter;
+import org.hswebframework.web.dict.EnumDict;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+@SuppressWarnings("all")
+public abstract class CompareUtils {
+
+    public static boolean compare(Object source, Object target) {
+        if (source == target) {
+            return true;
+        }
+
+        if (source == null || target == null) {
+            return false;
+        }
+
+        if (source.equals(target)) {
+            return true;
+        }
+        if (source instanceof Number) {
+            return compare(((Number) source), target);
+        }
+        if (target instanceof Number) {
+            return compare(((Number) target), source);
+        }
+
+        if (source instanceof Date) {
+            return compare(((Date) source), target);
+        }
+
+        if (target instanceof Date) {
+            return compare(((Date) target), source);
+        }
+
+        if (source instanceof String) {
+            return compare(((String) source), target);
+        }
+
+        if (target instanceof String) {
+            return compare(((String) target), source);
+        }
+        if (source instanceof Collection) {
+            return compare(((Collection) source), target);
+        }
+
+        if (target instanceof Collection) {
+            return compare(((Collection) target), source);
+        }
+
+        if (source instanceof Map) {
+            return compare(((Map) source), target);
+        }
+
+        if (target instanceof Map) {
+            return compare(((Map) target), source);
+        }
+
+        if (source.getClass().isEnum()) {
+            return compare(((Enum) source), target);
+        }
+
+        if (target.getClass().isEnum()) {
+            return compare(((Enum) target), source);
+        }
+
+        if (source.getClass().isArray()) {
+            return compare(((Object[]) source), target);
+        }
+
+        if (target.getClass().isArray()) {
+            return compare(((Object[]) target), source);
+        }
+
+
+        return compare(FastBeanCopier.copy(source, HashMap.class), FastBeanCopier.copy(target, HashMap.class));
+
+    }
+
+    public static boolean compare(Map<?, ?> map, Object target) {
+        if (map == target) {
+            return true;
+        }
+
+        if (map == null || target == null) {
+            return false;
+        }
+        Map<?, ?> targetMap = null;
+        if (target instanceof Map) {
+            targetMap = ((Map) target);
+        } else {
+            targetMap = FastBeanCopier.copy(target, HashMap::new);
+        }
+
+        if (map.size() != targetMap.size()) {
+            return false;
+        }
+        for (Map.Entry entry : map.entrySet()) {
+            if (!compare(entry.getValue(), targetMap.get(entry.getKey()))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
+    public static boolean compare(Collection collection, Object target) {
+        if (collection == target) {
+            return true;
+        }
+
+        if (collection == null || target == null) {
+            return false;
+        }
+        Collection targetCollection = null;
+        if (target instanceof String) {
+            target = ((String) target).split("[, ;]");
+        }
+        if (target instanceof Collection) {
+            targetCollection = ((Collection) target);
+        } else if (target.getClass().isArray()) {
+            targetCollection = Arrays.asList(((Object[]) target));
+        }
+        if (targetCollection == null) {
+            return false;
+        }
+
+        Set left = new HashSet(collection);
+        Set right = new HashSet(targetCollection);
+
+        if (left.size() < right.size()) {
+            Set tmp = right;
+            right = left;
+            left = tmp;
+        }
+        l:
+        for (Object source : left) {
+            if (!right.stream().anyMatch(targetObj -> compare(source, targetObj))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean compare(Object[] number, Object target) {
+
+
+        return compare(Arrays.asList(number), target);
+    }
+
+    public static boolean compare(Number number, Object target) {
+        if (number == target) {
+            return true;
+        }
+
+        if (number == null || target == null) {
+            return false;
+        }
+
+        if (target.equals(number)) {
+            return true;
+        }
+        if (target instanceof Number) {
+            return number.doubleValue() == ((Number) target).doubleValue();
+        }
+        if (target instanceof Date) {
+            return number.longValue() == ((Date) target).getTime();
+        }
+        if (target instanceof String) {
+            //日期格式的字符串?
+            String stringValue = String.valueOf(target);
+            if (DateFormatter.isSupport(stringValue)) {
+                //格式化为相同格式的字符串进行对比
+                DateFormatter dateFormatter = DateFormatter.getFormatter(stringValue);
+                return (dateFormatter.toString(new Date(number.longValue())).equals(stringValue));
+            }
+            try{
+                return new BigDecimal(stringValue).doubleValue() == number.doubleValue();
+            }catch (NumberFormatException e){
+                return false;
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean compare(Enum e, Object target) {
+        if (e == target) {
+            return true;
+        }
+
+        if (e == null || target == null) {
+            return false;
+        }
+        String stringValue = String.valueOf(target);
+        if (e instanceof EnumDict) {
+            EnumDict dict = ((EnumDict) e);
+            return e.name().equalsIgnoreCase(stringValue) || dict.eq(target);
+        }
+
+        return e.name().equalsIgnoreCase(stringValue);
+    }
+
+    public static boolean compare(String string, Object target) {
+        if (string == target) {
+            return true;
+        }
+
+        if (string == null || target == null) {
+            return false;
+        }
+        if (string.equals(String.valueOf(target))) {
+            return true;
+        }
+
+        if (target instanceof Enum) {
+            return compare(((Enum) target), string);
+        }
+
+        if (target instanceof Date) {
+            return compare(((Date) target), string);
+        }
+
+        if (target instanceof Number) {
+            return compare(((Number) target), string);
+        }
+        if (target instanceof Collection) {
+            return compare(((Collection) target), string);
+        }
+
+        return false;
+    }
+
+    public static boolean compare(Date date, Object target) {
+        if (date == target) {
+            return true;
+        }
+
+        if (date == null || target == null) {
+            return false;
+        }
+        if (target instanceof Date) {
+            return date.getTime() == ((Date) target).getTime();
+        }
+
+        if (target instanceof String) {
+            //日期格式的字符串?
+            String stringValue = String.valueOf(target);
+            if (DateFormatter.isSupport(stringValue)) {
+                //格式化为相同格式的字符串进行对比
+                DateFormatter dateFormatter = DateFormatter.getFormatter(stringValue);
+                return (dateFormatter.toString(date).equals(stringValue));
+            }
+        }
+
+        if (target instanceof Number) {
+            long longValue = ((Number) target).longValue();
+            return date.getTime() == longValue;
+        }
+
+        return false;
+    }
+
+}

+ 49 - 0
hsweb-core/src/main/java/org/hswebframework/web/bean/Diff.java

@@ -0,0 +1,49 @@
+package org.hswebframework.web.bean;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class Diff {
+
+    private String property;
+
+    private Object before;
+
+    private Object after;
+
+    public static List<Diff> of(Object before, Object after) {
+        List<Diff> diffs = new ArrayList<>();
+
+        Map<String, Object> beforeMap = FastBeanCopier.copy(before, HashMap::new);
+        Map<String, Object> afterMap = FastBeanCopier.copy(after, HashMap::new);
+
+        for (Map.Entry<String, Object> entry : afterMap.entrySet()) {
+            Object afterValue = entry.getValue();
+            String key = entry.getKey();
+            Object beforeValue = beforeMap.get(key);
+            if (!CompareUtils.compare(beforeValue, afterValue)) {
+                diffs.add(new Diff(key, beforeValue, afterValue));
+            }
+        }
+        return diffs;
+
+    }
+
+    @Override
+    public String toString() {
+        return JSON.toJSONString(this);
+    }
+}

+ 179 - 0
hsweb-core/src/test/java/org/hswebframework/web/bean/CompareUtilsTest.java

@@ -0,0 +1,179 @@
+package org.hswebframework.web.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.utils.time.DateFormatter;
+import org.hswebframework.web.dict.EnumDict;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+public class CompareUtilsTest {
+
+    @Test
+    public void nullTest() {
+
+        Assert.assertFalse(CompareUtils.compare(1, null));
+
+        Assert.assertFalse(CompareUtils.compare((Object) null, 1));
+        Assert.assertTrue(CompareUtils.compare((Object) null, null));
+        Assert.assertFalse(CompareUtils.compare((Number) null, 1));
+        Assert.assertTrue(CompareUtils.compare((Number) null, null));
+        Assert.assertFalse(CompareUtils.compare((Date) null, 1));
+        Assert.assertTrue(CompareUtils.compare((Date) null, null));
+        Assert.assertFalse(CompareUtils.compare((String) null, 1));
+        Assert.assertTrue(CompareUtils.compare((String) null, null));
+        Assert.assertFalse(CompareUtils.compare((Collection) null, 1));
+        Assert.assertTrue(CompareUtils.compare((Collection) null, null));
+        Assert.assertFalse(CompareUtils.compare((Map<?, ?>) null, 1));
+        Assert.assertTrue(CompareUtils.compare((Map<?, ?>) null, null));
+
+    }
+
+    @Test
+    public void numberTest() {
+        Assert.assertTrue(CompareUtils.compare(1, 1));
+        Assert.assertTrue(CompareUtils.compare(1, 1D));
+        Assert.assertTrue(CompareUtils.compare(1, 1.0D));
+        Assert.assertTrue(CompareUtils.compare(1e3,"1e3"));
+        Assert.assertTrue(CompareUtils.compare(1e3,"1000"));
+
+        Assert.assertTrue(CompareUtils.compare(1, "1"));
+        Assert.assertTrue(CompareUtils.compare("1.0", 1));
+        Assert.assertFalse(CompareUtils.compare(1, "1a"));
+    }
+
+    @Test
+    public void enumTest() {
+
+        Assert.assertTrue(CompareUtils.compare(TestEnum.BLUE, "blue"));
+
+        Assert.assertFalse(CompareUtils.compare(TestEnum.RED, "blue"));
+
+
+        Assert.assertTrue(CompareUtils.compare(TestEnumDic.BLUE, "blue"));
+
+        Assert.assertFalse(CompareUtils.compare(TestEnumDic.RED, "blue"));
+
+
+        Assert.assertTrue(CompareUtils.compare(TestEnumDic.BLUE, "蓝色"));
+
+        Assert.assertFalse(CompareUtils.compare(TestEnumDic.RED, "蓝色"));
+
+
+    }
+
+    @Test
+    public void stringTest() {
+
+        Assert.assertTrue(CompareUtils.compare("20180101", DateFormatter.fromString("20180101")));
+
+        Assert.assertTrue(CompareUtils.compare(1,"1"));
+
+        Assert.assertTrue(CompareUtils.compare("1", 1));
+
+        Assert.assertTrue(CompareUtils.compare("1.0", 1.0D));
+
+        Assert.assertTrue(CompareUtils.compare("1.01", 1.01D));
+
+        Assert.assertTrue(CompareUtils.compare("1,2,3", Arrays.asList(1, 2, 3)));
+
+        Assert.assertTrue(CompareUtils.compare("blue", TestEnumDic.BLUE));
+
+        Assert.assertTrue(CompareUtils.compare("BLUE", TestEnum.BLUE));
+
+
+    }
+
+    @Test
+    public void dateTest() {
+
+        Date date = new Date();
+
+        Assert.assertTrue(CompareUtils.compare(date, new Date(date.getTime())));
+        Assert.assertTrue(CompareUtils.compare(date, DateFormatter.toString(date, "yyyy-MM-dd")));
+        Assert.assertTrue(CompareUtils.compare(date, DateFormatter.toString(date, "yyyy-MM-dd HH:mm:ss")));
+
+
+        Assert.assertTrue(CompareUtils.compare(date, date.getTime()));
+        Assert.assertTrue(CompareUtils.compare(date.getTime(), date));
+
+    }
+
+    @Test
+    public void connectionTest() {
+        Date date = new Date();
+
+        Assert.assertTrue(CompareUtils.compare(100, new BigDecimal("100")));
+
+        Assert.assertTrue(CompareUtils.compare(new BigDecimal("100"), 100.0D));
+
+        Assert.assertTrue(CompareUtils.compare(Arrays.asList(1, 2, 3), Arrays.asList("3", "2", "1")));
+
+        Assert.assertFalse(CompareUtils.compare(Arrays.asList(1, 2, 3), Arrays.asList("3", "3", "1")));
+
+        Assert.assertFalse(CompareUtils.compare(Arrays.asList(1, 2, 3), Arrays.asList("3", "1")));
+
+        Assert.assertFalse(CompareUtils.compare(Arrays.asList(1, 2, 3), Collections.emptyList()));
+        Assert.assertFalse(CompareUtils.compare(Collections.emptyList(), Arrays.asList(1, 2, 3)));
+
+        Assert.assertTrue(CompareUtils.compare(Arrays.asList(date, 3), Arrays.asList("3", DateFormatter.toString(date, "yyyy-MM-dd"))));
+
+    }
+
+    @Test
+    public void mapTest() {
+        Date date = new Date();
+
+        Assert.assertTrue(CompareUtils.compare(Collections.singletonMap("test", "123"), Collections.singletonMap("test", 123)));
+
+
+        Assert.assertFalse(CompareUtils.compare(Collections.singletonMap("test", "123"), Collections.emptyMap()));
+
+        Assert.assertTrue(CompareUtils.compare(Collections.singletonMap("test", "123"), new TestBean("123")));
+
+        Assert.assertTrue(CompareUtils.compare(Collections.singletonMap("test", date), new TestBean(DateFormatter.toString(date, "yyyy-MM-dd"))));
+
+    }
+
+    @Test
+    public void beanTest() {
+        Date date = new Date();
+
+        Assert.assertTrue(CompareUtils.compare(new TestBean(date), new TestBean(DateFormatter.toString(date, "yyyy-MM-dd"))));
+
+        Assert.assertTrue(CompareUtils.compare(new TestBean(1), new TestBean("1")));
+
+        Assert.assertTrue(CompareUtils.compare(new TestBean(1), new TestBean("1.0")));
+        Assert.assertFalse(CompareUtils.compare(new TestBean(1), new TestBean("1.0000000001")));
+
+    }
+
+    @Getter
+    @Setter
+    @AllArgsConstructor
+    public static class TestBean {
+        private Object test;
+    }
+
+
+    enum TestEnum {
+        RED, BLUE
+    }
+
+    @Getter
+    @AllArgsConstructor
+    enum TestEnumDic implements EnumDict<String> {
+        RED("RED", "红色"), BLUE("BLUE", "蓝色");
+
+        private String value;
+        private String text;
+
+    }
+
+}

+ 31 - 0
hsweb-core/src/test/java/org/hswebframework/web/bean/DiffTest.java

@@ -0,0 +1,31 @@
+package org.hswebframework.web.bean;
+
+import org.hswebframework.utils.time.DateFormatter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DiffTest {
+
+    @Test
+    public void mapTest() {
+        Map<String, Object> before = new HashMap<>();
+        before.put("name", "name");
+        before.put("age",21);
+        before.put("birthday", DateFormatter.fromString("19910101"));
+
+        Map<String, Object> after = new HashMap<>();
+        after.put("name", "name");
+        after.put("age", "21");
+        after.put("birthday", "1991-01-01");
+
+
+        List<Diff> diffs = Diff.of(before, after);
+        System.out.println(diffs);
+        Assert.assertTrue(diffs.isEmpty());
+
+    }
+}

+ 1 - 1
hsweb-datasource/hsweb-datasource-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-datasource/hsweb-datasource-jta/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
 
     </parent>

+ 1 - 1
hsweb-datasource/hsweb-datasource-web/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-datasource/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-logging/hsweb-access-logging-aop/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-logging</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-logging/hsweb-access-logging-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-logging</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-logging/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-starter/hsweb-spring-boot-starter/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-starter</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 72 - 9
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsAutoConfiguration.java

@@ -1,33 +1,96 @@
 package org.hswebframework.web.starter;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-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.Configuration;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.filter.CorsFilter;
 
+import java.util.Collections;
+import java.util.Optional;
+
 /**
- * 跨域设置
+ * 跨域设置,支持不同的请求路径,配置不同的跨域信息配置
+ *
+ * <p>
+ * Example:
+ * <pre class="code">
+ *   {@code
+ *      hsweb:
+ *        cors:
+ *          enable: true
+ *          configs:
+ *            - /**:
+ *                allowed-headers: "*"
+ *                allowed-methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
+ *                allowed-origins: ["http://xxx.example.com"]
+ *                allow-credentials: true
+ *                maxAge: 1800
+ *   }
+ * </pre>
+ *
+ * enable设为true,但是configs未配置,将使用已下的默认配置:
+ * <pre class="code">
+ *   {@code
+ *      hsweb:
+ *        cors:
+ *          enable: true
+ *          configs:
+ *            - /**:
+ *                allowed-headers: "*"
+ *                allowed-methods: ["GET", "POST", "HEAD"]
+ *                allowed-origins: "*"
+ *                allow-credentials: true
+ *                maxAge: 1800
+ *   }
+ * </pre>
+ *
+ * <p>
+ * <b>注意:</b>
+ * 配置文件中对象的属性名在 SpringBoot 2.x 版本开始不在支持特殊字符,会将特殊字符过滤掉,
+ * 仅支持{@code [A-Za-z0-9\-\_]},具体细节请查看{@code ConfigurationPropertyName}类的{@code adapt}方法
  *
  * @author zhouhao
+ * @author Jia
  * @since 1.0
  */
 @Configuration
 @ConditionalOnProperty(prefix = "hsweb.cors", name = "enable", havingValue = "true")
+@EnableConfigurationProperties(CorsProperties.class)
 public class CorsAutoConfiguration {
 
-    @ConfigurationProperties(prefix = "hsweb.cors")
-    @Bean
-    public CorsConfiguration corsConfiguration() {
-        return new CorsConfiguration();
-    }
+    /**
+     * 默认匹配全部
+     */
+    private static final String CORS_PATH_ALL = "/**";
 
     @Bean
-    public CorsFilter corsFilter(CorsConfiguration corsConfiguration) {
+    public CorsFilter corsFilter(CorsProperties corsProperties) {
         UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
-        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
+
+        Optional.ofNullable(corsProperties.getConfigs())
+                .orElse(Collections.singletonList(Collections.singletonMap(CORS_PATH_ALL,
+                        new CorsProperties.CorsConfiguration().applyPermitDefaultValues())))
+                .forEach((map) ->
+                        map.forEach((path, config) ->
+                                corsConfigurationSource.registerCorsConfiguration(path, buildConfiguration(config))
+                        )
+                );
+
         return new CorsFilter(corsConfigurationSource);
     }
+
+    private CorsConfiguration buildConfiguration(CorsProperties.CorsConfiguration config) {
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.setAllowedHeaders(config.getAllowedHeaders());
+        corsConfiguration.setAllowedMethods(config.getAllowedMethods());
+        corsConfiguration.setAllowedOrigins(config.getAllowedOrigins());
+        corsConfiguration.setAllowCredentials(config.getAllowCredentials());
+        corsConfiguration.setExposedHeaders(config.getExposedHeaders());
+        corsConfiguration.setMaxAge(config.getMaxAge());
+
+        return corsConfiguration;
+    }
 }

+ 85 - 0
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/CorsProperties.java

@@ -0,0 +1,85 @@
+package org.hswebframework.web.starter;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.cors.CorsConfiguration;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+@ConfigurationProperties(prefix = "hsweb.cors"/*, ignoreInvalidFields = true*/)
+public class CorsProperties {
+
+    @Getter
+    @Setter
+    private List<Map<String, CorsConfiguration>> configs;
+
+    @Getter
+    @Setter
+    @ToString
+    public static class CorsConfiguration {
+
+        /**
+         * Wildcard representing <em>all</em> origins, methods, or headers.
+         */
+        public static final String ALL = "*";
+
+        private List<String> allowedOrigins;
+
+        private List<String> allowedMethods;
+
+        private List<String> allowedHeaders;
+
+        private List<String> exposedHeaders;
+
+        private Boolean allowCredentials;
+
+        private Long maxAge;
+
+        CorsConfiguration applyPermitDefaultValues() {
+            if (this.allowedOrigins == null) {
+                this.addAllowedOrigin();
+            }
+            if (this.allowedMethods == null) {
+                this.setAllowedMethods(Arrays.asList(
+                        HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name()));
+            }
+            if (this.allowedHeaders == null) {
+                this.addAllowedHeader();
+            }
+            if (this.allowCredentials == null) {
+                this.setAllowCredentials(true);
+            }
+            if (this.maxAge == null) {
+                this.setMaxAge(1800L);
+            }
+            return this;
+        }
+
+        /**
+         * Add an origin to allow.
+         */
+        void addAllowedOrigin() {
+            if (this.allowedOrigins == null) {
+                this.allowedOrigins = new ArrayList<>(4);
+            }
+            this.allowedOrigins.add(CorsConfiguration.ALL);
+        }
+
+        /**
+         * Add an actual request header to allow.
+         */
+        void addAllowedHeader() {
+            if (this.allowedHeaders == null) {
+                this.allowedHeaders = new ArrayList<>(4);
+            }
+            this.allowedHeaders.add(CorsConfiguration.ALL);
+        }
+    }
+
+}

+ 2 - 2
hsweb-starter/hsweb-spring-boot-starter/src/main/java/org/hswebframework/web/starter/init/simple/SimpleDependencyInstaller.java

@@ -48,7 +48,7 @@ public class SimpleDependencyInstaller implements DependencyInstaller {
 
     public void doUnInstall(Map<String, Object> context) {
         if (unInstaller != null) {
-            installer.execute(context);
+            unInstaller.execute(context);
         }
     }
 
@@ -56,7 +56,7 @@ public class SimpleDependencyInstaller implements DependencyInstaller {
         SimpleDependencyUpgrader simpleDependencyUpgrader =
                 new SimpleDependencyUpgrader(installed, dependency, context);
         context.put("upgrader", simpleDependencyUpgrader);
-        if (unInstaller != null) {
+        if (upgrader != null) {
             upgrader.execute(context);
         }
     }

+ 3 - 3
hsweb-starter/hsweb-spring-boot-starter/src/test/resources/hsweb-starter.js

@@ -30,19 +30,19 @@ var versions = [
     {
         version: "3.0.0",
         upgrade: function (context) {
-            java.lang.System.out.println("更新到3.0.2了");
+            java.lang.System.out.println("更新到3.0.0了");
         }
     },
     {
         version: "3.0.1",
         upgrade: function (context) {
-            java.lang.System.out.println("更新到3.0.2了");
+            java.lang.System.out.println("更新到3.0.1了");
         }
     },
     {
         version: "3.0.2",
         upgrade: function (context) {
-            java.lang.System.out.println("更新到3.0.1了");
+            java.lang.System.out.println("更新到3.0.2了");
         }
     }
 ];

+ 1 - 1
hsweb-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-local/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-local/src/main/resources/hsweb-module.json

@@ -1,7 +1,7 @@
 {
   "groupId": "${project.groupId}",
   "artifactId": "${project.artifactId}",
-  "path": "hsweb-system/hsweb-system-authorization",
+  "path": "hsweb-system/hsweb-system-authorization/hsweb-system-authorization-local",
   "gitCommitHash": "${git.commit.hash}",
   "gitRepository": "http://github.com/hs-web/hsweb-framework",
   "version": "${project.version}",

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-starter/pom.xml

@@ -22,7 +22,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 9 - 2
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/pom.xml

@@ -5,13 +5,20 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>hsweb-system-authorization-web</artifactId>
     <description>业务模块-权限管理WEB API模块</description>
-
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
     <dependencies>
         <dependency>
             <groupId>javax.servlet</groupId>

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/src/main/java/org/hswebframework/web/authorization/controller/UserSettingController.java

@@ -39,7 +39,7 @@ public class UserSettingController {
                                                   @PathVariable String id) {
         UserSettingEntity entity = userSettingService.selectByUser(authentication.getUser().getId(), key, id);
         if (entity != null && entity.hasPermission(R, RW)) {
-            return ResponseMessage.ok();
+            return ResponseMessage.ok(entity);
         }
         return ResponseMessage.ok();
     }

+ 9 - 0
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web/src/main/resources/hsweb-module.json

@@ -0,0 +1,9 @@
+{
+  "groupId": "${project.groupId}",
+  "artifactId": "${project.artifactId}",
+  "path": "hsweb-system/hsweb-system-authorization/hsweb-system-authorization-web",
+  "gitCommitHash": "${git.commit.hash}",
+  "gitRepository": "http://github.com/hs-web/hsweb-framework",
+  "version": "${project.version}",
+  "comment": "权限管理Web层"
+}

+ 1 - 1
hsweb-system/hsweb-system-authorization/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-config/hsweb-system-config-api/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-system-config</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-system/hsweb-system-config/hsweb-system-config-local/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-system-config</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-system/hsweb-system-config/hsweb-system-config-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-config</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-system/hsweb-system-config/hsweb-system-config-web/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-system-config</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-system/hsweb-system-config/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-dashboard</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-local/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-dashboard</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-dashboard</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-dashboard/hsweb-system-dashboard-web/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-dashboard</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-dashboard/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-database-manager</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 9 - 2
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/pom.xml

@@ -5,12 +5,19 @@
     <parent>
         <artifactId>hsweb-system-database-manager</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>3.0.6</version>
+        <version>3.0.7</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>hsweb-system-database-manager-local</artifactId>
-
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+    </build>
     <dependencies>
         <dependency>
             <groupId>org.hswebframework.web</groupId>

+ 49 - 55
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/src/main/java/org/hswebframework/web/datasource/manager/simple/DefaultLocalTransactionExecutor.java

@@ -1,5 +1,6 @@
 package org.hswebframework.web.datasource.manager.simple;
 
+import lombok.SneakyThrows;
 import org.hswebframework.ezorm.rdb.executor.SqlExecutor;
 import org.hswebframework.web.database.manager.SqlExecuteRequest;
 import org.hswebframework.web.database.manager.SqlExecuteResult;
@@ -16,9 +17,7 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
@@ -31,7 +30,7 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    private Queue<Execution> executionQueue = new LinkedList<>();
+    private BlockingQueue<Execution> executionQueue = new LinkedBlockingQueue<>();
 
     private SqlExecutor sqlExecutor;
 
@@ -51,9 +50,6 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
 
     private volatile boolean running = false;
 
-    /* 线程循环开始等待sql进入的时候执行一次,sql进入的时候执行一次,然后唤醒线程开始执行sql */
-    private CyclicBarrier waitToReady = new CyclicBarrier(2);
-
     private CountDownLatch waitClose = new CountDownLatch(1);
 
     public DefaultLocalTransactionExecutor(SqlExecutor sqlExecutor, String transactionId, String datasourceId, TransactionTemplate transactionTemplate) {
@@ -82,11 +78,8 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
 
     protected void waitToClose() {
         try {
+            executionQueue.add(new NullExecution());
             logger.debug("wait transaction {} close", transactionId);
-            if (!running) {
-                //先唤醒执行,继续执行任务
-                waitToReady.await();
-            }
             //等待执行结束
             waitClose.await();
         } catch (Exception e) {
@@ -135,14 +128,20 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
             }
             while (!shutdown) {
                 logger.debug("wait sql execute request {}", transactionId);
+                Execution execution;
                 if (transactionTemplate.getTimeout() > 0) {
-                    waitToReady.await(transactionTemplate.getTimeout(), TimeUnit.MILLISECONDS);//等待有新的sql进来
+                    execution = executionQueue.poll(transactionTemplate.getTimeout(), TimeUnit.MILLISECONDS);//等待有新的sql进来
+                    if (execution == null) {
+                        throw new TimeoutException("事务[" + transactionId + "]超时");
+                    }
                 } else {
-                    waitToReady.await();
+                    execution = executionQueue.take();
+                }
+                if (execution instanceof NullExecution) {
+                    continue;
                 }
-                waitToReady.reset();//重置,下一次循环继续等待
                 //执行sql
-                doExecute();
+                doExecute(execution);
             }
         } catch (Exception e) {
             tryRollback();//回滚
@@ -164,41 +163,38 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
         }
     }
 
-    protected void doExecute() {
-        Execution execution;
-        while ((execution = executionQueue.poll()) != null) {
-            Execution finalE = execution;
-            running = true;
-            logger.debug("start execute sql {}", transactionId);
-            try {
-                List<SqlExecuteResult> requests = execution.request.getSql()
-                        .stream()
-                        .map(sqlInfo -> {
-                            try {
-                                if (finalE.datasourceId != null) {
-                                    DataSourceHolder.switcher().use(finalE.datasourceId);
-                                } else {
-                                    DataSourceHolder.switcher().useDefault();
-                                }
-                                //执行sql
-                                return sqlRequestExecutor.apply(sqlExecutor, sqlInfo);
-                            } catch (Exception e) {
-                                return SqlExecuteResult.builder()
-                                        .result(e.getMessage())
-                                        .sqlInfo(sqlInfo)
-                                        .success(false)
-                                        .build();
+    @SneakyThrows
+    protected void doExecute(Execution execution) {
+        running = true;
+        logger.debug("start execute sql {}", transactionId);
+        try {
+            List<SqlExecuteResult> requests = execution.request.getSql()
+                    .stream()
+                    .map(sqlInfo -> {
+                        try {
+                            if (execution.datasourceId != null) {
+                                DataSourceHolder.switcher().use(execution.datasourceId);
+                            } else {
+                                DataSourceHolder.switcher().useDefault();
                             }
-                        })
-                        .collect(Collectors.toList());
-                //通过回调返回执行结果
-                execution.callback.accept(requests);
-            } catch (Exception e) {
-                execution.onError.accept(e);
-                return;
-            }
+                            //执行sql
+                            return sqlRequestExecutor.apply(sqlExecutor, sqlInfo);
+                        } catch (Exception e) {
+                            return SqlExecuteResult.builder()
+                                    .result(e.getMessage())
+                                    .sqlInfo(sqlInfo)
+                                    .success(false)
+                                    .build();
+                        }
+                    })
+                    .collect(Collectors.toList());
+            //通过回调返回执行结果
+            execution.callback.accept(requests);
+        } catch (Exception e) {
+            execution.onError.accept(e);
+        } finally {
+            running = false;
         }
-        running = false;
     }
 
     @Override
@@ -220,20 +216,18 @@ public class DefaultLocalTransactionExecutor implements TransactionExecutor {
             sqlExecuteResults.clear();
             countDownLatch.countDown();
         };
-        execution.onError = (e) -> {
-            countDownLatch.countDown();
-        };
+        execution.onError = (e) -> countDownLatch.countDown();
         logger.debug("submit sql execute job {}", transactionId);
         executionQueue.add(execution);
-        //当前没有在执行sql,说明现在正在等待新的sql进入,唤醒之
-        if (!running) {
-            waitToReady.await();
-        }
         //等待sql执行完毕
         countDownLatch.await();
         return results;
     }
 
+    private class NullExecution extends Execution {
+
+    }
+
     protected class Execution {
 
         protected String datasourceId;

+ 0 - 0
hsweb-system/hsweb-system-database-manager/hsweb-system-database-manager-local/src/main/resources/hsweb-module.json


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác