From 5db1e87200fbc794b7e5247c28c5b3900ade246d Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Wed, 13 Oct 2021 14:13:24 +0800 Subject: [PATCH 001/416] 4.0.12 --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 2 +- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 6 +++--- 26 files changed, 28 insertions(+), 28 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index 474c3bf07..c934b6e02 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index 9f0520387..35782663a 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index ac8384abf..5d1eb4026 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index ee5932301..fffdb47e8 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index 2dfc46220..1f70cecc1 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index 70a5d4d87..b37cd8fae 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index 1aa8c684f..ee97725d6 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index 1e20dc9d8..47836eab9 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index 78403e73d..73284a906 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 6a0ad3521..582e86bbe 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index 441f96ea6..7c6708f52 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 568b37f01..094eb1d63 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index 1aa0e2ee7..9ae233df8 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index 66a48e7a8..4ff665b7b 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index 556da7658..d7350b1e1 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index e7b01fc7e..d3cad29a6 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index 63578e39f..045cde927 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index c37e11d05..76bde2742 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index e6052a036..132061de4 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index 0e9365faa..db9216b92 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index dfc0507ad..70349ffef 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index 68192e546..8cf3b2d53 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index e28a65878..6bc56f838 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index 24f3d9977..cf4381e7e 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index 17f87c9a6..fa4e74ef1 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12-SNAPSHOT + 4.0.12 ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 4f07bd296..fc884dabc 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.12-SNAPSHOT + 4.0.12 hsweb-starter hsweb-core @@ -90,12 +90,12 @@ 3.2.2 1.6.12 - 4.0.12-SNAPSHOT + 4.0.12 3.0.2 3.0.2 2.7.0 - Arabba-RELEASE + Arabba-SR10 From f6938e6f65c7a8591c84cdf831af363fd17ed391 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Thu, 28 Oct 2021 08:58:57 +0800 Subject: [PATCH 002/416] 4.0.13-SNAPSHOT --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 2 +- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index c934b6e02..260044351 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index 35782663a..4cee3010c 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index 5d1eb4026..b1ed31100 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index fffdb47e8..ca288ae27 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index 1f70cecc1..f273b989f 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index b37cd8fae..2f03314e7 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index ee97725d6..49956e019 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index 47836eab9..b48abe970 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index 73284a906..256a58bd1 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 582e86bbe..8e7394a11 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index 7c6708f52..7add8016e 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 094eb1d63..6291e1e5b 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index 9ae233df8..fa7a74e6e 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index 4ff665b7b..f10f0f041 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index d7350b1e1..b264011c3 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index d3cad29a6..a1417bb87 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index 045cde927..607ebd984 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 76bde2742..1b75183c0 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index 132061de4..459e8e1ed 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index db9216b92..db9703dc3 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index 70349ffef..fe06e8d32 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index 8cf3b2d53..5d42aacb4 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index 6bc56f838..9b98e9b81 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index cf4381e7e..041afbbf9 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index fa4e74ef1..d28ee529b 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.12 + 4.0.13-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index fc884dabc..870043527 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.12 + 4.0.13-SNAPSHOT hsweb-starter hsweb-core From c9af0310dbdca0066c7a6c47f185581dd20b1b28 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Thu, 28 Oct 2021 09:02:51 +0800 Subject: [PATCH 003/416] =?UTF-8?q?=E4=BC=98=E5=8C=96id=20generator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/id/IDGenerator.java | 15 ++--- .../hswebframework/web/utils/DigestUtils.java | 60 +++++++++++++++++++ 2 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java diff --git a/hsweb-core/src/main/java/org/hswebframework/web/id/IDGenerator.java b/hsweb-core/src/main/java/org/hswebframework/web/id/IDGenerator.java index bbb88dd8e..0b8dca66c 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/id/IDGenerator.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/id/IDGenerator.java @@ -19,6 +19,7 @@ package org.hswebframework.web.id; import org.hswebframework.utils.RandomUtil; +import org.hswebframework.web.utils.DigestUtils; import java.math.BigInteger; import java.security.MessageDigest; @@ -41,7 +42,7 @@ public interface IDGenerator { @SuppressWarnings("unchecked") static IDGenerator getNullGenerator() { - return (IDGenerator) NULL; + return (IDGenerator) NULL; } /** @@ -55,17 +56,9 @@ static IDGenerator getNullGenerator() { IDGenerator RANDOM = RandomUtil::randomChar; /** - * md5(uuid()+random()) + * md5(uuid()) */ - IDGenerator MD5 = () -> { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(UUID.generate().concat(RandomUtil.randomChar()).getBytes()); - return new BigInteger(1, md.digest()).toString(16); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - }; + IDGenerator MD5 = () -> DigestUtils.md5Hex(UUID.generate()); /** * 雪花算法 diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java new file mode 100644 index 000000000..214443292 --- /dev/null +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java @@ -0,0 +1,60 @@ +package org.hswebframework.web.utils; + +import org.apache.commons.codec.binary.Hex; + +import java.security.MessageDigest; + +public class DigestUtils { + + public static final MessageDigest md5 = org.apache.commons.codec.digest.DigestUtils.getMd5Digest(); + public static final MessageDigest sha256 = org.apache.commons.codec.digest.DigestUtils.getSha256Digest(); + public static final MessageDigest sha1 = org.apache.commons.codec.digest.DigestUtils.getSha1Digest(); + + public static byte[] md5(byte[] data) { + return org.apache.commons.codec.digest.DigestUtils.digest(md5, data); + } + + public static byte[] md5(String str) { + return md5(str.getBytes()); + } + + public static String md5Hex(String str) { + return Hex.encodeHexString(md5(str.getBytes())); + } + + public static byte[] sha256(byte[] data) { + return org.apache.commons.codec.digest.DigestUtils.digest(sha256, data); + } + + public static byte[] sha256(String str) { + return sha256(str.getBytes()); + } + + public static String sha256Hex(String str) { + return Hex.encodeHexString(sha256(str.getBytes())); + } + + public static byte[] sha1(byte[] data) { + return org.apache.commons.codec.digest.DigestUtils.digest(sha1, data); + } + + public static byte[] sha1(String str) { + return sha1(str.getBytes()); + } + + public static String sha1Hex(String str) { + return Hex.encodeHexString(sha1(str.getBytes())); + } + + public static byte[] digest(MessageDigest digest, byte[] data) { + return org.apache.commons.codec.digest.DigestUtils.digest(digest, data); + } + + public static byte[] digest(MessageDigest digest, String str) { + return digest(digest, str.getBytes()); + } + + public static String digestHex(MessageDigest digest, String str) { + return Hex.encodeHexString(digest(digest, str)); + } +} From 08bdc14973546374e62ca653ffad229148aa7ac2 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Thu, 28 Oct 2021 09:09:51 +0800 Subject: [PATCH 004/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0UserStateChangedEvent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/event/UserStateChangedEvent.java | 20 +++++++++++++++++++ .../service/DefaultReactiveUserService.java | 15 ++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserStateChangedEvent.java diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserStateChangedEvent.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserStateChangedEvent.java new file mode 100644 index 000000000..35c08bd31 --- /dev/null +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserStateChangedEvent.java @@ -0,0 +1,20 @@ +package org.hswebframework.web.system.authorization.api.event; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.hswebframework.web.event.DefaultAsyncEvent; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor(staticName = "of") +public class UserStateChangedEvent extends DefaultAsyncEvent { + + private List userIdList; + + private byte state; + +} diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java index f3580edc5..2f771c7a3 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java @@ -13,10 +13,7 @@ import org.hswebframework.web.system.authorization.api.PasswordValidator; import org.hswebframework.web.system.authorization.api.UsernameValidator; import org.hswebframework.web.system.authorization.api.entity.UserEntity; -import org.hswebframework.web.system.authorization.api.event.ClearUserAuthorizationCacheEvent; -import org.hswebframework.web.system.authorization.api.event.UserCreatedEvent; -import org.hswebframework.web.system.authorization.api.event.UserDeletedEvent; -import org.hswebframework.web.system.authorization.api.event.UserModifiedEvent; +import org.hswebframework.web.system.authorization.api.event.*; import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService; import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Autowired; @@ -113,7 +110,7 @@ protected Mono doUpdate(UserEntity userEntity) { .execute() .flatMap(__ -> new UserModifiedEvent(userEntity, passwordChanged).publish(eventPublisher)) .thenReturn(userEntity) - .doOnNext(e->{ + .doOnNext(e -> { eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of(e.getId())); }); }); @@ -160,7 +157,13 @@ public Mono changeState(Publisher userId, byte state) { .set(UserEntity::getStatus, state) .where() .in(UserEntity::getId, list) - .execute()) + .execute() + .flatMap(i -> UserStateChangedEvent + .of(list, state) + .publish(eventPublisher) + .thenReturn(i) + ) + ) .defaultIfEmpty(0); } From cb6df631d538bca03170b3dfeede77d5d1c57e51 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Thu, 28 Oct 2021 10:20:44 +0800 Subject: [PATCH 005/416] =?UTF-8?q?=E7=A6=81=E7=94=A8=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E8=B8=A2=E5=87=BA=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...AuthorizationServiceAutoConfiguration.java | 6 +++ .../RemoveUserTokenWhenUserDisabled.java | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/RemoveUserTokenWhenUserDisabled.java diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java index 92c3ad910..a8f5e2f95 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java @@ -4,6 +4,7 @@ import org.hswebframework.web.authorization.ReactiveAuthenticationInitializeService; import org.hswebframework.web.authorization.ReactiveAuthenticationManagerProvider; import org.hswebframework.web.authorization.simple.DefaultAuthorizationAutoConfiguration; +import org.hswebframework.web.authorization.token.UserTokenManager; import org.hswebframework.web.system.authorization.api.UserDimensionProvider; import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService; import org.hswebframework.web.system.authorization.defaults.service.*; @@ -69,6 +70,11 @@ public DefaultPermissionService defaultPermissionService() { return new DefaultPermissionService(); } + @Bean + @ConditionalOnBean(UserTokenManager.class) + public RemoveUserTokenWhenUserDisabled removeUserTokenWhenUserDisabled(UserTokenManager tokenManager){ + return new RemoveUserTokenWhenUserDisabled(tokenManager); + } } @Bean diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/RemoveUserTokenWhenUserDisabled.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/RemoveUserTokenWhenUserDisabled.java new file mode 100644 index 000000000..80780d087 --- /dev/null +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/RemoveUserTokenWhenUserDisabled.java @@ -0,0 +1,38 @@ +package org.hswebframework.web.system.authorization.defaults.service; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.hswebframework.web.authorization.token.UserTokenManager; +import org.hswebframework.web.system.authorization.api.event.UserModifiedEvent; +import org.hswebframework.web.system.authorization.api.event.UserStateChangedEvent; +import org.springframework.context.event.EventListener; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@AllArgsConstructor +@Slf4j +public class RemoveUserTokenWhenUserDisabled { + + private final UserTokenManager userTokenManager; + + @EventListener + public void handleStateChangeEvent(UserModifiedEvent event) { + if (event.getUserEntity().getStatus() != null && event.getUserEntity().getStatus() != 1) { + event.async( + Mono.just(event.getUserEntity().getId()) + .flatMap(userTokenManager::signOutByUserId) + ); + } + } + + @EventListener + public void handleStateChangeEvent(UserStateChangedEvent event) { + if (event.getState() != 1) { + event.async( + Flux.fromIterable(event.getUserIdList()) + .flatMap(userTokenManager::signOutByUserId) + ); + } + } + +} From 79e85859b78bd8dd34e28bbf46a1b9c7ecfd327e Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Tue, 2 Nov 2021 15:22:01 +0800 Subject: [PATCH 006/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dpath=E4=B8=BAnull?= =?UTF-8?q?=E6=97=B6=E4=BC=9A=E6=9F=A5=E8=AF=A2=E5=87=BA=E6=89=80=E6=9C=89?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReactiveTreeSortEntityService.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java index 9b49472c1..84839cacc 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java @@ -1,6 +1,5 @@ package org.hswebframework.web.crud.service; -import org.apache.commons.collections4.CollectionUtils; import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult; import org.hswebframework.ezorm.rdb.operator.dml.Terms; import org.hswebframework.utils.RandomUtil; @@ -13,10 +12,8 @@ import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import reactor.util.function.Tuple3; import java.util.*; -import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -52,7 +49,10 @@ default Mono> queryIncludeChildrenTree(QueryParamEntity paramEntity) { default Flux queryIncludeChildren(Collection idList) { return findById(idList) - .flatMap(e -> createQuery() + .flatMap(e -> StringUtils + .isEmpty(e.getPath()) + ? Mono.just(e) + : createQuery() .where() .like$("path", e.getPath()) .fetch()); @@ -60,7 +60,10 @@ default Flux queryIncludeChildren(Collection idList) { default Flux queryIncludeParent(Collection idList) { return findById(idList) - .flatMap(e -> createQuery() + .flatMap(e -> StringUtils + .isEmpty(e.getPath()) + ? Mono.just(e) + : createQuery() .where() .accept(Terms.Like.reversal("path", e.getPath(), false, true)) .notEmpty("path") @@ -70,7 +73,10 @@ default Flux queryIncludeParent(Collection idList) { default Flux queryIncludeChildren(QueryParamEntity queryParam) { return query(queryParam) - .flatMap(e -> createQuery() + .flatMap(e -> StringUtils + .isEmpty(e.getPath()) + ? Mono.just(e) + : createQuery() .where() .like$("path", e.getPath()) .fetch()); @@ -193,9 +199,9 @@ default Flux tryRefactorPath(Flux stream) { K parentId = old != null ? old.getParentId() : data.getParentId(); E oldParent = parentId == null ? null : oldMap.get(parentId); if (old != null) { - K newParentId= data.getParentId(); + K newParentId = data.getParentId(); //父节点发生变化,更新所有子节点path - if (!Objects.equals(parentId,newParentId)) { + if (!Objects.equals(parentId, newParentId)) { List> jobs = new ArrayList<>(); Consumer childConsumer = child -> { //更新了父节点,但是同时也传入的对应的子节点 @@ -237,14 +243,14 @@ default Flux tryRefactorPath(Flux stream) { pathRefactor.accept(oldParent); } else if (parentId != null) { return findById(parentId) - .switchIfEmpty(Mono.fromRunnable(() ->{ + .switchIfEmpty(Mono.fromRunnable(() -> { data.setParentId(null); data.setLevel(1); data.setPath(old.getPath()); })) .doOnNext(pathRefactor) .thenReturn(data); - }else { + } else { data.setPath(old.getPath()); } From e867cca1a6d10a589fc578691479d57b467865bf Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Tue, 9 Nov 2021 12:17:05 +0800 Subject: [PATCH 007/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=B8=AD=E6=96=87=E6=9D=A1=E4=BB=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/crud/entity/TermExpressionParser.java | 9 ++++++--- .../crud/entity/TermExpressionParserTest.java | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TermExpressionParser.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TermExpressionParser.java index af76310f1..7000e3c46 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TermExpressionParser.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TermExpressionParser.java @@ -9,6 +9,8 @@ import org.hswebframework.ezorm.core.param.TermType; import org.hswebframework.web.api.crud.entity.QueryParamEntity; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -24,12 +26,13 @@ */ public class TermExpressionParser { - static final URLCodec urlCodec = new URLCodec(); - @SneakyThrows public static List parse(String expression) { - expression = urlCodec.decode(expression); + try { + expression = URLDecoder.decode(expression, "utf-8"); + }catch (Throwable ignore){ + } Query conditional = QueryParamEntity.newQuery(); NestConditional nest = null; diff --git a/hsweb-commons/hsweb-commons-api/src/test/java/org/hswebframework/web/api/crud/entity/TermExpressionParserTest.java b/hsweb-commons/hsweb-commons-api/src/test/java/org/hswebframework/web/api/crud/entity/TermExpressionParserTest.java index a04ea1cd0..1d0b883b2 100644 --- a/hsweb-commons/hsweb-commons-api/src/test/java/org/hswebframework/web/api/crud/entity/TermExpressionParserTest.java +++ b/hsweb-commons/hsweb-commons-api/src/test/java/org/hswebframework/web/api/crud/entity/TermExpressionParserTest.java @@ -23,6 +23,25 @@ public void testUrl(){ assertEquals(terms.get(1).getValue(), "test"); } + + @Test + public void testChinese() { + { + List terms = TermExpressionParser.parse("name = 我"); + + assertEquals(terms.get(0).getTermType(), TermType.eq); + assertEquals(terms.get(0).getValue(),"我"); + + } + + { + List terms = TermExpressionParser.parse("name like %我%"); + + assertEquals(terms.get(0).getTermType(), TermType.like); + assertEquals(terms.get(0).getValue(),"%我%"); + + } + } @Test public void test() { { From 88d4fcf8dc6bc8b9d63e5f199f6968355ee4e7ee Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Tue, 9 Nov 2021 12:17:31 +0800 Subject: [PATCH 008/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=8E=B7=E5=8F=96map=E4=B8=AD=E5=8C=85?= =?UTF-8?q?=E5=90=AB.=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/hswebframework/web/utils/ExpressionUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/ExpressionUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/ExpressionUtils.java index de2af2fb1..5e247667d 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/utils/ExpressionUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/ExpressionUtils.java @@ -3,7 +3,6 @@ import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.BeanUtilsBean2; -import org.apache.commons.codec.digest.DigestUtils; import org.hswebframework.expands.script.engine.DynamicScriptEngine; import org.hswebframework.expands.script.engine.DynamicScriptEngineFactory; import org.hswebframework.expands.script.engine.ExecuteResult; @@ -91,7 +90,10 @@ public static String analytical(String expression, Map vars, Str if (StringUtils.isEmpty(var)) { return ""; } - + Object val = vars.get(var); + if (val != null) { + return String.valueOf(val); + } if ("spel".equalsIgnoreCase(language) && !var.contains("#")) { try { Object fast = BeanUtilsBean2.getInstance().getPropertyUtils().getProperty(vars, var); From e831c1d227b3eb0a214f7db2dea3e072f6016313 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Wed, 17 Nov 2021 11:58:22 +0800 Subject: [PATCH 009/416] #104 upgrade javassist 3.28.0-GA --- hsweb-core/pom.xml | 2 +- .../src/main/java/org/hswebframework/web/proxy/Proxy.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 8e7394a11..1e26bc252 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -18,7 +18,7 @@ org.javassist javassist - 3.22.0-GA + 3.28.0-GA com.fasterxml.jackson.core diff --git a/hsweb-core/src/main/java/org/hswebframework/web/proxy/Proxy.java b/hsweb-core/src/main/java/org/hswebframework/web/proxy/Proxy.java index cf6c1b3d0..f6a453e0c 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/proxy/Proxy.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/proxy/Proxy.java @@ -153,7 +153,7 @@ public I newInstance() { @SneakyThrows public Class getTargetClass() { if (targetClass == null) { - targetClass = ctClass.toClass(ClassUtils.getDefaultClassLoader(), null); + targetClass = (Class)ctClass.toClass(ClassUtils.getDefaultClassLoader(), null); } return targetClass; } From fdc16aeef3708c3f77f24bd94f2073a6bedaec4f Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Fri, 26 Nov 2021 11:49:44 +0800 Subject: [PATCH 010/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/web/CommonErrorControllerAdvice.java | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java index 17b6140a9..c1556f9c7 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java @@ -16,7 +16,9 @@ import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; @@ -95,39 +97,44 @@ public Mono>> handleException(C @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) + @SuppressWarnings("all") public Mono>> handleException(BindException e) { - return handleException(new ValidationException(e.getMessage(), e - .getBindingResult().getAllErrors() - .stream() - .filter(FieldError.class::isInstance) - .map(FieldError.class::cast) - .map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null)) - .collect(Collectors.toList()))); + return handleBindingResult(e.getBindingResult()); } @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) + @SuppressWarnings("all") public Mono>> handleException(WebExchangeBindException e) { - return handleException(new ValidationException(e.getMessage(), e - .getBindingResult().getAllErrors() - .stream() - .filter(FieldError.class::isInstance) - .map(FieldError.class::cast) - .map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null)) - .collect(Collectors.toList()))); + return handleBindingResult(e.getBindingResult()); } @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) + @SuppressWarnings("all") public Mono>> handleException(MethodArgumentNotValidException e) { - return handleException(new ValidationException(e.getMessage(), e - .getBindingResult().getAllErrors() + return handleBindingResult(e.getBindingResult()); + } + + private Mono>> handleBindingResult(BindingResult result) { + String message; + FieldError fieldError = result.getFieldError(); + ObjectError globalError = result.getGlobalError(); + + if (null != fieldError) { + message = fieldError.getDefaultMessage(); + } else if (null != globalError) { + message = globalError.getDefaultMessage(); + } else { + message = CodeConstants.Error.illegal_argument; + } + List details = result + .getFieldErrors() .stream() - .filter(FieldError.class::isInstance) - .map(FieldError.class::cast) .map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null)) - .collect(Collectors.toList()))); + .collect(Collectors.toList()); + return handleException(new ValidationException(message, details)); } @ExceptionHandler From f7ab9f922616b0deadefa3d04773fb67048f5563 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Mon, 6 Dec 2021 17:54:15 +0800 Subject: [PATCH 011/416] =?UTF-8?q?=E4=BC=98=E5=8C=96FastBeanCopier?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hsweb-core/pom.xml | 11 ++ .../web/bean/ClassDescription.java | 27 ++++ .../web/bean/ClassDescriptions.java | 16 +++ .../web/bean/FastBeanCopier.java | 119 +++++++++++------- 4 files changed, 125 insertions(+), 48 deletions(-) create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 1e26bc252..4dfe92bb4 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -106,5 +106,16 @@ reactor-extra + + com.google.guava + guava + + + + jctools-core + org.jctools + 2.1.2 + + \ No newline at end of file diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java new file mode 100644 index 000000000..9de02b6b0 --- /dev/null +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java @@ -0,0 +1,27 @@ +package org.hswebframework.web.bean; + +import lombok.Getter; +import org.hswebframework.web.dict.EnumDict; + +import java.util.Collection; + +@Getter +public class ClassDescription { + private final Class type; + + private final boolean collectionType; + private final boolean arrayType; + private final boolean enumType; + private final boolean enumDict; + private final int fieldSize; + + public ClassDescription(Class type) { + this.type = type; + collectionType = Collection.class.isAssignableFrom(type); + enumDict = EnumDict.class.isAssignableFrom(type); + arrayType = type.isArray(); + enumType = type.isEnum(); + fieldSize = type.getDeclaredFields().length; + } + +} diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java new file mode 100644 index 000000000..c5af73b58 --- /dev/null +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java @@ -0,0 +1,16 @@ +package org.hswebframework.web.bean; + +import org.jctools.maps.NonBlockingHashMap; + +import java.util.Map; + +public class ClassDescriptions { + + private static final Map, ClassDescription> CACHE = new NonBlockingHashMap<>(); + + public static ClassDescription getDescription(Class type) { + return CACHE.computeIfAbsent(type, ClassDescription::new); + } + + +} diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java index e00ba28d4..066da714a 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java @@ -1,14 +1,17 @@ package org.hswebframework.web.bean; +import com.google.common.collect.Maps; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.BeanUtilsBean; +import org.apache.commons.beanutils.ConvertUtilsBean; import org.apache.commons.beanutils.PropertyUtilsBean; import org.hswebframework.utils.time.DateFormatter; import org.hswebframework.web.dict.EnumDict; import org.hswebframework.web.proxy.Proxy; +import org.jctools.maps.NonBlockingHashMap; import org.springframework.core.ResolvableType; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -30,10 +33,12 @@ */ @Slf4j public final class FastBeanCopier { - private static final Map CACHE = new ConcurrentHashMap<>(); + private static final Map CACHE = new NonBlockingHashMap<>(); private static final PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance().getPropertyUtils(); + private static final ConvertUtilsBean convertUtils = BeanUtilsBean.getInstance().getConvertUtils(); + private static final Map, Class> wrapperClassMapping = new HashMap<>(); @SuppressWarnings("all") @@ -123,7 +128,7 @@ static Class getUserClass(Object object) { Class type = ClassUtils.getUserClass(object); if (java.lang.reflect.Proxy.isProxyClass(type)) { - Class[] interfaces= type.getInterfaces(); + Class[] interfaces = type.getInterfaces(); return interfaces[0]; } @@ -167,8 +172,8 @@ public static Copier createCopier(Class source, Class target) { "\n}"; try { return Proxy.create(Copier.class) - .addMethod(method) - .newInstance(); + .addMethod(method) + .newInstance(); } catch (Exception e) { log.error("创建bean copy 代理对象失败:\n{}", method, e); throw new UnsupportedOperationException(e.getMessage(), e); @@ -178,20 +183,22 @@ public static Copier createCopier(Class source, Class target) { private static Map createProperty(Class type) { List fieldNames = Arrays.stream(type.getDeclaredFields()) - .map(Field::getName).collect(Collectors.toList()); + .map(Field::getName).collect(Collectors.toList()); return Stream.of(propertyUtils.getPropertyDescriptors(type)) - .filter(property -> !property.getName().equals("class") && property.getReadMethod() != null && property.getWriteMethod() != null) - .map(BeanClassProperty::new) - //让字段有序 - .sorted(Comparator.comparing(property -> fieldNames.indexOf(property.name))) - .collect(Collectors.toMap(ClassProperty::getName, Function.identity(), (k, k2) -> k, LinkedHashMap::new)); + .filter(property -> !property + .getName() + .equals("class") && property.getReadMethod() != null && property.getWriteMethod() != null) + .map(BeanClassProperty::new) + //让字段有序 + .sorted(Comparator.comparing(property -> fieldNames.indexOf(property.name))) + .collect(Collectors.toMap(ClassProperty::getName, Function.identity(), (k, k2) -> k, LinkedHashMap::new)); } private static Map createMapProperty(Map template) { return template.values().stream().map(classProperty -> new MapClassProperty(classProperty.name)) - .collect(Collectors.toMap(ClassProperty::getName, Function.identity(), (k, k2) -> k, LinkedHashMap::new)); + .collect(Collectors.toMap(ClassProperty::getName, Function.identity(), (k, k2) -> k, LinkedHashMap::new)); } private static String createCopierCode(Class source, Class target) { @@ -231,13 +238,16 @@ private static String createCopierCode(Class source, Class target) { code.append("if($$__source.").append(sourceProperty.getReadMethod()).append("!=null){\n"); } code.append(targetProperty.generateVar(targetProperty.getName())).append("=") - .append(sourceProperty.generateGetter(target, targetProperty.getType())) - .append(";\n"); + .append(sourceProperty.generateGetter(target, targetProperty.getType())) + .append(";\n"); if (!targetProperty.isPrimitive()) { code.append("\tif(").append(sourceProperty.getName()).append("!=null){\n"); } - code.append("\t$$__target.").append(targetProperty.generateSetter(targetProperty.getType(), sourceProperty.getName())).append(";\n"); + code + .append("\t$$__target.") + .append(targetProperty.generateSetter(targetProperty.getType(), sourceProperty.getName())) + .append(";\n"); if (!targetProperty.isPrimitive()) { code.append("\t}\n"); } @@ -310,10 +320,10 @@ public boolean isWrapper(Class type) { protected Class getPrimitiveType(Class type) { return wrapperClassMapping.entrySet().stream() - .filter(entry -> entry.getValue() == type) - .map(Map.Entry::getKey) - .findFirst() - .orElse(null); + .filter(entry -> entry.getValue() == type) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); } protected Class getWrapperType() { @@ -334,11 +344,11 @@ public BiFunction, Class, String> createGetterFunction() { boolean hasGeneric = false; if (field != null) { String[] arr = Arrays.stream(ResolvableType.forField(field) - .getGenerics()) - .map(ResolvableType::getRawClass) - .filter(Objects::nonNull) - .map(t -> t.getName().concat(".class")) - .toArray(String[]::new); + .getGenerics()) + .map(ResolvableType::getRawClass) + .filter(Objects::nonNull) + .map(t -> t.getName().concat(".class")) + .toArray(String[]::new); if (arr.length > 0) { generic = "new Class[]{" + String.join(",", arr) + "}"; hasGeneric = true; @@ -365,11 +375,11 @@ public BiFunction, Class, String> createGetterFunction() { } else { //类型不一致,调用convert转换 convertCode.append("((").append(targetWrapperClass.getName()) - .append(")") - .append(convert) - .append(").") - .append(targetType.getName()) - .append("Value()"); + .append(")") + .append(convert) + .append(").") + .append(targetType.getName()) + .append("Value()"); } } else if (isPrimitive()) { @@ -377,25 +387,30 @@ public BiFunction, Class, String> createGetterFunction() { //源字段类型为基本数据类型,目标字段为包装器类型 if (targetIsWrapper) { convertCode.append(targetType.getName()) - .append(".valueOf(") - .append(getterCode) - .append(")"); + .append(".valueOf(") + .append(getterCode) + .append(")"); } else { convertCode.append("(").append(targetType.getName()) - .append(")(") - .append(convert) - .append(")"); + .append(")(") + .append(convert) + .append(")"); } } else { convertCode.append("(").append(getTypeName(targetType)) - .append(")(") - .append(convert) - .append(")"); + .append(")(") + .append(convert) + .append(")"); } } else { if (Cloneable.class.isAssignableFrom(targetType)) { try { - convertCode.append("(").append(getTypeName()).append(")").append(getterCode).append(".clone()"); + convertCode + .append("(") + .append(getTypeName()) + .append(")") + .append(getterCode) + .append(".clone()"); } catch (Exception e) { convertCode.append(getterCode); } @@ -499,7 +514,9 @@ public T convert(Object source, Class targetClass, Class[] genericType) { if (source == null) { return null; } - if (source.getClass().isEnum()) { + ClassDescription target = ClassDescriptions.getDescription(targetClass); + + if (target.isEnumType()) { if (source instanceof EnumDict) { Object val = (T) ((EnumDict) source).getValue(); if (targetClass.isInstance(val)) { @@ -555,8 +572,8 @@ public T convert(Object source, Class targetClass, Class[] genericType) { return (T) collection; } - if (targetClass.isEnum()) { - if (EnumDict.class.isAssignableFrom(targetClass)) { + if (target.isEnumType()){ + if (target.isEnumDict()) { String strVal = String.valueOf(source); Object val = EnumDict.find((Class) targetClass, e -> { @@ -567,10 +584,10 @@ public T convert(Object source, Class targetClass, Class[] genericType) { } return convert(val, targetClass, genericType); } - String strSource=String.valueOf(source); + String strSource = String.valueOf(source); for (T t : targetClass.getEnumConstants()) { if (((Enum) t).name().equalsIgnoreCase(strSource) - ||Objects.equals(String.valueOf(((Enum) t).ordinal()),strSource)) { + || Objects.equals(String.valueOf(((Enum) t).ordinal()), strSource)) { return t; } } @@ -579,21 +596,27 @@ public T convert(Object source, Class targetClass, Class[] genericType) { return null; } //转换为数组 - if (targetClass.isArray()) { + if (target.isArrayType()) { Class componentType = targetClass.getComponentType(); List val = convert(source, List.class, new Class[]{componentType}); return (T) val.toArray((Object[]) Array.newInstance(componentType, val.size())); } try { - org.apache.commons.beanutils.Converter converter = BeanUtilsBean - .getInstance() - .getConvertUtils() - .lookup(targetClass); + org.apache.commons.beanutils.Converter converter = convertUtils.lookup(targetClass); if (null != converter) { return converter.convert(targetClass, source); } + //快速复制map + if (targetClass == Map.class) { + if(source instanceof Map) { + return (T) new HashMap(((Map) source)); + } + ClassDescription sourType = ClassDescriptions.getDescription(source.getClass()); + return (T)copy(source, Maps.newHashMapWithExpectedSize(sourType.getFieldSize())); + } + return copy(source, beanFactory.newInstance(targetClass), this); } catch (Exception e) { log.warn("复制类型{}->{}失败", source, targetClass, e); From e199b29925c8789ab2ad8d4bc3b857d732cea790 Mon Sep 17 00:00:00 2001 From: zeje Date: Thu, 9 Dec 2021 18:59:12 +0800 Subject: [PATCH 012/416] Update RedisUserTokenManager.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 处理redis中Hash:user-token只增不减的bug --- .../web/authorization/token/redis/RedisUserTokenManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java index e890de127..a33b5fa3f 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java @@ -184,7 +184,7 @@ public Mono signOutByToken(String token) { return getByToken(token) .flatMap(t -> operations .delete(getTokenRedisKey(t.getToken())) - .then(userTokenMapping.remove(getUserRedisKey(t.getToken()), token)) + .then(userTokenMapping.remove(getUserRedisKey(t.getUserId()), token)) .then(onTokenRemoved(t)) ) .then(); From b881e4bbefb473840c9c5751151b67614b842548 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Fri, 10 Dec 2021 09:40:56 +0800 Subject: [PATCH 013/416] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=88=97=E9=95=BF?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/authorization/api/entity/DimensionUserEntity.java | 4 ++-- .../web/dictionary/entity/DictionaryEntity.java | 2 +- .../web/dictionary/entity/DictionaryItemEntity.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java index b4cb0256f..752361a18 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java @@ -34,7 +34,7 @@ public class DimensionUserEntity extends GenericEntity { private String dimensionTypeId; @Comment("维度ID") - @Column(name = "dimension_id", nullable = false, length = 32) + @Column(name = "dimension_id", nullable = false, length = 64) @Schema(description = "维度ID") private String dimensionId; @@ -45,7 +45,7 @@ public class DimensionUserEntity extends GenericEntity { private String dimensionName; @Comment("用户ID") - @Column(name = "user_id", nullable = false, length = 32) + @Column(name = "user_id", nullable = false, length = 64) @Schema(description = "用户ID") private String userId; diff --git a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java index 4dd1a001a..6b95b7e37 100644 --- a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java +++ b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java @@ -46,7 +46,7 @@ public class DictionaryEntity extends GenericEntity implements RecordCre @Schema(description = "字典名称") private String name; //分类 - @Column(length = 32, name = "classified") + @Column(length = 64, name = "classified") @Schema(description = "分类标识") private String classified; //说明 diff --git a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java index 09d417b23..ef74f9f2e 100644 --- a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java +++ b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java @@ -41,7 +41,7 @@ }) public class DictionaryItemEntity extends GenericTreeSortSupportEntity implements EnumDict { //字典id - @Column(name = "dict_id", length = 32, updatable = false, nullable = false) + @Column(name = "dict_id", length = 64, updatable = false, nullable = false) @Schema(description = "数据字典ID") private String dictId; //名称 From 25040ef2f898a5ab5d1072c5ee20b647127e8c60 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Fri, 10 Dec 2021 09:41:15 +0800 Subject: [PATCH 014/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A0=91=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/GenericTreeSortSupportEntity.java | 2 +- .../ReactiveTreeSortEntityService.java | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericTreeSortSupportEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericTreeSortSupportEntity.java index 6a37ebf61..8a79dbc5a 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericTreeSortSupportEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/GenericTreeSortSupportEntity.java @@ -37,7 +37,7 @@ public abstract class GenericTreeSortSupportEntity extends GenericEntity /** * 父级类别 */ - @Column(name = "parent_id", length = 32) + @Column(name = "parent_id", length = 64) @Comment("父级ID") @Schema(description = "父节点ID") private PK parentId; diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java index 84839cacc..d0759d640 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java @@ -48,38 +48,48 @@ default Mono> queryIncludeChildrenTree(QueryParamEntity paramEntity) { } default Flux queryIncludeChildren(Collection idList) { + Set duplicateCheck = new HashSet<>(); + return findById(idList) - .flatMap(e -> StringUtils - .isEmpty(e.getPath()) + .concatMap(e -> StringUtils + .isEmpty(e.getPath())|| !duplicateCheck.add(e.getPath()) ? Mono.just(e) : createQuery() .where() .like$("path", e.getPath()) - .fetch()); + .fetch()) + .distinct(TreeSupportEntity::getId); } default Flux queryIncludeParent(Collection idList) { + Set duplicateCheck = new HashSet<>(); + return findById(idList) - .flatMap(e -> StringUtils - .isEmpty(e.getPath()) + .concatMap(e -> StringUtils + .isEmpty(e.getPath())|| !duplicateCheck.add(e.getPath()) ? Mono.just(e) : createQuery() .where() .accept(Terms.Like.reversal("path", e.getPath(), false, true)) .notEmpty("path") .notNull("path") - .fetch()); + .fetch()) + .distinct(TreeSupportEntity::getId); } default Flux queryIncludeChildren(QueryParamEntity queryParam) { + Set duplicateCheck = new HashSet<>(); + return query(queryParam) - .flatMap(e -> StringUtils - .isEmpty(e.getPath()) + .concatMap(e -> StringUtils + .isEmpty(e.getPath()) || !duplicateCheck.add(e.getPath()) ? Mono.just(e) : createQuery() .where() .like$("path", e.getPath()) - .fetch()); + .fetch() + ) + .distinct(TreeSupportEntity::getId); } @Override From 26dc740560e3b29f33a3ed2c0719d715aed934f5 Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Mon, 13 Dec 2021 19:12:29 +0800 Subject: [PATCH 015/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8DDigestUtils=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E7=BA=BF=E7=A8=8B=E4=B8=8B=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/hswebframework/web/utils/DigestUtils.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java index 214443292..246a6dbd2 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java @@ -6,12 +6,12 @@ public class DigestUtils { - public static final MessageDigest md5 = org.apache.commons.codec.digest.DigestUtils.getMd5Digest(); - public static final MessageDigest sha256 = org.apache.commons.codec.digest.DigestUtils.getSha256Digest(); - public static final MessageDigest sha1 = org.apache.commons.codec.digest.DigestUtils.getSha1Digest(); + public static final ThreadLocal md5 = ThreadLocal.withInitial(org.apache.commons.codec.digest.DigestUtils::getMd5Digest); + public static final ThreadLocal sha256 = ThreadLocal.withInitial(org.apache.commons.codec.digest.DigestUtils::getSha256Digest); + public static final ThreadLocal sha1 = ThreadLocal.withInitial(org.apache.commons.codec.digest.DigestUtils::getSha1Digest); public static byte[] md5(byte[] data) { - return org.apache.commons.codec.digest.DigestUtils.digest(md5, data); + return org.apache.commons.codec.digest.DigestUtils.digest(md5.get(), data); } public static byte[] md5(String str) { @@ -23,7 +23,7 @@ public static String md5Hex(String str) { } public static byte[] sha256(byte[] data) { - return org.apache.commons.codec.digest.DigestUtils.digest(sha256, data); + return org.apache.commons.codec.digest.DigestUtils.digest(sha256.get(), data); } public static byte[] sha256(String str) { @@ -35,7 +35,7 @@ public static String sha256Hex(String str) { } public static byte[] sha1(byte[] data) { - return org.apache.commons.codec.digest.DigestUtils.digest(sha1, data); + return org.apache.commons.codec.digest.DigestUtils.digest(sha1.get(), data); } public static byte[] sha1(String str) { From e5df1e819919061a27b5e04b3d9673f3eb3a629b Mon Sep 17 00:00:00 2001 From: zhou-hao Date: Mon, 13 Dec 2021 19:15:46 +0800 Subject: [PATCH 016/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8DDigestUtils=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E7=BA=BF=E7=A8=8B=E4=B8=8B=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/utils/DigestUtilsTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 hsweb-core/src/test/java/org/hswebframework/web/utils/DigestUtilsTest.java diff --git a/hsweb-core/src/test/java/org/hswebframework/web/utils/DigestUtilsTest.java b/hsweb-core/src/test/java/org/hswebframework/web/utils/DigestUtilsTest.java new file mode 100644 index 000000000..f052ef09e --- /dev/null +++ b/hsweb-core/src/test/java/org/hswebframework/web/utils/DigestUtilsTest.java @@ -0,0 +1,28 @@ +package org.hswebframework.web.utils; + +import lombok.SneakyThrows; +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import static org.junit.Assert.*; + +public class DigestUtilsTest { + + + @Test + @SneakyThrows + public void test() { + Set check = ConcurrentHashMap.newKeySet(); + + for (int i = 0; i < 1000; i++) { + new Thread(() -> check.add(DigestUtils.md5Hex("test"))) + .start(); + } + Thread.sleep(1000); + System.out.println(check); + assertEquals(1, check.size()); + } +} \ No newline at end of file From 4de4861d15dca6095e1d8c21c5ce9a56ff77b0d9 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 21 Dec 2021 10:10:41 +0800 Subject: [PATCH 017/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/FieldDataAccess.java | 4 + .../authorization/annotation/Resource.java | 73 ++++++++++++ .../annotation/ResourceAction.java | 43 +++++++- .../authorization/annotation/SaveAction.java | 9 +- .../authorization/annotation/UserOwnData.java | 3 + .../events/AuthorizingHandleBeforeEvent.java | 32 +++++- .../web/api/crud/entity/Entity.java | 30 +++++ .../web/api/crud/entity/PagerResult.java | 36 ++++++ .../crud/entity/QueryNoPagingOperation.java | 18 +++ .../web/api/crud/entity/QueryOperation.java | 18 ++- .../web/api/crud/entity/QueryParamEntity.java | 16 ++- .../api/crud/entity/RecordCreationEntity.java | 32 ++++++ .../api/crud/entity/RecordModifierEntity.java | 30 +++++ .../api/crud/entity/SortSupportEntity.java | 22 +++- .../api/crud/entity/TreeSupportEntity.java | 57 ++++++++++ .../annotation/EnableEasyormRepository.java | 16 +++ .../web/crud/annotation/Reactive.java | 4 + .../web/crud/service/ReactiveCrudService.java | 23 ++-- .../ReactiveTreeSortEntityService.java | 51 ++++++++- .../crud/web/CommonErrorControllerAdvice.java | 9 +- .../web/reactive/ReactiveCrudController.java | 9 ++ .../web/reactive/ReactiveSaveController.java | 104 +++++++++++++++++- .../ReactiveServiceQueryController.java | 73 +++++++++++- .../ReactiveServiceSaveController.java | 100 +++++++++++++++-- 24 files changed, 767 insertions(+), 45 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java index 5c945f3fc..70b129ebf 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java @@ -4,10 +4,14 @@ import java.lang.annotation.*; +/** + * @deprecated 已弃用 + */ @DataAccessType(id = "FIELD_DENY", name = "字段权限") @Retention(RetentionPolicy.RUNTIME) @Documented @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD}) +@Deprecated public @interface FieldDataAccess { @AliasFor(annotation = DataAccessType.class) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java index 543704dbc..6b0efbe24 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java @@ -1,28 +1,101 @@ package org.hswebframework.web.authorization.annotation; +import org.hswebframework.web.authorization.Permission; import org.hswebframework.web.authorization.define.Phased; import java.lang.annotation.*; +/** + * 接口资源声明注解,声明Controller的资源相关信息,用于进行权限控制。 + *
+ * 在Controller进行注解,表示此接口需要有对应的权限{@link Permission#getId()}才能进行访问. + * 具体的操作权限控制,需要在方法上注解{@link ResourceAction}. + *
+ * + * + *
{@code
+ * @RestController
+ * //声明资源
+ * @Resource(id = "test", name = "测试功能")
+ * public class TestController implements ReactiveCrudController {
+ *
+ *     //声明操作,需要有 test:query 权限才能访问此接口
+ *     @QueryAction
+ *     public Mono getUser() {
+ *         return Authentication.currentReactive()
+ *                 .switchIfEmpty(Mono.error(new UnAuthorizedException()))
+ *                 .map(Authentication::getUser);
+ *     }
+ *
+ * }
+ * }
+ * 
+ * 如果接口不需要进行权限控制,可注解{@link Authorize#ignore()}来标识此接口不需要权限控制. + * 或者通过监听 {@link org.hswebframework.web.authorization.events.AuthorizingHandleBeforeEvent}来进行自定义处理 + *
{@code
+ *   @EventListener
+ *   public void handleAuthEvent(AuthorizingHandleBeforeEvent e) {
+ *      //admin用户可以访问全部操作
+ *      if ("admin".equals(e.getContext().getAuthentication().getUser().getUsername())) {
+ *         e.setAllow(true);
+ *       }
+ *    }
+ * }
+ * + * @author zhouhao + * @see ResourceAction + * @see Authorize + * @see org.hswebframework.web.authorization.events.AuthorizingHandleBeforeEvent + * @since 4.0 + */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Resource { + + /** + * 资源ID + * + * @return 资源ID + */ String id(); + /** + * @return 资源名称 + */ String name(); + /** + * @return 资源操作定义 + */ ResourceAction[] actions() default {}; + /** + * @return 多个操作控制逻辑 + */ Logical logical() default Logical.DEFAULT; + /** + * @return 权限控制阶段 + */ Phased phased() default Phased.before; + /** + * @return 资源描述 + */ String[] description() default {}; + /** + * @return 资源分组 + */ String[] group() default {}; + /** + * 如果在方法上设置此属性,表示是否合并类上注解的属性 + * + * @return 是否合并 + */ boolean merge() default true; } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java index 335ef878d..e8993be5d 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/ResourceAction.java @@ -1,24 +1,65 @@ package org.hswebframework.web.authorization.annotation; -import org.hswebframework.web.authorization.define.Phased; + +import org.hswebframework.web.authorization.Permission; import java.lang.annotation.*; /** + * 对资源操作的描述,通常用来进行权限控制. + *

+ * 在Controller方法上添加此注解,来声明根据权限操作{@link Permission#getActions()}进行权限控制. + *

+ * 可以使用注解继承的方式来统一定义操作: + *

{@code
+ * @Target(ElementType.METHOD)
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @Inherited
+ * @Documented
+ * @ResourceAction(id = "create", name = "新增")
+ * public @interface CreateAction {
+ *
+ * }
+ * }
+ * 
+ * * @see CreateAction + * @see DeleteAction + * @see SaveAction + * @see org.hswebframework.web.authorization.Authentication + * @see Permission#getActions() */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface ResourceAction { + /** + * 操作标识 + * + * @return 操作标识 + * @see Permission#getActions() + */ String id(); + /** + * @return 操作名称 + */ String name(); + /** + * @return 操作说明 + */ String[] description() default {}; + /** + * @return 多个操作时的判断逻辑 + */ Logical logical() default Logical.DEFAULT; + /** + * @deprecated 已弃用, 4.1中移除 + */ + @Deprecated DataAccess[] dataAccess() default @DataAccess(ignore = true); } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java index cf7b7b339..d878c52ae 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/SaveAction.java @@ -5,6 +5,12 @@ import java.lang.annotation.*; +/** + * 继承{@link ResourceAction},提供统一的id定义 + * + * @author zhouhao + * @since 4.0 + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Inherited @@ -12,6 +18,7 @@ @ResourceAction(id = Permission.ACTION_SAVE, name = "保存") public @interface SaveAction { - @AliasFor(annotation = ResourceAction.class,attribute = "dataAccess") + @Deprecated + @AliasFor(annotation = ResourceAction.class, attribute = "dataAccess") DataAccess dataAccess() default @DataAccess(ignore = true); } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java index 7f4caa9f8..74dbb12f7 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java @@ -4,12 +4,15 @@ /** * 声明某个操作支持用户查看自己的数据 + * + * @deprecated 已弃用 */ @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @DataAccessType(id = "user_own_data", name = "用户自己的数据") +@Deprecated public @interface UserOwnData { } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizingHandleBeforeEvent.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizingHandleBeforeEvent.java index 3eb6d2876..d2d189f26 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizingHandleBeforeEvent.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizingHandleBeforeEvent.java @@ -4,6 +4,22 @@ import org.hswebframework.web.authorization.define.HandleType; import org.springframework.context.ApplicationEvent; +/** + * 权限控制事件,在进行权限控制之前会推送此事件,用于自定义权限控制结果: + *
{@code
+ *   @EventListener
+ *   public void handleAuthEvent(AuthorizingHandleBeforeEvent e) {
+ *      //admin用户可以访问全部操作
+ *      if ("admin".equals(e.getContext().getAuthentication().getUser().getUsername())) {
+ *         e.setAllow(true);
+ *       }
+ *    }
+ * }
+ * + * @author zhouhao + * @since 4.0 + */ +// TODO: 2021/12/21 Reactive支持 public class AuthorizingHandleBeforeEvent extends ApplicationEvent implements AuthorizationEvent { private static final long serialVersionUID = -1095765748533721998L; @@ -14,7 +30,7 @@ public class AuthorizingHandleBeforeEvent extends ApplicationEvent implements Au private String message; - private HandleType handleType; + private final HandleType handleType; public AuthorizingHandleBeforeEvent(AuthorizingContext context, HandleType handleType) { super(context); @@ -33,6 +49,11 @@ public boolean isAllow() { return allow; } + /** + * 设置通过当前请求 + * + * @param allow allow + */ public void setAllow(boolean allow) { execute = false; this.allow = allow; @@ -42,11 +63,18 @@ public String getMessage() { return message; } + /** + * 设置错误提示消息 + * + * @param message 消息 + */ public void setMessage(String message) { this.message = message; } - + /** + * @return 权限控制类型 + */ public HandleType getHandleType() { return handleType; } diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java index 52d100b81..9d69f33e6 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java @@ -32,18 +32,48 @@ */ public interface Entity extends Serializable { + /** + * 使用jsr303对当前实体类进行验证,如果未通过验证则会抛出{@link org.hswebframework.web.exception.ValidationException}异常 + * + * @param groups 分组 + * @see org.hswebframework.web.exception.ValidationException + */ default void tryValidate(Class... groups) { ValidatorUtils.tryValidate(this, groups); } + /** + * 将当前实体类复制到指定其他类型中,类型将会被自动实例化,在类型明确时,建议使用{@link Entity#copyFrom(Object, String...)}. + * + * @param target 目标类型 + * @param ignoreProperties 忽略复制的属性 + * @param 类型 + * @return 复制结果 + */ default T copyTo(Class target, String... ignoreProperties) { return FastBeanCopier.copy(this, target, ignoreProperties); } + /** + * 将当前实体类复制到其他对象中 + * + * @param target 目标实体 + * @param ignoreProperties 忽略复制的属性 + * @param 类型 + * @return 复制结果 + */ default T copyTo(T target, String... ignoreProperties) { return FastBeanCopier.copy(this, target, ignoreProperties); } + /** + * 从其他对象复制属性到当前对象 + * + * @param target 其他对象 + * @param ignoreProperties 忽略复制的属性 + * @param 类型 + * @return 当前对象 + */ @SuppressWarnings("all") default T copyFrom(Object target, String... ignoreProperties) { return (T) FastBeanCopier.copy(target, this, ignoreProperties); diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java index 77d473772..9ff27518b 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/PagerResult.java @@ -28,15 +28,42 @@ import java.util.List; import java.util.Map; +/** + * 分页查询结果,用于在分页查询时,定义查询结果.如果需要拓展此类,例如自定义json序列化,请使用spi方式定义拓展实现类型: + *
+ * ---resources
+ * -----|--META-INF
+ * -----|----services
+ * -----|------org.hswebframework.web.api.crud.entity.PagerResult
+ * 
+ * + * @param 结果类型 + * @author zhouhao + * @since 4.0.0 + */ @Getter @Setter public class PagerResult { private static final long serialVersionUID = -6171751136953308027L; + /** + * 创建一个空结果 + * + * @param 结果类型 + * @return PagerResult + */ public static PagerResult empty() { return of(0, new ArrayList<>()); } + /** + * 创建一个分页结果 + * + * @param total 总数据量 + * @param list 当前页数据列表 + * @param 结果类型 + * @return PagerResult + */ @SuppressWarnings("all") public static PagerResult of(int total, List list) { PagerResult result; @@ -46,6 +73,15 @@ public static PagerResult of(int total, List list) { return result; } + /** + * 创建一个分页结果,并将查询参数中的分页索引等信息填充到分页结果中 + * + * @param total 总数据量 + * @param list 当前页数据列表 + * @param entity 查询参数 + * @param 结果类型 + * @return PagerResult + */ public static PagerResult of(int total, List list, QueryParam entity) { PagerResult pagerResult = of(total, list); pagerResult.setPageIndex(entity.getThinkPageIndex()); diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryNoPagingOperation.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryNoPagingOperation.java index cdf1ac6b7..f24aafb69 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryNoPagingOperation.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryNoPagingOperation.java @@ -22,6 +22,24 @@ import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; +/** + * 使用注解继承来对swagger接口文档注解的拓展,用来标识接口不支持分页查询参数. + * + * + *
{@code
+ * @GetMapping
+ * @QueryNoPagingOperation(summary="接口说明")
+ * public Flux handleRequest(@Parameter(hidden = true) QueryParamEntity query){
+ *  return service.query(query);
+ * }
+ *
+ * }
+ * + * 注意在参数上注解 {@code @Parameter(hidden=true)} + * @author zhouhao + * @since 4.0.5 + * @see QueryNoPagingOperation#parameters() + */ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryOperation.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryOperation.java index 9552e72f5..3dd75ab47 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryOperation.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryOperation.java @@ -22,6 +22,22 @@ import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.METHOD; +/** + * 使用注解继承来对swagger接口文档注解的拓展,用来标识接口支持分页查询参数. + * + *
{@code
+ * @GetMapping
+ * @QueryOperation(summary="接口说明")
+ * public Flux handleRequest(@Parameter(hidden = true) QueryParamEntity query){
+ *  return service.query(query);
+ * }
+ *
+ * }
+ * + * @author zhouhao + * @see QueryOperation#parameters() + * @since 4.0.5 + */ @Target({METHOD, ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @@ -97,7 +113,7 @@ Parameter[] parameters() default { @Parameter(name = "where", description = "条件表达式,和terms参数冲突", example = "id = 1", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), @Parameter(name = "orderBy", description = "排序表达式,和sorts参数冲突", example = "id desc", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), @Parameter(name = "includes", description = "指定要查询的列,多列使用逗号分隔", example = "id", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), - @Parameter(name = "excludes", description = "指定不查询的列,多列使用逗号分隔", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), + @Parameter(name = "excludes", description = "指定不查询的列,多列使用逗号分隔", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), @Parameter(name = "terms[0].column", description = "指定条件字段", schema = @Schema(implementation = String.class), in = ParameterIn.QUERY), @Parameter(name = "terms[0].termType", description = "条件类型", schema = @Schema(implementation = String.class), example = "like", in = ParameterIn.QUERY), @Parameter(name = "terms[0].type", description = "多个条件组合方式", schema = @Schema(implementation = Term.Type.class), in = ParameterIn.QUERY), diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java index b02fecca2..680d51589 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java @@ -25,9 +25,19 @@ * 查询参数实体,使用easyorm进行动态查询参数构建
* 可通过静态方法创建:
* 如: - * - * QueryParamEntity.of("id",id); - * + *
+ *{@code
+ *      QueryParamEntity.of("id",id);
+ *}
+ * 
+ * + * 或者使用DSL方式来构造: + *
{@code
+ *  QueryParamEntity
+ *  .newQuery()
+ *  .where("id",1)
+ *  .execute(service::query)
+ * }
* * @author zhouhao * @see QueryParam diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordCreationEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordCreationEntity.java index 930e841f6..69c9d7272 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordCreationEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordCreationEntity.java @@ -12,23 +12,55 @@ */ public interface RecordCreationEntity extends Entity { + /** + * @return 创建者ID + */ String getCreatorId(); + /** + * 设置创建者ID + * + * @param creatorId 创建者ID + */ void setCreatorId(String creatorId); + /** + * 创建时间,UTC时间戳 + * + * @return 创建时间 + * @see System#currentTimeMillis() + */ Long getCreateTime(); + /** + * 设置创建时间 ,UTC时间戳 + * + * @param createTime 创建时间 + * @see System#currentTimeMillis() + */ void setCreateTime(Long createTime); + /** + * 设置创建者名字,为了兼容,默认不支持记录创建者名字,由具体的实现类进行实现 + * + * @param name 创建者名字 + */ default void setCreatorName(String name) { } + /** + * 设置创建时间为当前时间 + */ default void setCreateTimeNow() { setCreateTime(System.currentTimeMillis()); } + /** + * @deprecated 已弃用, 在4.1版本中移除 + */ @JsonIgnore + @Deprecated default String getCreatorIdProperty() { return "creatorId"; } diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordModifierEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordModifierEntity.java index e43c41801..4811967a5 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordModifierEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/RecordModifierEntity.java @@ -13,22 +13,52 @@ public interface RecordModifierEntity extends Entity { String modifierId = "modifierId"; String modifyTime = "modifyTime"; + /** + * 修改人ID + * + * @return 修改人ID + */ String getModifierId(); + /** + * 设置修改人ID + * + * @param modifierId 修改人ID + */ void setModifierId(String modifierId); + /** + * 设置修改人名字,为了兼容,默认不支持记录修改人名字,由具体的实现类进行实现 + * + * @param modifierName 修改人名字 + */ default void setModifierName(String modifierName) { } + /** + * @return 修改时间 + */ Long getModifyTime(); + /** + * 设置修改时间,UTC时间戳 + * + * @param modifyTime 修改时间 + * @see System#currentTimeMillis() + */ void setModifyTime(Long modifyTime); + /** + * 设置修改时间为当前时间 + */ default void setModifyTimeNow() { setModifyTime(System.currentTimeMillis()); } + /** + * @deprecated 已弃用, 4.1版本中移除 + */ @JsonIgnore default String getModifierIdProperty() { return modifierId; diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/SortSupportEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/SortSupportEntity.java index 64dd3862e..657946c8e 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/SortSupportEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/SortSupportEntity.java @@ -18,18 +18,30 @@ package org.hswebframework.web.api.crud.entity; +import javax.annotation.Nonnull; + +/** + * 支持排序的实体 + * + * @author zhouhao + * @since 4.0.0 + */ public interface SortSupportEntity extends Comparable, Entity { + /** + * @return 排序序号 + */ Long getSortIndex(); + /** + * 设置排序序号 + * + * @param sortIndex 排序序号 + */ void setSortIndex(Long sortIndex); @Override - default int compareTo(SortSupportEntity support) { - if (support == null) { - return -1; - } - + default int compareTo(@Nonnull SortSupportEntity support) { return Long.compare(getSortIndex() == null ? 0 : getSortIndex(), support.getSortIndex() == null ? 0 : support.getSortIndex()); } } diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java index 3f35ddb6c..fd3e4e4f9 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java @@ -29,25 +29,82 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +/** + * 支持树结构的实体类 + * + * @param 主键类型 + * @author zhouhao + * @since 4.0 + */ @SuppressWarnings("all") public interface TreeSupportEntity extends Entity { + /** + * 获取主键 + * + * @return ID + */ PK getId(); + /** + * 设置主键 + * + * @param id ID + */ void setId(PK id); + /** + * 获取树路径,树路径表示当前节点所在位置 + * 格式通常为: aBcD-EfgH-iJkl,以-分割,一个分割表示一级. + * 比如: aBcD-EfgH-iJkl表示 当前节点在第三级,上一个节点为EfgH. + * + * @return 树路径 + */ String getPath(); + /** + * 设置路径,此值通常不需要手动设置,在进行保存时,由service自动进行分配. + * + * @param path 路径 + * @see TreeSupportEntity#expandTree2List(TreeSupportEntity, IDGenerator) + */ void setPath(String path); + /** + * 获取上级ID + * + * @return 上级ID + */ PK getParentId(); + /** + * 设置上级节点ID + * + * @param parentId + */ void setParentId(PK parentId); + /** + * 获取节点层级 + * + * @return 节点层级 + */ Integer getLevel(); + /** + * 设置节点层级 + * + * @return 节点层级 + */ void setLevel(Integer level); + /** + * 获取所有子节点,默认情况下此字段只会返回null.可以使用{@link TreeSupportEntity#list2tree(Collection, BiConsumer)}将 + * 列表结构转为树形结构 + * + * @param 当前实体类型 + * @return 自己节点 + */ > List getChildren(); @Override diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/EnableEasyormRepository.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/EnableEasyormRepository.java index c7c9a60f8..5e2e820e8 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/EnableEasyormRepository.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/EnableEasyormRepository.java @@ -7,6 +7,13 @@ import java.lang.annotation.*; /** + * 在启动类上注解,标识开启自动注册实体通用增删改查接口到spring上下文中. + * 在spring中,可直接进行泛型注入使用: + *
{@code
+ *   @Autowire
+ *   ReactiveRepository repository;
+ * }
+ * * @see org.hswebframework.ezorm.rdb.mapping.ReactiveRepository * @see org.hswebframework.ezorm.rdb.mapping.SyncRepository * @since 4.0.0 @@ -30,8 +37,17 @@ */ Class[] annotation() default Table.class; + /** + * @return 是否开启响应式, 默认开启 + */ boolean reactive() default true; + /** + * 是否开启非响应式操作,在使用WebFlux时,不建议开启 + * + * @return 开启非响应式 + * @see org.hswebframework.ezorm.rdb.mapping.SyncRepository + */ boolean nonReactive() default false; } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/Reactive.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/Reactive.java index b535fe517..aa7982b48 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/Reactive.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/annotation/Reactive.java @@ -3,7 +3,11 @@ import java.lang.annotation.*; /** + * 在实体类上注解,标记是否开启响应式仓库 + * + * @author zhouhao * @see org.hswebframework.ezorm.rdb.mapping.ReactiveRepository + * @since 4.0.0 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java index 67680a295..6179b186a 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveCrudService.java @@ -37,13 +37,13 @@ public interface ReactiveCrudService { /** * 创建一个DSL的动态查询接口,可使用DSL方式进行链式调用来构造动态查询条件.例如: - *
-     * Flux<MyEntity> flux=
-     *     service
+     * 
{@code
+     * Flux flux = service
      *     .createQuery()
      *     .where(MyEntity::getName,name)
      *     .in(MyEntity::getState,state1,state2)
      *     .fetch()
+     * }
      * 
* * @return 动态查询接口 @@ -54,14 +54,14 @@ default ReactiveQuery createQuery() { /** * 创建一个DSL动态更新接口,可使用DSL方式进行链式调用来构造动态更新条件.例如: - *
-     * Mono<Integer> flux=
-     *     service
+     * 
{@code
+     * Mono result = service
      *     .createUpdate()
      *     .set(entity::getState)
      *     .where(MyEntity::getName,name)
      *     .in(MyEntity::getState,state1,state2)
      *     .execute()
+     *     }
      * 
* * @return 动态更新接口 @@ -72,13 +72,13 @@ default ReactiveUpdate createUpdate() { /** * 创建一个DSL动态删除接口,可使用DSL方式进行链式调用来构造动态删除条件.例如: - *
-     * Mono<Integer> flux=
-     *     service
+     * 
{@code
+     * Mono result = service
      *     .createDelete()
      *     .where(MyEntity::getName,name)
      *     .in(MyEntity::getState,state1,state2)
      *     .execute()
+     * }
      * 
* * @return 动态更新接口 @@ -194,6 +194,8 @@ default Mono> queryPager(QueryParamEntity queryParamMono) { @Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager) default Mono> queryPager(QueryParamEntity query, Function mapper) { + //如果查询参数指定了总数,表示不需要再进行count操作. + //建议前端在使用分页查询时,切换下一页时,将第一次查询到total结果传入查询参数,可以提升查询性能. if (query.getTotal() != null) { return getRepository() .createQuery() @@ -203,7 +205,7 @@ default Mono> queryPager(QueryParamEntity query, Function PagerResult.of(query.getTotal(), list, query)); } - //并行分页 + //并行分页,更快,所在页码无数据时,会返回空list. if (query.isParallelPager()) { return Mono .zip( @@ -220,6 +222,7 @@ default Mono> queryPager(QueryParamEntity query, Function(), query)); } + //查询前根据数据总数进行重新分页:要跳转的页码没有数据则跳转到最后一页 return query(query.clone().rePaging(total)) .map(mapper) .collectList() diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java index d0759d640..64f14a28c 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java @@ -20,6 +20,8 @@ import java.util.stream.Collectors; /** + * 树形结构的通用增删改查服务 + * * @param TreeSortSupportEntity * @param ID * @see GenericReactiveTreeSupportCrudService @@ -27,10 +29,22 @@ public interface ReactiveTreeSortEntityService, K> extends ReactiveCrudService { + /** + * 动态查询并将查询结构转为树形结构 + * + * @param paramEntity 查询参数 + * @return 树形结构 + */ default Mono> queryResultToTree(Mono paramEntity) { return paramEntity.flatMap(this::queryResultToTree); } + /** + * 动态查询并将查询结构转为树形结构 + * + * @param paramEntity 查询参数 + * @return 树形结构 + */ default Mono> queryResultToTree(QueryParamEntity paramEntity) { return query(paramEntity) .collectList() @@ -39,6 +53,12 @@ default Mono> queryResultToTree(QueryParamEntity paramEntity) { this::createRootNodePredicate)); } + /** + * 动态查询并将查询结构转为树形结构,包含所有子节点 + * + * @param paramEntity 查询参数 + * @return 树形结构 + */ default Mono> queryIncludeChildrenTree(QueryParamEntity paramEntity) { return queryIncludeChildren(paramEntity) .collectList() @@ -47,29 +67,43 @@ default Mono> queryIncludeChildrenTree(QueryParamEntity paramEntity) { this::createRootNodePredicate)); } + /** + * 查询指定ID的实体以及对应的全部子节点 + * + * @param idList ID集合 + * @return 树形结构 + */ default Flux queryIncludeChildren(Collection idList) { Set duplicateCheck = new HashSet<>(); return findById(idList) .concatMap(e -> StringUtils - .isEmpty(e.getPath())|| !duplicateCheck.add(e.getPath()) + .isEmpty(e.getPath()) || !duplicateCheck.add(e.getPath()) ? Mono.just(e) : createQuery() .where() + //使用path快速查询 .like$("path", e.getPath()) .fetch()) .distinct(TreeSupportEntity::getId); } + /** + * 查询指定ID的实体以及对应的全部父节点 + * + * @param idList ID集合 + * @return 树形结构 + */ default Flux queryIncludeParent(Collection idList) { Set duplicateCheck = new HashSet<>(); return findById(idList) .concatMap(e -> StringUtils - .isEmpty(e.getPath())|| !duplicateCheck.add(e.getPath()) + .isEmpty(e.getPath()) || !duplicateCheck.add(e.getPath()) ? Mono.just(e) : createQuery() .where() + //where ? like path and path !='' and path not null .accept(Terms.Like.reversal("path", e.getPath(), false, true)) .notEmpty("path") .notNull("path") @@ -77,6 +111,12 @@ default Flux queryIncludeParent(Collection idList) { .distinct(TreeSupportEntity::getId); } + /** + * 动态查询并将查询结构转为树形结构 + * + * @param queryParam 查询参数 + * @return 树形结构 + */ default Flux queryIncludeChildren(QueryParamEntity queryParam) { Set duplicateCheck = new HashSet<>(); @@ -134,6 +174,7 @@ default Mono checkCyclicDependency(K id, E ele) { .then(Mono.just(ele)); } + //重构子节点的path default Mono refactorChildPath(K id, String path, Consumer pathAccepter) { return this .createQuery() @@ -161,6 +202,7 @@ default Mono refactorChildPath(K id, String path, Consumer pathAccepter default Mono save(Publisher entityPublisher) { return Flux .from(entityPublisher) + //1.先平铺 .flatMapIterable(e -> TreeSupportEntity.expandTree2List(e, getIDGenerator())) .collectList() .flatMapIterable(list -> { @@ -168,14 +210,17 @@ default Mono save(Publisher entityPublisher) { .stream() .filter(e -> e.getId() != null) .collect(Collectors.toMap(TreeSupportEntity::getId, Function.identity())); - + //2. 重新组装树结构 return TreeSupportEntity.list2tree(list, this::setChildren, (Predicate) e -> this.isRootNode(e) || map.get(e.getParentId()) == null); }) + //执行验证 .doOnNext(e -> e.tryValidate(CreateGroup.class)) + //再次平铺为 .flatMapIterable(e -> TreeSupportEntity.expandTree2List(e, getIDGenerator())) + //重构path .as(this::tryRefactorPath) .as(this.getRepository()::save); diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java index c1556f9c7..0d4b0b77e 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java @@ -32,8 +32,13 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +/** + * 统一错误处理 + * + * @author zhouhao + * @since 4.0 + */ @RestControllerAdvice -//@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) @Slf4j @Order public class CommonErrorControllerAdvice { @@ -134,7 +139,7 @@ private Mono>> handleBindingRes .stream() .map(err -> new ValidationException.Detail(err.getField(), err.getDefaultMessage(), null)) .collect(Collectors.toList()); - return handleException(new ValidationException(message, details)); + return handleException(new ValidationException(message, details)); } @ExceptionHandler diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveCrudController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveCrudController.java index 3437a0eab..16c31e46f 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveCrudController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveCrudController.java @@ -1,5 +1,14 @@ package org.hswebframework.web.crud.web.reactive; +/** + * 通用响应式增删该查Controller,实现本接口来默认支持增删改查相关操作. + * + * @param 实体类型 + * @param 主键类型 + * @see ReactiveSaveController + * @see ReactiveQueryController + * @see ReactiveDeleteController + */ public interface ReactiveCrudController extends ReactiveSaveController, ReactiveQueryController, diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveSaveController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveSaveController.java index c373a6323..cad2f6dcc 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveSaveController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveSaveController.java @@ -15,6 +15,12 @@ import javax.validation.Valid; +/** + * 响应式保存接口,基于{@link ReactiveRepository}提供默认的新增,保存,修改接口. + * + * @param 实体类型 + * @param 主键类型 + */ public interface ReactiveSaveController { @Authorize(ignore = true) @@ -38,6 +44,14 @@ default E applyModifierEntity(Authentication authentication, E entity) { return entity; } + /** + * 尝试设置登陆用户信息到实体中 + * + * @param entity 实体 + * @param authentication 权限信息 + * @see RecordCreationEntity + * @see RecordModifierEntity + */ @Authorize(ignore = true) default E applyAuthentication(E entity, Authentication authentication) { if (entity instanceof RecordCreationEntity) { @@ -49,45 +63,123 @@ default E applyAuthentication(E entity, Authentication authentication) { return entity; } + /** + * 保存数据,如果传入了id,并且对应数据存在,则尝试覆盖,不存在则新增. + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * PATCH /api/test
+     * Content-Type: application/json
+     *
+     * [
+     *  {
+     *   "name":"value"
+     *  }
+     * ]
+     * }
+     * 
+ * + * @param payload payload + * @return 保存结果 + */ @PatchMapping @SaveAction @Operation(summary = "保存数据", description = "如果传入了id,并且对应数据存在,则尝试覆盖,不存在则新增.") default Mono save(@RequestBody Flux payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMapMany(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .as(getRepository()::save); } + /** + * 批量新增 + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * POST /api/test/_batch
+     * Content-Type: application/json
+     *
+     * [
+     *  {
+     *   "name":"value"
+     *  }
+     * ]
+     * }
+     * 
+ * + * @param payload payload + * @return 保存结果 + */ @PostMapping("/_batch") @SaveAction @Operation(summary = "批量新增数据") default Mono add(@RequestBody Flux payload) { - - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMapMany(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .collectList() .as(getRepository()::insertBatch); } + /** + * 新增单个数据,并返回新增后的数据. + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * POST /api/test
+     * Content-Type: application/json
+     *
+     *  {
+     *   "name":"value"
+     *  }
+     * }
+     * 
+ * + * @param payload payload + * @return 新增后的数据 + */ @PostMapping @SaveAction @Operation(summary = "新增单个数据,并返回新增后的数据.") default Mono add(@RequestBody Mono payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .flatMap(entity -> getRepository().insert(Mono.just(entity)).thenReturn(entity)); } + /** + * 根据ID修改数据 + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * PUT /api/test/{id}
+     * Content-Type: application/json
+     *
+     *  {
+     *   "name":"value"
+     *  }
+     * }
+     * 
+ * + * @param payload payload + * @return 是否成功 + */ @PutMapping("/{id}") @SaveAction @Operation(summary = "根据ID修改数据") default Mono update(@PathVariable K id, @RequestBody Mono payload) { - - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .flatMap(entity -> getRepository().updateById(id, Mono.just(entity))) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java index d1dd307e4..ef0f074a1 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java @@ -74,7 +74,7 @@ default Flux query(@Parameter(hidden = true) QueryParamEntity query) { @QueryAction @QueryNoPagingOperation(summary = "使用POST方式分页动态查询(不返回总数)", description = "此操作不返回分页总数,如果需要获取全部数据,请设置参数paging=false") - default Flux query(@Parameter(hidden = true)@RequestBody Mono query) { + default Flux query(@Parameter(hidden = true) @RequestBody Mono query) { return query.flatMapMany(this::query); } @@ -105,6 +105,31 @@ default Mono> queryPager(@Parameter(hidden = true) QueryParamEnti } + /** + * POST方式动态查询. + * + *
+     *     POST /_query
+     *
+     *     {
+     *         "pageIndex":0,
+     *         "pageSize":20,
+     *         "where":"name like 张%", //放心使用,没有SQL注入
+     *         "orderBy":"id desc",
+     *         "terms":[ //高级条件
+     *             {
+     *                 "column":"name",
+     *                 "termType":"like",
+     *                 "value":"张%"
+     *             }
+     *         ]
+     *     }
+     * 
+ * + * @param query 查询条件 + * @return 结果流 + * @see QueryParamEntity + */ @PostMapping("/_query") @QueryAction @SuppressWarnings("all") @@ -113,6 +138,31 @@ default Mono> queryPager(@Parameter(hidden = true) @RequestBody M return query.flatMap(q -> queryPager(q)); } + /** + * POST方式动态查询数量. + * + *
+     *     POST /_count
+     *
+     *     {
+     *         "pageIndex":0,
+     *         "pageSize":20,
+     *         "where":"name like 张%", //放心使用,没有SQL注入
+     *         "orderBy":"id desc",
+     *         "terms":[ //高级条件
+     *             {
+     *                 "column":"name",
+     *                 "termType":"like",
+     *                 "value":"张%"
+     *             }
+     *         ]
+     *     }
+     * 
+ * + * @param query 查询条件 + * @return 查询结果 + * @see QueryParamEntity + */ @PostMapping("/_count") @QueryAction @QueryNoPagingOperation(summary = "使用POST方式查询总数") @@ -121,14 +171,17 @@ default Mono count(@Parameter(hidden = true) @RequestBody Mono - * GET /_count + * + * GET /_query/_count?pageIndex=0&pageSize=20&where=name is 张三&orderBy=id desc + * *
* * @param query 查询条件 - * @return 统计结果 + * @return 查询结果 + * @see QueryParamEntity */ @GetMapping("/_count") @QueryAction @@ -140,6 +193,18 @@ default Mono count(@Parameter(hidden = true) QueryParamEntity query) { .count(); } + /** + * 根据ID查询. + *
+     * {@code
+     *     GET /{id}
+     * }
+     * 
+ * + * @param id ID + * @return 结果流 + * @see QueryParamEntity + */ @GetMapping("/{id:.+}") @QueryAction @Operation(summary = "根据ID查询") diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java index 581adfb7f..cf82b783b 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java @@ -1,6 +1,7 @@ package org.hswebframework.web.crud.web.reactive; import io.swagger.v3.oas.annotations.Operation; +import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult; import org.hswebframework.web.api.crud.entity.RecordCreationEntity; import org.hswebframework.web.api.crud.entity.RecordModifierEntity; @@ -12,10 +13,16 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -public interface ReactiveServiceSaveController { +/** + * 响应式保存接口,基于{@link ReactiveCrudService}提供默认的新增,保存,修改接口. + * + * @param 实体类型 + * @param 主键类型 + */ +public interface ReactiveServiceSaveController { @Authorize(ignore = true) - ReactiveCrudService getService(); + ReactiveCrudService getService(); @Authorize(ignore = true) default E applyCreationEntity(Authentication authentication, E entity) { @@ -46,45 +53,124 @@ default E applyAuthentication(E entity, Authentication authentication) { return entity; } + /** + * 保存数据,如果传入了id,并且对应数据存在,则尝试覆盖,不存在则新增. + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * PATCH /api/test
+     * Content-Type: application/json
+     *
+     * [
+     *  {
+     *   "name":"value"
+     *  }
+     * ]
+     * }
+     * 
+ * + * @param payload payload + * @return 保存结果 + */ @PatchMapping @SaveAction @Operation(summary = "保存数据", description = "如果传入了id,并且对应数据存在,则尝试覆盖,不存在则新增.") default Mono save(@RequestBody Flux payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMapMany(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .as(getService()::save); } + /** + * 批量新增 + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * POST /api/test/_batch
+     * Content-Type: application/json
+     *
+     * [
+     *  {
+     *   "name":"value"
+     *  }
+     * ]
+     * }
+     * 
+ * + * @param payload payload + * @return 保存结果 + */ @PostMapping("/_batch") @SaveAction @Operation(summary = "批量新增数据") default Mono add(@RequestBody Flux payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMapMany(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .collectList() .as(getService()::insertBatch); } + /** + * 新增单个数据,并返回新增后的数据. + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * POST /api/test
+     * Content-Type: application/json
+     *
+     *  {
+     *   "name":"value"
+     *  }
+     * }
+     * 
+ * + * @param payload payload + * @return 新增后的数据 + */ @PostMapping @SaveAction @Operation(summary = "新增单个数据,并返回新增后的数据.") default Mono add(@RequestBody Mono payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .flatMap(entity -> getService().insert(Mono.just(entity)).thenReturn(entity)); } - + /** + * 根据ID修改数据 + *

+ * 以类注解{@code @RequestMapping("/api/test")}为例: + *
{@code
+     *
+     * PUT /api/test/{id}
+     * Content-Type: application/json
+     *
+     *  {
+     *   "name":"value"
+     *  }
+     * }
+     * 
+ * + * @param payload payload + * @return 是否成功 + */ @PutMapping("/{id}") @SaveAction @Operation(summary = "根据ID修改数据") default Mono update(@PathVariable K id, @RequestBody Mono payload) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .flatMap(entity -> getService().updateById(id, Mono.just(entity))) From 43d3b908c4a8f0f8083fbb11b90334b71282069b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 23 Dec 2021 15:05:40 +0800 Subject: [PATCH 018/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9ca7dcc37..deff62247 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # hsweb4 基于spring-boot2,全响应式的后台管理框架 + [![Codecov](https://codecov.io/gh/hs-web/hsweb-framework/branch/4.0.x/graph/badge.svg)](https://codecov.io/gh/hs-web/hsweb-framework/branch/master) [![Build Status](https://api.travis-ci.com/hs-web/hsweb-framework.svg?branch=4.0.x)](https://travis-ci.com/hs-web/hsweb-framework) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) # 功能,特性 + - [x] 基于[r2dbc](https://github.com/r2dbc) ,[easy-orm](https://github.com/hs-web/hsweb-easy-orm/tree/4.0.x) 的通用响应式CRUD - [x] H2,Mysql,SqlServer,PostgreSQL - [x] 响应式r2dbc事务控制 @@ -12,7 +14,7 @@ - [x] 数据权限控制 - [ ] 双因子验证 - [x] 多维度权限管理功能 -- [x] 响应式缓存 +- [x] 响应式缓存 - [ ] 非响应式支持(mvc,jdbc) - [ ] 内置业务功能 - [x] 权限管理 @@ -24,10 +26,108 @@ - [ ] 文件秒传 - [x] 数据字典 -# 文档 +# 示例 + +https://github.com/zhou-hao/hsweb4-examples + +## 应用场景 + +1. 完全开源的后台管理系统. +2. 模块化的后台管理系统. +3. 功能可拓展的后台管理系统. +4. 集成各种常用功能的后台管理系统. +5. 前后分离的后台管理系统. + +注意: +项目主要基于`spring-boot`,`spring-webflux`. 在使用`hsweb`之前,你应该对 [project-reactor](https://projectreactor.io/) , +[spring-boot](https://github.com/spring-projects/spring-boot) 有一定的了解. + +项目模块太多?不要被吓到.我们不推荐将本项目直接`clone`后修改,运行.而是使用maven依赖的方式使用`hsweb`. 选择自己需要的模块进行依赖,正式版发布后,所有模块都将发布到maven中央仓库. + +## 文档 + +各个模块的使用方式查看对应模块下的 `README.md`,在使用之前, 你可以先粗略浏览一下各个模块,对每个模块的作用有大致的了解. + +## 核心技术选型 + +1. Java 8 +2. Maven3 +3. Spring Boot 2.x +4. Project Reactor 响应式编程框架 +5. hsweb easy orm 对r2dbc的orm封装 + +## 模块简介 + +| 模块 | 说明 | +| ------------- |:----------:| +|[hsweb-authorization](hsweb-authorization)| 权限控制 | +|[hsweb-commons](hsweb-commons) | 基础通用功能 | +|[hsweb-concurrent](hsweb-concurrent)| 并发包,缓存,等 | +|[hsweb-core](hsweb-core)| 框架核心,基础工具类 | +|[hsweb-datasource](hsweb-datasource)| 数据源 | +|[hsweb-logging](hsweb-logging)| 日志 | +|[hsweb-starter](hsweb-starter)| 模块启动器 | +|[hsweb-system](hsweb-system)| **系统常用功能** | + +## 核心特性 + +1. 响应式,首个基于spring-webflux,r2dbc,从头到位的响应式. +2. DSL风格,可拓展的通用curd,支持前端直接传参数,无需担心任何sql注入. + +```java + //where name = #{name} + createQuery() + .where("name",name) + .fetch(); + + //update s_user set name = #{user.name} where id = #{user.id} + createUpdate() + .set(user::getName) + .where(user::getId) + .execute(); + +``` + +3. 类JPA增删改 + +```java + +@Table(name = "s_entity") +public class MyEntity { + + @Id + private String id; + + @Column + private String name; + + @Column + private Long createTime; +} + +``` + +直接注入即可实现增删改查 + +```java + +@Autowire +private ReactiveRepository repository; + +``` + +2. 灵活的权限控制 + +```java + +@PostMapping("/account") +@SaveAction +public Mono addAccount(@RequestBody Mono account){ + return accountService.doSave(account); +} -直接看代码: https://github.com/zhou-hao/hsweb4-examples +``` -# 实践 +## License -[JetLinks开源物联网平台](https://github.com/jetlinks) +[Apache 2.0](https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt) \ No newline at end of file From 5f752c81c3b7fc18c7b1126008e41b550456b15a Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Dec 2021 13:44:29 +0800 Subject: [PATCH 019/416] =?UTF-8?q?=E5=87=8F=E5=B0=91=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/aop/MethodInterceptorHolder.java | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java b/hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java index 4bfa511c4..57b1b0304 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java @@ -18,14 +18,16 @@ package org.hswebframework.web.aop; +import com.google.common.collect.Maps; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Setter; import org.aopalliance.intercept.MethodInvocation; import org.hswebframework.web.utils.AnnotationUtils; +import org.hswebframework.web.utils.DigestUtils; import org.reactivestreams.Publisher; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; -import org.springframework.util.DigestUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -48,25 +50,28 @@ public class MethodInterceptorHolder { public static final ParameterNameDiscoverer nameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); public static MethodInterceptorHolder create(MethodInvocation invocation) { - String id = DigestUtils.md5DigestAsHex(String.valueOf(invocation.getMethod().hashCode()).getBytes()); String[] argNames = nameDiscoverer.getParameterNames(invocation.getMethod()); Object[] args = invocation.getArguments(); - Map argMap = new LinkedHashMap<>(); - String[] names = new String[args.length]; - for (int i = 0, len = args.length; i < len; i++) { - names[i] = (argNames == null || argNames.length <= i || argNames[i] == null) ? "arg" + i : argNames[i]; - argMap.put(names[i], args[i]); - } - return new MethodInterceptorHolder(id, - invocation.getMethod(), - invocation.getThis(), - args, - names, - argMap); + String[] names; + //参数名与参数长度不一致,则填充argx来作为参数名 + if (argNames == null || argNames.length != args.length) { + names = new String[args.length]; + for (int i = 0, len = args.length; i < len; i++) { + names[i] = (argNames == null || argNames.length <= i || argNames[i] == null) ? "arg" + i : argNames[i]; + } + } else { + names = argNames; + } + return new MethodInterceptorHolder(null, + invocation.getMethod(), + invocation.getThis(), + args, + names, + null); } - private final String id; + private String id; private final Method method; @@ -76,8 +81,27 @@ public static MethodInterceptorHolder create(MethodInvocation invocation) { private final String[] argumentsNames; - private final Map namedArguments; + private Map namedArguments; + + public String getId() { + if (id == null) { + id = DigestUtils.md5Hex(method.toString()); + } + return id; + } + protected Map createNamedArguments() { + Map namedArguments = Maps.newLinkedHashMapWithExpectedSize(arguments.length); + for (int i = 0, len = arguments.length; i < len; i++) { + namedArguments.put(argumentsNames[i], arguments[i]); + } + return namedArguments; + + } + + public Map getNamedArguments() { + return namedArguments == null ? namedArguments = createNamedArguments() : namedArguments; + } public T findMethodAnnotation(Class annClass) { return AnnotationUtils.findMethodAnnotation(annClass, method, annClass); From 7846812266602c596ac74a3897e908a6b0f2e493 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Dec 2021 13:45:04 +0800 Subject: [PATCH 020/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/logging/aop/AccessLoggerParser.java | 2 +- .../aop/DefaultAccessLoggerParser.java | 2 +- .../aop/ReactiveAopAccessLoggerSupport.java | 59 +++++++++++++------ .../aop/ResourceAccessLoggerParser.java | 2 +- .../aop/Swagger3AccessLoggerParser.java | 2 +- .../aop/SwaggerAccessLoggerParser.java | 2 +- 6 files changed, 47 insertions(+), 22 deletions(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AccessLoggerParser.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AccessLoggerParser.java index e51573e94..584ba6f85 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AccessLoggerParser.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/AccessLoggerParser.java @@ -7,7 +7,7 @@ import java.lang.reflect.Method; public interface AccessLoggerParser { - boolean support(Class clazz, Method method); + boolean support(Class clazz, Method method); LoggerDefine parse(MethodInterceptorHolder holder); } diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/DefaultAccessLoggerParser.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/DefaultAccessLoggerParser.java index 3c9f742ba..a0fc433fc 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/DefaultAccessLoggerParser.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/DefaultAccessLoggerParser.java @@ -13,7 +13,7 @@ public class DefaultAccessLoggerParser implements AccessLoggerParser { @Override - public boolean support(Class clazz, Method method) { + public boolean support(Class clazz, Method method) { AccessLogger ann = AnnotationUtils.findAnnotation(method, AccessLogger.class); //注解了并且未取消 return null != ann && !ann.ignore(); diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index 9dd11cf35..7afb1a897 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -16,6 +16,7 @@ import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.ClassUtils; +import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; @@ -41,6 +42,11 @@ public class ReactiveAopAccessLoggerSupport extends StaticMethodMatcherPointcutA @Autowired private ApplicationEventPublisher eventPublisher; + private final Map defineCache = new ConcurrentReferenceHashMap<>(); + + private static final LoggerDefine UNSUPPORTED = new LoggerDefine(); + + @SuppressWarnings("all") public ReactiveAopAccessLoggerSupport() { setAdvice((MethodInterceptor) methodInvocation -> { MethodInterceptorHolder methodInterceptorHolder = MethodInterceptorHolder.create(methodInvocation); @@ -55,23 +61,34 @@ public ReactiveAopAccessLoggerSupport() { }); } + private Mono currentRequestInfo() { + return Mono + .subscriberContext() + .handle((context, sink) -> { + if (context.hasKey(RequestInfo.class)) { + RequestInfo info = context.get(RequestInfo.class); + ReactiveLogger.log(context, info::setContext); + sink.next(info); + } + }); + } + protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { - return Mono.subscriberContext() - .flatMap(ctx -> Mono.justOrEmpty(ctx.getOrEmpty(RequestInfo.class)) - .doOnNext(info -> ReactiveLogger.log(ctx, info::setContext))) + return this + .currentRequestInfo() .doOnNext(loggerInfo::putAccessInfo) .thenMany(flux) .doOnError(loggerInfo::setException) .doFinally(f -> { loggerInfo.setResponseTime(System.currentTimeMillis()); eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo)); - }).subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + }) + .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); } protected Mono wrapMonoResponse(Mono mono, AccessLoggerInfo loggerInfo) { - return Mono.subscriberContext() - .flatMap(ctx -> Mono.justOrEmpty(ctx.getOrEmpty(RequestInfo.class)) - .doOnNext(info -> ReactiveLogger.log(ctx, info::setContext))) + return this + .currentRequestInfo() .doOnNext(loggerInfo::putAccessInfo) .then(mono) .doOnError(loggerInfo::setException) @@ -79,20 +96,26 @@ protected Mono wrapMonoResponse(Mono mono, AccessLoggerInfo loggerInfo) { .doFinally(f -> { loggerInfo.setResponseTime(System.currentTimeMillis()); eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo)); - }).subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + }) + .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + } + + private LoggerDefine createDefine(MethodInterceptorHolder holder) { + return loggerParsers + .stream() + .filter(parser -> parser.support(ClassUtils.getUserClass(holder.getTarget()), holder.getMethod())) + .findAny() + .map(parser -> parser.parse(holder)) + .orElse(UNSUPPORTED); } @SuppressWarnings("all") protected AccessLoggerInfo createLogger(MethodInterceptorHolder holder) { AccessLoggerInfo info = new AccessLoggerInfo(); info.setId(IDGenerator.MD5.generate()); - info.setRequestTime(System.currentTimeMillis()); - LoggerDefine define = loggerParsers.stream() - .filter(parser -> parser.support(ClassUtils.getUserClass(holder.getTarget()), holder.getMethod())) - .findAny() - .map(parser -> parser.parse(holder)) - .orElse(null); + + LoggerDefine define = defineCache.computeIfAbsent(holder.getMethod(), method -> createDefine(holder)); if (define != null) { info.setAction(define.getAction()); @@ -113,14 +136,14 @@ protected AccessLoggerInfo createLogger(MethodInterceptorHolder holder) { continue; } if (val instanceof Mono) { - args[i] = ((Mono) val) + args[i] = ((Mono) val) .doOnNext(param -> { value.put(name, param); }); } else if (val instanceof Flux) { List arr = new ArrayList<>(); value.put(name, arr); - args[i] = ((Flux) val) + args[i] = ((Flux) val) .doOnNext(param -> { arr.add(param); }); @@ -143,7 +166,9 @@ public int getOrder() { @Override public boolean matches(Method method, Class aClass) { - return loggerParsers.stream().anyMatch(parser -> parser.support(aClass, method)); + return loggerParsers + .stream() + .anyMatch(parser -> parser.support(aClass, method)); } @Override diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ResourceAccessLoggerParser.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ResourceAccessLoggerParser.java index acf42e5b3..faf351128 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ResourceAccessLoggerParser.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ResourceAccessLoggerParser.java @@ -22,7 +22,7 @@ public class ResourceAccessLoggerParser implements AccessLoggerParser { )); @Override - public boolean support(Class clazz, Method method) { + public boolean support(Class clazz, Method method) { Set a1 = AnnotatedElementUtils.findAllMergedAnnotations(method, annotations); Set a2 = AnnotatedElementUtils.findAllMergedAnnotations(clazz, annotations); diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/Swagger3AccessLoggerParser.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/Swagger3AccessLoggerParser.java index c0b91a8c7..12de9191b 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/Swagger3AccessLoggerParser.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/Swagger3AccessLoggerParser.java @@ -12,7 +12,7 @@ public class Swagger3AccessLoggerParser implements AccessLoggerParser { @Override - public boolean support(Class clazz, Method method) { + public boolean support(Class clazz, Method method) { Tag api = AnnotationUtils.findAnnotation(clazz, Tag.class); Operation operation = AnnotationUtils.findAnnotation(method, Operation.class); diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/SwaggerAccessLoggerParser.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/SwaggerAccessLoggerParser.java index 408ab7d33..2ac75180b 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/SwaggerAccessLoggerParser.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/SwaggerAccessLoggerParser.java @@ -11,7 +11,7 @@ public class SwaggerAccessLoggerParser implements AccessLoggerParser { @Override - public boolean support(Class clazz, Method method) { + public boolean support(Class clazz, Method method) { Api api = AnnotationUtils.findAnnotation(clazz, Api.class); ApiOperation operation = AnnotationUtils.findAnnotation(method, ApiOperation.class); From 4131aa3653efc77622128b4444a2bd0d1063bb53 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 4 Jan 2022 15:00:39 +0800 Subject: [PATCH 021/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/web/CommonWebMvcConfiguration.java | 2 ++ .../web/crud/web/ResponseMessageWrapperAdvice.java | 1 - hsweb-core/pom.xml | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebMvcConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebMvcConfiguration.java index b310160e8..cb72e93e4 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebMvcConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebMvcConfiguration.java @@ -1,5 +1,6 @@ package org.hswebframework.web.crud.web; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -9,6 +10,7 @@ @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) +@ConditionalOnClass(org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice.class) public class CommonWebMvcConfiguration { @Bean diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java index 8728f13cf..b57bcc504 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java @@ -13,7 +13,6 @@ import org.springframework.http.server.ServerHttpResponse; import org.springframework.util.CollectionUtils; import org.springframework.util.MimeType; -import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 4dfe92bb4..a45bbb244 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -20,18 +20,22 @@ javassist 3.28.0-GA + com.fasterxml.jackson.core jackson-databind + org.hswebframework hsweb-utils + org.springframework spring-context + org.springframework spring-web From a9c625648d10d811670be94d5b0b54ee0c526a5e Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 6 Jan 2022 09:27:26 +0800 Subject: [PATCH 022/416] 4.0.13 --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 2 +- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index 260044351..3e0b543e6 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index 4cee3010c..7feeaf2e0 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index b1ed31100..ae2b152e5 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index ca288ae27..bbd184af8 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index f273b989f..f3ad81381 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index 2f03314e7..ba1fd7f3e 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index 49956e019..33fae8613 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index b48abe970..b0f9524fa 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index 256a58bd1..92e5f1712 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index a45bbb244..46dd45ddd 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index 7add8016e..0de58de02 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 6291e1e5b..50111f82a 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index fa7a74e6e..d6fb038b6 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index f10f0f041..6bf9f6f4b 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index b264011c3..a3e501d1d 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index a1417bb87..28404502a 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index 607ebd984..647087ca1 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 1b75183c0..f5734c051 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index 459e8e1ed..00049fb01 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index db9703dc3..86cdc693f 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index fe06e8d32..e09542425 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index 5d42aacb4..944c194fc 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index 9b98e9b81..0c4d96f2a 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index 041afbbf9..1a0ed1765 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index d28ee529b..7bb080bc9 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13-SNAPSHOT + 4.0.13 ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 870043527..61561dc00 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.13-SNAPSHOT + 4.0.13 hsweb-starter hsweb-core From 6515aa31582f760d587743df71d443ea74cb7d30 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 19 Jan 2022 17:25:28 +0800 Subject: [PATCH 023/416] 4.0.14-SNAPSHOT --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 8 +++++++- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 32 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index 3e0b543e6..b78ebb166 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index 7feeaf2e0..1d9548f1c 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index ae2b152e5..cfd6f7ffa 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index bbd184af8..eae29abb9 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index f3ad81381..e8b562365 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index ba1fd7f3e..3d80c02ed 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index 33fae8613..a95048ed0 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index b0f9524fa..27e913412 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index 92e5f1712..678172be7 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 46dd45ddd..9e83cf5aa 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index 0de58de02..017bd92ca 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 50111f82a..494446890 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index d6fb038b6..6d4b217fb 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index 6bf9f6f4b..c9449114e 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index a3e501d1d..51d34eb87 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index 28404502a..323d43ddb 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index 647087ca1..c0b0adaa1 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index f5734c051..5970be36b 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index 00049fb01..0958d3092 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 @@ -34,6 +34,12 @@ commons-codec commons-codec + + org.hswebframework.web + hsweb-commons-crud + ${project.version} + compile + \ No newline at end of file diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index 86cdc693f..c5269c3f5 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index e09542425..9a2488316 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index 944c194fc..081cf8074 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index 0c4d96f2a..00ee64ca2 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index 1a0ed1765..c0f869ecc 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index 7bb080bc9..eb48a52e7 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.13 + 4.0.14-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 61561dc00..7747c72c5 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.13 + 4.0.14-SNAPSHOT hsweb-starter hsweb-core From 554fdc2ed48ccb8e1c7e5798b0bad70357762f13 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 19 Jan 2022 17:26:12 +0800 Subject: [PATCH 024/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0DimensionDeletedEvent?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6,=E5=9C=A8=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E7=BB=B4=E5=BA=A6=E6=95=B0=E6=8D=AE=E8=A2=AB=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=97=B6,=E9=9C=80=E8=A6=81=E6=8E=A8=E9=80=81=E6=AD=A4?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/event/DimensionDeletedEvent.java | 12 ++++++++++++ .../api/event/UserDeletedEvent.java | 16 +++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/DimensionDeletedEvent.java diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/DimensionDeletedEvent.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/DimensionDeletedEvent.java new file mode 100644 index 000000000..833031d82 --- /dev/null +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/DimensionDeletedEvent.java @@ -0,0 +1,12 @@ +package org.hswebframework.web.system.authorization.api.event; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.hswebframework.web.event.DefaultAsyncEvent; + +@Getter +@AllArgsConstructor +public class DimensionDeletedEvent extends DefaultAsyncEvent { + private final String dimensionType; + private final String dimensionId; +} diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserDeletedEvent.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserDeletedEvent.java index 8bb299139..219b7530b 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserDeletedEvent.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/UserDeletedEvent.java @@ -1,18 +1,16 @@ package org.hswebframework.web.system.authorization.api.event; -import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.hswebframework.web.event.DefaultAsyncEvent; +import org.hswebframework.web.authorization.DefaultDimensionType; import org.hswebframework.web.system.authorization.api.entity.UserEntity; @Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class UserDeletedEvent extends DefaultAsyncEvent { +public class UserDeletedEvent extends DimensionDeletedEvent { - private UserEntity user; + private final UserEntity user; + public UserDeletedEvent(UserEntity user) { + super(DefaultDimensionType.user.getId(), user.getId()); + this.user = user; + } } From 54194e8cbbfa4f51019da932f5ed426ed5dd1566 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 19 Jan 2022 17:26:54 +0800 Subject: [PATCH 025/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/AuthorizationSettingEntity.java | 2 + .../DefaultAuthorizationSettingService.java | 144 +++++++++--------- ...aultReactiveAuthenticationManagerTest.java | 9 ++ 3 files changed, 82 insertions(+), 73 deletions(-) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java index f22009d01..9ef0a8470 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java @@ -9,6 +9,7 @@ import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec; import org.hswebframework.web.api.crud.entity.Entity; import org.hswebframework.web.bean.FastBeanCopier; +import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.validator.CreateGroup; import org.springframework.util.CollectionUtils; @@ -27,6 +28,7 @@ }) @Getter @Setter +@EnableEntityEvent public class AuthorizationSettingEntity implements Entity { @Id @Column(length = 32) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java index ad5350040..9988da900 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java @@ -6,13 +6,19 @@ import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult; import org.hswebframework.web.authorization.DimensionProvider; import org.hswebframework.web.authorization.DimensionType; +import org.hswebframework.web.crud.events.EntityCreatedEvent; +import org.hswebframework.web.crud.events.EntityDeletedEvent; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; import org.hswebframework.web.crud.service.GenericReactiveCrudService; import org.hswebframework.web.system.authorization.api.entity.AuthorizationSettingEntity; import org.hswebframework.web.system.authorization.api.event.ClearUserAuthorizationCacheEvent; +import org.hswebframework.web.system.authorization.api.event.DimensionDeletedEvent; import org.hswebframework.web.system.authorization.defaults.configuration.PermissionProperties; import org.reactivestreams.Publisher; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -30,7 +36,6 @@ public class DefaultAuthorizationSettingService extends GenericReactiveCrudServi @Autowired private List providers; - protected AuthorizationSettingEntity generateId(AuthorizationSettingEntity entity) { if (StringUtils.isEmpty(entity.getId())) { entity.setId(DigestUtils.md5Hex(entity.getPermission() + entity.getDimensionType() + entity.getDimensionTarget())); @@ -42,28 +47,7 @@ protected AuthorizationSettingEntity generateId(AuthorizationSettingEntity entit public Mono save(Publisher entityPublisher) { return Flux.from(entityPublisher) .map(this::generateId) - .collectList() - .flatMap(autz -> super.save(Flux.fromIterable(autz)).doOnSuccess(r -> clearUserAuthCache(autz))); - } - - @Override - public Mono updateById(String id, Mono entityPublisher) { - return entityPublisher - .flatMap(autz -> super.updateById(id, Mono.just(autz)) - .doOnSuccess((r) -> clearUserAuthCache(Collections.singletonList(autz)))); - } - - @Override - public Mono deleteById(Publisher idPublisher) { - Flux cache = Flux.from(idPublisher); - - return this - .findById(cache) - .collectList() - .flatMap(list -> this - .deleteById(cache) - .doOnSuccess((i) -> clearUserAuthCache(list)) - ); + .as(super::save); } @Override @@ -71,68 +55,82 @@ public Mono insert(Publisher entityPublishe return Flux.from(entityPublisher) .map(this::generateId) - .collectList() - .flatMap(list -> super - .insert(Flux.fromIterable(list)) - .doOnSuccess(i -> clearUserAuthCache(list))); + .as(super::insert); } @Override public Mono insertBatch(Publisher> entityPublisher) { return Flux .from(entityPublisher) + .doOnNext(list -> list.forEach(this::generateId)) + .as(super::insertBatch); + } + + protected Mono clearUserAuthCache(List settings) { + return Flux + .fromIterable(providers) + .flatMap(provider -> + //按维度类型进行映射 + provider.getAllType() + .map(DimensionType::getId) + .map(t -> Tuples.of(t, provider))) + .collect(Collectors.toMap(Tuple2::getT1, Tuple2::getT2)) + .flatMapMany(typeProviderMapping -> Flux + .fromIterable(settings)//根据维度获取所有userId + .flatMap(setting -> Mono + .justOrEmpty(typeProviderMapping.get(setting.getDimensionType())) + .flatMapMany(provider -> provider.getUserIdByDimensionId(setting.getDimensionTarget())))) .collectList() - .flatMap(list -> super - .insertBatch(Flux.fromStream(list.stream() - .map(lst -> lst.stream() - .map(this::generateId) - .collect(Collectors.toList())))) - .doOnSuccess(i -> clearUserAuthCache(list - .stream() - .flatMap(Collection::stream) - .collect(Collectors.toList())))); + .map(ClearUserAuthorizationCacheEvent::of) + .doOnNext(eventPublisher::publishEvent) + .then(); } - @Override - public ReactiveUpdate createUpdate() { - - return super - .createUpdate() - .onExecute((update, r) -> r - .doOnSuccess(i -> this - .createQuery() - .setParam(update.toQueryParam()) - .fetch() - .collectList() - .subscribe(this::clearUserAuthCache))); + @EventListener + public void handleAuthSettingDeleted(EntityDeletedEvent event) { + event.async( + clearUserAuthCache(event.getEntity()) + ); } - @Override - public ReactiveDelete createDelete() { - return super.createDelete() - .onExecute((delete, r) -> r - .doOnSuccess(i -> this - .createQuery() - .setParam(delete.toQueryParam()) - .fetch() - .collectList() - .subscribe(this::clearUserAuthCache))); + @EventListener + public void handleAuthSettingChanged(EntityModifyEvent event) { + event.async( + clearUserAuthCache(event.getAfter()) + ); + } + + @EventListener + public void handleAuthSettingSaved(EntitySavedEvent event) { + event.async( + clearUserAuthCache(event.getEntity()) + ); + } + + @EventListener + public void handleAuthSettingAdded(EntityCreatedEvent event) { + event.async( + clearUserAuthCache(event.getEntity()) + ); + } + + @EventListener + public void handleDimensionAdd(DimensionDeletedEvent event) { + event.async( + createDelete() + .where(AuthorizationSettingEntity::getDimensionType, event.getDimensionType()) + .and(AuthorizationSettingEntity::getDimensionTarget, event.getDimensionId()) + .execute() + ); } - protected void clearUserAuthCache(List settings) { - Flux.fromIterable(providers) - .flatMap(provider -> - //按维度类型进行映射 - provider.getAllType() - .map(DimensionType::getId) - .map(t -> Tuples.of(t, provider))) - .collect(Collectors.toMap(Tuple2::getT1, Tuple2::getT2)) - .flatMapMany(typeProviderMapping -> Flux - .fromIterable(settings)//根据维度获取所有userId - .flatMap(setting -> Mono.justOrEmpty(typeProviderMapping.get(setting.getDimensionType())) - .flatMapMany(provider -> provider.getUserIdByDimensionId(setting.getDimensionTarget())))) - .collectList() - .map(ClearUserAuthorizationCacheEvent::of) - .subscribe(eventPublisher::publishEvent); + @EventListener + public void handleDimensionDeletedEvent(DimensionDeletedEvent event) { + event.async( + createDelete() + .where(AuthorizationSettingEntity::getDimensionType, event.getDimensionType()) + .and(AuthorizationSettingEntity::getDimensionTarget, event.getDimensionId()) + .execute() + ); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveAuthenticationManagerTest.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveAuthenticationManagerTest.java index 424d02e9c..07beab561 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveAuthenticationManagerTest.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/reactive/DefaultReactiveAuthenticationManagerTest.java @@ -93,11 +93,20 @@ public void test() { .as(StepVerifier::create) .expectNext(true) .verifyComplete(); + userService.deleteUser(entity.getId()) .as(StepVerifier::create) .expectNext(true) .verifyComplete(); + settingRepository.createQuery() + .where(AuthorizationSettingEntity::getDimensionType,"user") + .and(AuthorizationSettingEntity::getDimensionTarget,entity.getId()) + .fetch() + .as(StepVerifier::create) + .expectNextCount(0) + .verifyComplete(); + } } \ No newline at end of file From bc5e68a09bfa2d8fd26e8954f520e321534f227e Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 19 Jan 2022 18:36:41 +0800 Subject: [PATCH 026/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=B4=E5=BA=A6?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=BB=91=E5=AE=9A=E8=A7=A3=E7=BB=91=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/AuthorizationSettingEntity.java | 1 + .../api/entity/DimensionEntity.java | 2 + .../api/entity/DimensionUserEntity.java | 5 +- .../DefaultAuthorizationSettingService.java | 12 + .../service/DefaultDimensionService.java | 77 ++----- .../service/DefaultDimensionUserService.java | 125 ++++++----- .../DefaultDimensionUserServiceTest.java | 208 ++++++++++++++++++ 7 files changed, 314 insertions(+), 116 deletions(-) create mode 100644 hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserServiceTest.java diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java index 9ef0a8470..435663f8a 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java @@ -67,6 +67,7 @@ public class AuthorizationSettingEntity implements Entity { @Comment("状态") @NotNull(message = "状态不能为空",groups = CreateGroup.class) @Schema(description = "状态,0禁用,1启用") + @DefaultValue("1") private Byte state; @Column diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java index 0056a12ed..d4ec1e83f 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java @@ -7,6 +7,7 @@ import org.hswebframework.ezorm.rdb.mapping.annotation.Comment; import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec; import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity; +import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.validator.CreateGroup; import javax.persistence.Column; @@ -24,6 +25,7 @@ @Table(name = "s_dimension", indexes = { @Index(name = "idx_dims_path", columnList = "path") }) +@EnableEntityEvent public class DimensionEntity extends GenericTreeSortSupportEntity { @Override diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java index 752361a18..827d5a744 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java @@ -7,6 +7,7 @@ import org.hswebframework.ezorm.rdb.mapping.annotation.Comment; import org.hswebframework.ezorm.rdb.mapping.annotation.EnumCodec; import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.dict.EnumDict; import org.hswebframework.web.system.authorization.api.enums.DimensionUserFeature; import org.springframework.util.DigestUtils; @@ -26,6 +27,7 @@ @Index(name = "idx_dimsu_user_id", columnList = "user_id"), }) +@EnableEntityEvent public class DimensionUserEntity extends GenericEntity { @Comment("维度类型ID") @@ -40,13 +42,14 @@ public class DimensionUserEntity extends GenericEntity { @Comment("维度名称") @Column(name = "dimension_name", nullable = false) - @NotBlank(message = "[dimensionName]不能为空") + @NotBlank @Schema(description = "维度名称") private String dimensionName; @Comment("用户ID") @Column(name = "user_id", nullable = false, length = 64) @Schema(description = "用户ID") + @NotBlank private String userId; @Comment("用户名") diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java index 9988da900..b71960930 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java @@ -43,6 +43,18 @@ protected AuthorizationSettingEntity generateId(AuthorizationSettingEntity entit return entity; } + @Override + public Mono save(AuthorizationSettingEntity data) { + generateId(data); + return super.save(data); + } + + @Override + public Mono save(Collection collection) { + collection.forEach(this::generateId); + return super.save(collection); + } + @Override public Mono save(Publisher entityPublisher) { return Flux.from(entityPublisher) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java index bd702d177..abcbda00d 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionService.java @@ -1,36 +1,30 @@ package org.hswebframework.web.system.authorization.defaults.service; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections4.BidiMap; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.bidimap.DualHashBidiMap; -import org.apache.commons.collections4.multimap.HashSetValuedHashMap; -import org.hswebframework.ezorm.rdb.mapping.ReactiveDelete; 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.authorization.Dimension; import org.hswebframework.web.authorization.DimensionProvider; import org.hswebframework.web.authorization.DimensionType; import org.hswebframework.web.authorization.dimension.DimensionUserBind; import org.hswebframework.web.authorization.dimension.DimensionUserBindProvider; -import org.hswebframework.web.crud.service.GenericReactiveCrudService; +import org.hswebframework.web.crud.events.EntityDeletedEvent; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; import org.hswebframework.web.crud.service.GenericReactiveTreeSupportCrudService; -import org.hswebframework.web.crud.service.ReactiveCrudService; -import org.hswebframework.web.crud.service.ReactiveTreeSortEntityService; import org.hswebframework.web.id.IDGenerator; -import org.hswebframework.web.system.authorization.api.entity.AuthorizationSettingEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionTypeEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionUserEntity; import org.hswebframework.web.system.authorization.api.event.ClearUserAuthorizationCacheEvent; -import org.reactivestreams.Publisher; +import org.hswebframework.web.system.authorization.api.event.DimensionDeletedEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.util.*; +import java.util.Collection; +import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; @@ -45,9 +39,6 @@ public class DefaultDimensionService @Autowired private ReactiveRepository dimensionTypeRepository; - @Autowired - private ReactiveRepository settingRepository; - @Autowired private ApplicationEventPublisher eventPublisher; @@ -131,53 +122,23 @@ public Flux getUserIdByDimensionId(String dimensionId) { .map(DimensionUserEntity::getUserId); } - @Override - public Mono save(Publisher entityPublisher) { - return super.save(entityPublisher) - .doOnSuccess((r) -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all())); - } - - @Override - public Mono updateById(String id, Mono entityPublisher) { - return super.updateById(id, entityPublisher) - .doOnSuccess((r) -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all())); + @EventListener + public void handleDimensionChanged(EntitySavedEvent event) { + eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all()); } - @Override - public ReactiveUpdate createUpdate() { - return super.createUpdate() - .onExecute((update, result) -> result.doOnSuccess((r) -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all()))); + @EventListener + public void handleDimensionChanged(EntityModifyEvent event) { + eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all()); } - @Override - public ReactiveDelete createDelete() { - return super.createDelete() - .onExecute((delete, result) -> result.doOnSuccess((r) -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all()))); - } + @EventListener + public void dispatchDimensionDeleteEvent(EntityDeletedEvent event) { - @Override - public Mono deleteById(Publisher idPublisher) { - - return Flux.from(idPublisher) - .collectList() - .flatMap(list -> super.queryIncludeChildren(list) - .flatMap(dimension -> dimensionUserRepository.createDelete() //删除维度用户关联 - .where() - .is(DimensionUserEntity::getDimensionId, dimension.getId()) - .execute() - .then(getRepository().deleteById(Mono.just(dimension.getId()))) - .thenReturn(dimension) - ) - .groupBy(DimensionEntity::getTypeId, DimensionEntity::getId)//按维度类型分组 - .flatMap(grouping -> grouping.collectList() - .flatMap(dimensionId -> settingRepository //删除权限设置 - .createDelete() - .where(AuthorizationSettingEntity::getDimensionType, grouping.key()) - .in(AuthorizationSettingEntity::getDimensionTarget, dimensionId) - .execute())) - .collect(Collectors.summarizingInt(Integer::intValue)) - .doOnSuccess((r) -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.all())) - .thenReturn(list.size())); + event.async( + Flux.fromIterable(event.getEntity()) + .flatMap(e -> new DimensionDeletedEvent(e.getTypeId(), e.getId()).publish(eventPublisher)) + ); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java index f3c8d7e7c..2ab396a51 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java @@ -5,9 +5,14 @@ import org.hswebframework.ezorm.rdb.mapping.ReactiveDelete; import org.hswebframework.ezorm.rdb.mapping.ReactiveUpdate; import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult; +import org.hswebframework.web.crud.events.EntityCreatedEvent; +import org.hswebframework.web.crud.events.EntityDeletedEvent; +import org.hswebframework.web.crud.events.EntityModifyEvent; +import org.hswebframework.web.crud.events.EntitySavedEvent; import org.hswebframework.web.crud.service.GenericReactiveCrudService; import org.hswebframework.web.event.AsyncEvent; import org.hswebframework.web.exception.BusinessException; +import org.hswebframework.web.system.authorization.api.entity.DimensionEntity; import org.hswebframework.web.system.authorization.api.entity.DimensionUserEntity; import org.hswebframework.web.system.authorization.api.event.ClearUserAuthorizationCacheEvent; import org.hswebframework.web.system.authorization.api.event.DimensionBindEvent; @@ -22,8 +27,13 @@ import reactor.function.Function3; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.function.Function; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.*; @Slf4j public class DefaultDimensionUserService extends GenericReactiveCrudService { @@ -31,6 +41,7 @@ public class DefaultDimensionUserService extends GenericReactiveCrudService save(Publisher entityPublisher) { - return this - .publishEvent(entityPublisher, DimensionBindEvent::new) - .as(super::save); + //转发保存维度信息到DimensionBindEvent事件,并清空权限缓存 + @EventListener + public void dispatchDimensionBind(EntitySavedEvent event) { + event.async( + this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionBindEvent::new) + .then( + this.clearUserCache(event.getEntity()) + ) + ); } - @Override - public Mono updateById(String id, Mono entityPublisher) { - return entityPublisher - .doOnNext(entity -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of(entity.getUserId()))) - .as(e -> super.updateById(id, e)); + //新增绑定时转发DimensionBindEvent并清空用户权限信息 + @EventListener + public void dispatchDimensionBind(EntityCreatedEvent event) { + event.async( + this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionBindEvent::new) + .then( + this.clearUserCache(event.getEntity()) + ) + ); } - @Override - public Mono insert(Publisher entityPublisher) { - return this - .publishEvent(entityPublisher, DimensionBindEvent::new) - .as(super::insert) - .onErrorMap(DuplicateKeyException.class, (err) -> new BusinessException("error.duplicate_key")); + //删除绑定时转发DimensionUnbindEvent并清空用户权限信息 + @EventListener + public void dispatchDimensionUnbind(EntityDeletedEvent event) { + event.async( + this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionUnbindEvent::new) + .then( + this.clearUserCache(event.getEntity()) + ) + ); } - @Override - public Mono insertBatch(Publisher> entityPublisher) { + //修改绑定信息时清空权限 + @EventListener + public void handleModifyEvent(EntityModifyEvent event) { + event.async( + this.clearUserCache(event.getAfter()) + ); + } - Flux> cache = Flux.from(entityPublisher).cache(); + //维度被删除时同时删除绑定信息 + @EventListener + public void handleDimensionDeletedEntity(EntityDeletedEvent event) { + event.async( + Flux.fromIterable(event.getEntity()) + .collect(groupingBy(DimensionEntity::getTypeId, + mapping(DimensionEntity::getId, toSet()))) + .flatMapIterable(Map::entrySet) + .flatMap(entry -> this + .createDelete() + .where(DimensionUserEntity::getDimensionTypeId, entry.getKey()) + .in(DimensionUserEntity::getDimensionId, entry.getValue()) + .execute()) + ); - return this - .publishEvent(cache.flatMapIterable(Function.identity()), DimensionBindEvent::new) - .then(super.insertBatch(cache)); } private Flux publishEvent(Publisher stream, @@ -83,7 +120,6 @@ private Flux publishEvent(Publisher st .groupBy(DimensionUserEntity::getDimensionId) .flatMap(dimensionIdGroup -> { String dimensionId = dimensionIdGroup.key(); - return dimensionIdGroup .map(DimensionUserEntity::getUserId) .collectList() @@ -96,39 +132,14 @@ private Flux publishEvent(Publisher st .thenMany(cache); } - @Override - @SuppressWarnings("all") - public ReactiveUpdate createUpdate() { - return super - .createUpdate() - .onExecute((update, r) -> r - .flatMap(result -> this - .createQuery() - .select(DimensionUserEntity::getUserId) - .setParam(update.toQueryParam()) - .fetch() - .map(DimensionUserEntity::getUserId) - .distinct() - .collectList() - .map(ClearUserAuthorizationCacheEvent::of) - .doOnNext(eventPublisher::publishEvent) - .thenReturn(result) - ) - ); + private Mono clearUserCache(List entities) { + return Flux.fromIterable(entities) + .map(DimensionUserEntity::getUserId) + .distinct() + .collectList() + .map(ClearUserAuthorizationCacheEvent::of) + .doOnNext(eventPublisher::publishEvent) + .then(); } - @Override - @SuppressWarnings("all") - public ReactiveDelete createDelete() { - return super - .createDelete() - .onExecute((delete, r) -> this - .publishEvent(this.createQuery() - .select(DimensionUserEntity::getUserId) - .setParam(delete.toQueryParam()) - .fetch(), - DimensionUnbindEvent::new - ).then(r) - ); - } -} +} \ No newline at end of file diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserServiceTest.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserServiceTest.java new file mode 100644 index 000000000..4009026e3 --- /dev/null +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/test/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserServiceTest.java @@ -0,0 +1,208 @@ +package org.hswebframework.web.system.authorization.defaults.service; + +import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; +import org.hswebframework.web.authorization.AuthenticationManager; +import org.hswebframework.web.authorization.ReactiveAuthenticationManager; +import org.hswebframework.web.system.authorization.api.entity.*; +import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService; +import org.hswebframework.web.system.authorization.defaults.service.reactive.ReactiveTestApplication; +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; + +import static org.junit.Assert.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ReactiveTestApplication.class) +public class DefaultDimensionUserServiceTest { + + @Autowired + private ReactiveUserService userService; + + @Autowired + private ReactiveRepository typeRepository; + + @Autowired + private DefaultDimensionService dimensionService; + + @Autowired + private DefaultDimensionUserService dimensionUserService; + + @Autowired + private DefaultAuthorizationSettingService settingService; + + @Autowired + private ReactiveAuthenticationManager authenticationManager; + + @Test + public void testDeleteBind() { + String dimensionType = "role"; + String dimensionId = "testDeleteBind"; + String userId = initData(dimensionType, dimensionId); + + //删除绑定关系 + dimensionUserService + .createDelete() + .where(DimensionUserEntity::getUserId, userId) + .execute() + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + //校验权限 + authenticationManager + .getByUserId(userId) + .map(auth -> !auth.hasDimension(dimensionType, dimensionId)) + .as(StepVerifier::create) + .expectNext(true) + .verifyComplete(); + + //权限设置并没有被删除 + settingService + .createQuery() + .where(AuthorizationSettingEntity::getDimensionType, dimensionType) + .and(AuthorizationSettingEntity::getDimensionTarget, dimensionId) + .count() + .as(StepVerifier::create) + .expectNext(1) + .verifyComplete(); + + } + + @Test + public void testDeleteDimension() { + String dimensionType = "role"; + String dimensionId = "testDeleteDimension"; + String userId = initData(dimensionType, dimensionId); + + //删除维度 + dimensionService + .deleteById(dimensionId) + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + //判断没有维度 + authenticationManager + .getByUserId(userId) + .map(auth -> !auth.hasDimension(dimensionType, dimensionId)) + .as(StepVerifier::create) + .expectNext(true) + .verifyComplete(); + + //权限设置也被删除 + settingService + .createQuery() + .where(AuthorizationSettingEntity::getDimensionType, dimensionType) + .and(AuthorizationSettingEntity::getDimensionTarget, dimensionId) + .count() + .as(StepVerifier::create) + .expectNext(0) + .verifyComplete(); + + + } + + @Test + public void testDeleteUser() { + String dimensionType = "role"; + String dimensionId = "test"; + + String userId = initData(dimensionType, dimensionId); + + userService.deleteUser(userId) + .as(StepVerifier::create) + .expectNext(true) + .verifyComplete(); + + authenticationManager + .getByUserId(userId) + .as(StepVerifier::create) + .expectNextCount(0) + .verifyComplete(); + + + dimensionUserService + .createQuery() + .where(DimensionUserEntity::getUserId, userId) + .count() + .as(StepVerifier::create) + .expectNext(0) + .verifyComplete(); + + } + + + private String initData(String dimensionType, String dimensionId) { + UserEntity userEntity = userService.newUserInstance().blockOptional().orElseThrow(NullPointerException::new); + userEntity.setName("test"); + userEntity.setUsername("test_" + dimensionId); + userEntity.setPassword("admin"); + userService.saveUser(Mono.just(userEntity)) + .as(StepVerifier::create) + .expectNext(true) + .verifyComplete(); + + DimensionTypeEntity type = new DimensionTypeEntity(); + type.setId(dimensionType); + type.setName(dimensionType); + typeRepository.save(type) + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + DimensionEntity dimension = new DimensionEntity(); + dimension.setId(dimensionId); + dimension.setTypeId(dimensionType); + dimension.setName(dimensionId); + + dimensionService + .save(dimension) + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + DimensionUserEntity bind = new DimensionUserEntity(); + bind.setDimensionId(dimension.getId()); + bind.setDimensionTypeId(dimension.getTypeId()); + bind.setDimensionName(dimension.getName()); + bind.setUserId(userEntity.getId()); + bind.setUserName(userEntity.getName()); + dimensionUserService + .save(bind) + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + AuthorizationSettingEntity setting = new AuthorizationSettingEntity(); + setting.setDimensionType(dimension.getTypeId()); + setting.setDimensionTarget(dimension.getId()); + setting.setPermission("test"); + + settingService + .insert(setting) + .then() + .as(StepVerifier::create) + .expectComplete() + .verify(); + + authenticationManager + .getByUserId(userEntity.getId()) + .map(auth -> auth.hasDimension(dimensionType, dimensionId)) + .as(StepVerifier::create) + .expectNext(true) + .verifyComplete(); + + return userEntity.getId(); + } + +} \ No newline at end of file From abf7f91c923f3f81b319560fa262367e1ad37469 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 19 Jan 2022 18:36:59 +0800 Subject: [PATCH 027/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E8=81=9A=E5=90=88=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/service/ReactiveTreeSortEntityService.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java index 64f14a28c..66de7ca0e 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java @@ -12,6 +12,7 @@ import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.math.MathFlux; import java.util.*; import java.util.function.Consumer; @@ -335,12 +336,12 @@ default Mono updateById(K id, Mono entityPublisher) { @Override default Mono deleteById(Publisher idPublisher) { - return findById(Flux.from(idPublisher)) - .flatMap(e -> createDelete() - .where() - .like$(e::getPath) - .execute()) - .collect(Collectors.summingInt(Integer::intValue)); + return this + .findById(Flux.from(idPublisher)) + .concatMap(e -> StringUtils.hasText(e.getPath()) + ? createDelete().where().like$(e::getPath).execute() + : getRepository().deleteById(e.getId())) + .as(MathFlux::sumInt); } IDGenerator getIDGenerator(); From 8b21574e23b71f023ffb043145660fa1225d9db9 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 25 Jan 2022 09:20:56 +0800 Subject: [PATCH 028/416] =?UTF-8?q?=E4=BC=98=E5=8C=96DigestUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/utils/DigestUtils.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java index 246a6dbd2..ac58189f4 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/DigestUtils.java @@ -3,6 +3,8 @@ import org.apache.commons.codec.binary.Hex; import java.security.MessageDigest; +import java.util.function.Consumer; +import java.util.function.Supplier; public class DigestUtils { @@ -10,6 +12,30 @@ public class DigestUtils { public static final ThreadLocal sha256 = ThreadLocal.withInitial(org.apache.commons.codec.digest.DigestUtils::getSha256Digest); public static final ThreadLocal sha1 = ThreadLocal.withInitial(org.apache.commons.codec.digest.DigestUtils::getSha1Digest); + public static byte[] md5(Consumer digestHandler) { + return digest(md5::get, digestHandler); + } + + public static String md5Hex(Consumer digestHandler) { + return digestHex(md5::get, digestHandler); + } + + public static byte[] sha1(Consumer digestHandler) { + return digest(sha1::get, digestHandler); + } + + public static String sha1Hex(Consumer digestHandler) { + return digestHex(sha1::get, digestHandler); + } + + public static byte[] sha256(Consumer digestHandler) { + return digest(sha256::get, digestHandler); + } + + public static String sha256Hex(Consumer digestHandler) { + return digestHex(sha1::get, digestHandler); + } + public static byte[] md5(byte[] data) { return org.apache.commons.codec.digest.DigestUtils.digest(md5.get(), data); } @@ -57,4 +83,16 @@ public static byte[] digest(MessageDigest digest, String str) { public static String digestHex(MessageDigest digest, String str) { return Hex.encodeHexString(digest(digest, str)); } + + private static byte[] digest(Supplier digestSupplier, + Consumer digestHandler) { + MessageDigest digest = digestSupplier.get(); + digestHandler.accept(digest); + return digest.digest(); + } + + private static String digestHex(Supplier digestSupplier, + Consumer digestHandler) { + return Hex.encodeHexString(digest(digestSupplier, digestHandler)); + } } From e5158ed3b27d60f37d538868c4b344e05a8015e4 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 25 Jan 2022 15:39:29 +0800 Subject: [PATCH 029/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../define/AuthorizeDefinitionContext.java | 7 ++++ .../define/AuthorizeDefinitionCustomizer.java | 7 ++++ ...ompositeAuthorizeDefinitionCustomizer.java | 24 +++++++++++ .../define/MergedAuthorizeDefinition.java | 6 +-- ...ultAopMethodAuthorizeDefinitionParser.java | 18 +++++++- .../web/api/crud/entity/QueryParamEntity.java | 24 +++++++++-- .../EnableCacheReactiveCrudService.java | 42 ++++++++++++++----- .../ReactiveServiceQueryController.java | 12 +++--- .../web/cache/ReactiveCache.java | 21 +++++----- .../web/bean/FastBeanCopier.java | 1 - ...AuthorizationServiceAutoConfiguration.java | 9 +++- .../service/PermissionSynchronization.java | 16 +++++-- 12 files changed, 146 insertions(+), 41 deletions(-) create mode 100644 hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionContext.java create mode 100644 hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionCustomizer.java create mode 100644 hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/CompositeAuthorizeDefinitionCustomizer.java diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionContext.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionContext.java new file mode 100644 index 000000000..8b69af611 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionContext.java @@ -0,0 +1,7 @@ +package org.hswebframework.web.authorization.define; + +public interface AuthorizeDefinitionContext { + + void addResource(ResourceDefinition def); + +} diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionCustomizer.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionCustomizer.java new file mode 100644 index 000000000..b0fe8d320 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/AuthorizeDefinitionCustomizer.java @@ -0,0 +1,7 @@ +package org.hswebframework.web.authorization.define; + +public interface AuthorizeDefinitionCustomizer { + + void custom(AuthorizeDefinitionContext context); + +} diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/CompositeAuthorizeDefinitionCustomizer.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/CompositeAuthorizeDefinitionCustomizer.java new file mode 100644 index 000000000..54af14835 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/CompositeAuthorizeDefinitionCustomizer.java @@ -0,0 +1,24 @@ +package org.hswebframework.web.authorization.define; + +import lombok.AllArgsConstructor; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@AllArgsConstructor +public class CompositeAuthorizeDefinitionCustomizer implements AuthorizeDefinitionCustomizer{ + + private final List customizers; + + public CompositeAuthorizeDefinitionCustomizer(Iterable customizers){ + this(StreamSupport.stream(customizers.spliterator(),false).collect(Collectors.toList())); + } + + @Override + public void custom(AuthorizeDefinitionContext context) { + for (AuthorizeDefinitionCustomizer customizer : customizers) { + customizer.custom(context); + } + } +} diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/MergedAuthorizeDefinition.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/MergedAuthorizeDefinition.java index 94d32070d..b247c7a0c 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/MergedAuthorizeDefinition.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/MergedAuthorizeDefinition.java @@ -4,11 +4,11 @@ import java.util.Set; -public class MergedAuthorizeDefinition { +public class MergedAuthorizeDefinition implements AuthorizeDefinitionContext { - private ResourcesDefinition resources = new ResourcesDefinition(); + private final ResourcesDefinition resources = new ResourcesDefinition(); - private DimensionsDefinition dimensions = new DimensionsDefinition(); + private final DimensionsDefinition dimensions = new DimensionsDefinition(); public Set getResources() { return resources.getResources(); diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java index 0a5f9efaf..6b3c96afe 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java @@ -6,6 +6,7 @@ import org.hswebframework.web.authorization.annotation.Authorize; import org.hswebframework.web.authorization.annotation.DataAccess; import org.hswebframework.web.authorization.annotation.Dimension; +import org.hswebframework.web.authorization.annotation.ResourceAction; import org.hswebframework.web.authorization.basic.define.DefaultBasicAuthorizeDefinition; import org.hswebframework.web.authorization.basic.define.EmptyAuthorizeDefinition; import org.hswebframework.web.authorization.define.AuthorizeDefinition; @@ -15,8 +16,10 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -63,7 +66,8 @@ public AuthorizeDefinition parse(Class target, Method method, MethodIntercept } //使用自定义 if (!CollectionUtils.isEmpty(parserCustomizers)) { - definition = parserCustomizers.stream() + definition = parserCustomizers + .stream() .map(customizer -> customizer.parse(target, method, context)) .filter(Objects::nonNull) .findAny().orElse(null); @@ -77,7 +81,7 @@ public AuthorizeDefinition parse(Class target, Method method, MethodIntercept Authorize annotation = AnnotationUtils.findAnnotation(target, method, Authorize.class); - if (annotation != null && annotation.ignore()) { + if (isIgnoreMethod(method) || (annotation != null && annotation.ignore())) { cache.put(key, EmptyAuthorizeDefinition.instance); return null; } @@ -107,4 +111,14 @@ public void destroy() { cache.clear(); } + static boolean isIgnoreMethod(Method method) { + //不是public的方法 + if(!Modifier.isPublic(method.getModifiers())){ + return true; + } + //没有以下注解 + return null == AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class) + && null == AnnotatedElementUtils.findMergedAnnotation(method, ResourceAction.class); + } + } diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java index 680d51589..fadebf1d1 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/QueryParamEntity.java @@ -10,9 +10,11 @@ import org.apache.commons.collections.CollectionUtils; import org.hswebframework.ezorm.core.NestConditional; import org.hswebframework.ezorm.core.dsl.Query; +import org.hswebframework.ezorm.core.param.Param; import org.hswebframework.ezorm.core.param.QueryParam; import org.hswebframework.ezorm.core.param.Term; import org.hswebframework.ezorm.core.param.TermType; +import org.hswebframework.web.bean.FastBeanCopier; import org.springframework.util.StringUtils; @@ -26,11 +28,11 @@ * 可通过静态方法创建:
* 如: *
- *{@code
+ * {@code
  *      QueryParamEntity.of("id",id);
- *}
+ * }
  * 
- * + *

* 或者使用DSL方式来构造: *

{@code
  *  QueryParamEntity
@@ -97,6 +99,20 @@ public Set getExcludes() {
         return super.getExcludes();
     }
 
+    /**
+     * 基于另外一个条件参数来创建查询条件实体
+     *
+     * @param param 参数
+     * @return 新的查询条件
+     * @since 4.0.14
+     */
+    public static QueryParamEntity of(Param param) {
+        if (param instanceof QueryParamEntity) {
+            return ((QueryParamEntity) param).clone();
+        }
+        return FastBeanCopier.copy(param, new QueryParamEntity());
+    }
+
     /**
      * 创建一个空的查询参数实体,该实体无任何参数.
      *
@@ -217,7 +233,7 @@ public QueryParamEntity noPaging() {
         return this;
     }
 
-    public QueryParamEntity doNotSort(){
+    public QueryParamEntity doNotSort() {
         this.setSorts(new ArrayList<>());
         return this;
     }
diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/EnableCacheReactiveCrudService.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/EnableCacheReactiveCrudService.java
index d152b5e36..272ecd4e5 100644
--- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/EnableCacheReactiveCrudService.java
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/EnableCacheReactiveCrudService.java
@@ -9,6 +9,7 @@
 import reactor.core.publisher.Mono;
 
 import java.util.Collection;
+import java.util.function.Function;
 
 public interface EnableCacheReactiveCrudService extends ReactiveCrudService {
 
@@ -16,8 +17,8 @@ public interface EnableCacheReactiveCrudService extends ReactiveCrudServic
 
     default Mono findById(K id) {
         return this.getCache()
-                .mono("id:" + id)
-                .onCacheMissResume(ReactiveCrudService.super.findById(Mono.just(id)));
+                   .mono("id:" + id)
+                   .onCacheMissResume(ReactiveCrudService.super.findById(Mono.just(id)));
     }
 
     @Override
@@ -27,44 +28,65 @@ default Mono findById(Mono publisher) {
 
     @Override
     default Mono updateById(K id, Mono entityPublisher) {
-        return ReactiveCrudService.super.updateById(id, entityPublisher)
+        return ReactiveCrudService.super
+                .updateById(id, entityPublisher)
                 .doFinally(i -> getCache().evict("id:" + id).subscribe());
     }
 
+    @Override
+    default Mono save(E data) {
+        return ReactiveCrudService.super
+                .save(data)
+                .doFinally(i -> getCache().clear().subscribe());
+    }
+
     @Override
     default Mono save(Publisher entityPublisher) {
-        return ReactiveCrudService.super.save(entityPublisher)
+        return ReactiveCrudService.super
+                .save(entityPublisher)
+                .doFinally(i -> getCache().clear().subscribe());
+    }
+
+    @Override
+    default Mono insert(E data) {
+        return ReactiveCrudService.super
+                .insert(data)
                 .doFinally(i -> getCache().clear().subscribe());
     }
 
     @Override
     default Mono insert(Publisher entityPublisher) {
-        return ReactiveCrudService.super.insert(entityPublisher)
+        return ReactiveCrudService.super
+                .insert(entityPublisher)
                 .doFinally(i -> getCache().clear().subscribe());
     }
 
     @Override
     default Mono insertBatch(Publisher> entityPublisher) {
-        return ReactiveCrudService.super.insertBatch(entityPublisher)
+        return ReactiveCrudService.super
+                .insertBatch(entityPublisher)
                 .doFinally(i -> getCache().clear().subscribe());
     }
 
     @Override
     default Mono deleteById(Publisher idPublisher) {
-        return Flux.from(idPublisher)
-                .doOnNext(id -> this.getCache().evict("id:" + id).subscribe())
+        return Flux
+                .from(idPublisher)
+                .flatMap(id -> this.getCache().evict("id:" + id).thenReturn(id))
                 .as(ReactiveCrudService.super::deleteById);
     }
 
     @Override
     default ReactiveUpdate createUpdate() {
-        return ReactiveCrudService.super.createUpdate()
+        return ReactiveCrudService.super
+                .createUpdate()
                 .onExecute((update, s) -> s.doFinally((__) -> getCache().clear().subscribe()));
     }
 
     @Override
     default ReactiveDelete createDelete() {
-        return ReactiveCrudService.super.createDelete()
+        return ReactiveCrudService.super
+                .createDelete()
                 .onExecute((update, s) -> s.doFinally((__) -> getCache().clear().subscribe()));
     }
 }
diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java
index ef0f074a1..51eed4f7f 100644
--- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java
@@ -72,9 +72,9 @@ default Flux query(@Parameter(hidden = true) QueryParamEntity query) {
      */
     @PostMapping("/_query/no-paging")
     @QueryAction
-    @QueryNoPagingOperation(summary = "使用POST方式分页动态查询(不返回总数)",
+    @Operation(summary = "使用POST方式分页动态查询(不返回总数)",
             description = "此操作不返回分页总数,如果需要获取全部数据,请设置参数paging=false")
-    default Flux query(@Parameter(hidden = true) @RequestBody Mono query) {
+    default Flux query(@RequestBody Mono query) {
         return query.flatMapMany(this::query);
     }
 
@@ -133,8 +133,8 @@ default Mono> queryPager(@Parameter(hidden = true) QueryParamEnti
     @PostMapping("/_query")
     @QueryAction
     @SuppressWarnings("all")
-    @QueryOperation(summary = "使用POST方式分页动态查询")
-    default Mono> queryPager(@Parameter(hidden = true) @RequestBody Mono query) {
+    @Operation(summary = "使用POST方式分页动态查询")
+    default Mono> queryPager(@RequestBody Mono query) {
         return query.flatMap(q -> queryPager(q));
     }
 
@@ -165,8 +165,8 @@ default Mono> queryPager(@Parameter(hidden = true) @RequestBody M
      */
     @PostMapping("/_count")
     @QueryAction
-    @QueryNoPagingOperation(summary = "使用POST方式查询总数")
-    default Mono count(@Parameter(hidden = true) @RequestBody Mono query) {
+    @Operation(summary = "使用POST方式查询总数")
+    default Mono count(@RequestBody Mono query) {
         return query.flatMap(this::count);
     }
 
diff --git a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/ReactiveCache.java b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/ReactiveCache.java
index 0411631ae..6b5f0f971 100644
--- a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/ReactiveCache.java
+++ b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/ReactiveCache.java
@@ -26,19 +26,20 @@ public interface ReactiveCache {
     Mono clear();
 
     default CacheFlux.FluxCacheBuilderMapMiss flux(Object key) {
-        return otherSupplier ->
-                Flux.defer(() ->
-                        getFlux(key)
-                                .switchIfEmpty(otherSupplier.get()
-                                        .collectList()
-                                        .flatMapMany(values -> put(key, Flux.fromIterable(values))
-                                                .thenMany(Flux.fromIterable(values)))));
+        return otherSupplier -> Flux
+                .defer(() -> this
+                        .getFlux(key)
+                        .switchIfEmpty(otherSupplier.get()
+                                                    .collectList()
+                                                    .flatMapMany(values -> put(key, Flux.fromIterable(values))
+                                                            .thenMany(Flux.fromIterable(values)))));
     }
 
     default CacheMono.MonoCacheBuilderMapMiss mono(Object key) {
-        return otherSupplier ->
-                Mono.defer(() -> getMono(key)
+        return otherSupplier -> Mono
+                .defer(() -> this
+                        .getMono(key)
                         .switchIfEmpty(otherSupplier.get()
-                                .flatMap(value -> put(key, Mono.just(value)).thenReturn(value))));
+                                                    .flatMap(value -> put(key, Mono.just(value)).thenReturn(value))));
     }
 }
diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
index 066da714a..b80d23bf0 100644
--- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
+++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
@@ -20,7 +20,6 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.Supplier;
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java
index a8f5e2f95..2d80c4fba 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java
@@ -3,13 +3,17 @@
 import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
 import org.hswebframework.web.authorization.ReactiveAuthenticationInitializeService;
 import org.hswebframework.web.authorization.ReactiveAuthenticationManagerProvider;
+import org.hswebframework.web.authorization.define.AuthorizeDefinitionCustomizer;
+import org.hswebframework.web.authorization.define.CompositeAuthorizeDefinitionCustomizer;
 import org.hswebframework.web.authorization.simple.DefaultAuthorizationAutoConfiguration;
 import org.hswebframework.web.authorization.token.UserTokenManager;
 import org.hswebframework.web.system.authorization.api.UserDimensionProvider;
+import org.hswebframework.web.system.authorization.api.entity.PermissionEntity;
 import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService;
 import org.hswebframework.web.system.authorization.defaults.service.*;
 import org.hswebframework.web.system.authorization.defaults.service.terms.DimensionTerm;
 import org.hswebframework.web.system.authorization.defaults.service.terms.UserDimensionTerm;
+import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.boot.autoconfigure.AutoConfigureBefore;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
@@ -41,8 +45,9 @@ public ReactiveAuthenticationInitializeService reactiveAuthenticationInitializeS
         }
 
         @Bean
-        public PermissionSynchronization permissionSynchronization() {
-            return new PermissionSynchronization();
+        public PermissionSynchronization permissionSynchronization(ReactiveRepository permissionRepository,
+                                                                   ObjectProvider customizer) {
+            return new PermissionSynchronization(permissionRepository, new CompositeAuthorizeDefinitionCustomizer(customizer));
         }
 
         @Bean
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java
index 7a153619e..bd8baa237 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/PermissionSynchronization.java
@@ -26,13 +26,20 @@
 @Slf4j
 public class PermissionSynchronization implements CommandLineRunner {
 
-    @Autowired
-    private ReactiveRepository permissionRepository;
+    private final ReactiveRepository permissionRepository;
+
+    private final AuthorizeDefinitionCustomizer customizer;
 
     private final MergedAuthorizeDefinition definition = new MergedAuthorizeDefinition();
 
     private final Map> entityFieldsMapping = new HashMap<>();
 
+    public PermissionSynchronization(ReactiveRepository permissionRepository,
+                                     AuthorizeDefinitionCustomizer customizer) {
+        this.permissionRepository = permissionRepository;
+        this.customizer = customizer;
+    }
+
     @EventListener
     public void handleResourceParseEvent(AuthorizeDefinitionInitializedEvent event) {
         definition.merge(event.getAllDefinition());
@@ -115,7 +122,10 @@ public void run(String... args) throws Exception {
         if (definition.getResources().isEmpty()) {
             return;
         }
-        permissionRepository.createQuery()
+        customizer.custom(definition);
+
+        permissionRepository
+                .createQuery()
                 .fetch()
                 .collect(Collectors.toMap(PermissionEntity::getId, Function.identity()))
                 .flatMap(group -> Flux.fromIterable(definition.getResources())

From daaa6b47a6532cdf0926ccd3cb6cf97399f424fd Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Wed, 9 Feb 2022 09:39:27 +0800
Subject: [PATCH 030/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0getProperty?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../web/bean/FastBeanCopier.java              |  12 +-
 .../web/bean/SingleValueMap.java              | 108 ++++++++++++++++++
 2 files changed, 117 insertions(+), 3 deletions(-)
 create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java

diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
index b80d23bf0..a4930a267 100644
--- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
+++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
@@ -87,6 +87,12 @@ public boolean contains(Object o) {
         };
     }
 
+    public static Object getProperty(Object source, String key) {
+        SingleValueMap map = new SingleValueMap<>();
+        copy(source, map, include(key));
+        return map.getValue();
+    }
+
     public static  T copy(S source, T target, String... ignore) {
         return copy(source, target, DEFAULT_CONVERT, ignore);
     }
@@ -571,7 +577,7 @@ public  T convert(Object source, Class targetClass, Class[] genericType) {
                 return (T) collection;
             }
 
-            if (target.isEnumType()){
+            if (target.isEnumType()) {
                 if (target.isEnumDict()) {
                     String strVal = String.valueOf(source);
 
@@ -609,11 +615,11 @@ public  T convert(Object source, Class targetClass, Class[] genericType) {
 
                 //快速复制map
                 if (targetClass == Map.class) {
-                    if(source instanceof Map) {
+                    if (source instanceof Map) {
                         return (T) new HashMap(((Map) source));
                     }
                     ClassDescription sourType = ClassDescriptions.getDescription(source.getClass());
-                    return (T)copy(source, Maps.newHashMapWithExpectedSize(sourType.getFieldSize()));
+                    return (T) copy(source, Maps.newHashMapWithExpectedSize(sourType.getFieldSize()));
                 }
 
                 return copy(source, beanFactory.newInstance(targetClass), this);
diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java
new file mode 100644
index 000000000..08c024c61
--- /dev/null
+++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java
@@ -0,0 +1,108 @@
+package org.hswebframework.web.bean;
+
+import java.util.*;
+
+public class SingleValueMap implements Map {
+    private K key;
+    private V value;
+
+    @Override
+    public int size() {
+        return value == null ? 0 : 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    @Override
+    public boolean containsKey(Object key) {
+        return Objects.equals(this.key, key);
+    }
+
+    @Override
+    public boolean containsValue(Object value) {
+        return Objects.equals(this.value, value);
+    }
+
+    @Override
+    public V get(Object key) {
+        return null;
+    }
+
+    @Override
+    public V put(K key, V value) {
+        this.key = key;
+        V old = this.value;
+        this.value = value;
+        return old;
+    }
+
+    @Override
+    public V remove(Object key) {
+        if (Objects.equals(key, this.key)) {
+            V old = this.value;
+            this.value = null;
+            return old;
+        }
+        return null;
+    }
+
+    @Override
+    public void putAll(Map m) {
+        if (m.size() > 0) {
+            Map.Entry entry = m.entrySet().iterator().next();
+            this.key = entry.getKey();
+            this.value = entry.getValue();
+        }
+    }
+
+    @Override
+    public void clear() {
+        this.key = null;
+        this.value = null;
+    }
+
+    @Override
+    public Set keySet() {
+        return key == null ? Collections.emptySet() : Collections.singleton(key);
+    }
+
+    @Override
+    public Collection values() {
+        return value == null ? Collections.emptySet() : Collections.singleton(value);
+    }
+
+    @Override
+    public Set> entrySet() {
+        return key == null ? Collections.emptySet() : Collections.singleton(
+                new Entry() {
+                    @Override
+                    public K getKey() {
+                        return key;
+                    }
+
+                    @Override
+                    public V getValue() {
+                        return value;
+                    }
+
+                    @Override
+                    public V setValue(V value) {
+                        V old = SingleValueMap.this.value;
+                        SingleValueMap.this.value = value;
+                        return old;
+                    }
+                }
+        );
+    }
+
+    public V getValue() {
+        return value;
+    }
+
+    public K getKey() {
+        return key;
+    }
+}

From 417a31e6fe0095241c05837dd1b1b8b413028c02 Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Wed, 9 Feb 2022 14:45:43 +0800
Subject: [PATCH 031/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=A1=A8=E7=BB=93?=
 =?UTF-8?q?=E6=9E=84=E8=87=AA=E5=AE=9A=E4=B9=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../CompositeEntityTableMetadataResolver.java |   6 +-
 .../configuration/EasyormConfiguration.java   | 126 ++++++++++++------
 .../TableMetadataCustomizer.java              |  41 ++++++
 pom.xml                                       |   2 +-
 4 files changed, 127 insertions(+), 48 deletions(-)
 create mode 100644 hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/TableMetadataCustomizer.java

diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/CompositeEntityTableMetadataResolver.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/CompositeEntityTableMetadataResolver.java
index 28606bbe7..c19e21585 100644
--- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/CompositeEntityTableMetadataResolver.java
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/CompositeEntityTableMetadataResolver.java
@@ -15,7 +15,7 @@ public class CompositeEntityTableMetadataResolver implements EntityTableMetadata
 
     private final List resolvers = new ArrayList<>();
 
-    private final Map> cache = new ConcurrentHashMap<>();
+    private final Map, AtomicReference> cache = new ConcurrentHashMap<>();
 
     public void addParser(EntityTableMetadataParser resolver) {
         resolvers.add(resolver);
@@ -33,9 +33,7 @@ private RDBTableMetadata doResolve(Class entityClass) {
                 .filter(Optional::isPresent)
                 .map(Optional::get)
                 .reduce((t1, t2) -> {
-                    for (RDBColumnMetadata column : t1.getColumns()) {
-                        t2.addColumn(column.clone());
-                    }
+                    t2.merge(t1);
                     return t2;
                 }).orElse(null);
     }
diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java
index 107f16be7..15714adf8 100644
--- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java
@@ -10,9 +10,12 @@
 import org.hswebframework.ezorm.rdb.mapping.EntityManager;
 import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType;
 import org.hswebframework.ezorm.rdb.mapping.jpa.JpaEntityTableMetadataParser;
+import org.hswebframework.ezorm.rdb.mapping.jpa.JpaEntityTableMetadataParserProcessor;
 import org.hswebframework.ezorm.rdb.mapping.parser.EntityTableMetadataParser;
+import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
 import org.hswebframework.ezorm.rdb.metadata.RDBDatabaseMetadata;
 import org.hswebframework.ezorm.rdb.metadata.RDBSchemaMetadata;
+import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata;
 import org.hswebframework.ezorm.rdb.operator.DatabaseOperator;
 import org.hswebframework.ezorm.rdb.operator.DefaultDatabaseOperator;
 import org.hswebframework.web.api.crud.entity.EntityFactory;
@@ -35,9 +38,13 @@
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
 import java.time.Duration;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 
 @Configuration
 @EnableConfigurationProperties(EasyormProperties.class)
@@ -61,49 +68,6 @@ public EntityFactory entityFactory(ObjectProvider custo
         return factory;
     }
 
-    @Bean
-    @ConditionalOnMissingBean
-    public EntityManager entityManager(EntityTableMetadataResolver resolver, EntityFactory entityFactory) {
-        return new EntityManager() {
-            @Override
-            @SneakyThrows
-            public  E newInstance(Class type) {
-                return entityFactory.newInstance(type);
-            }
-
-            @Override
-            public EntityColumnMapping getMapping(Class entity) {
-
-                return resolver.resolve(entityFactory.getInstanceType(entity, true))
-                               .getFeature(MappingFeatureType.columnPropertyMapping.createFeatureId(entity))
-                               .map(EntityColumnMapping.class::cast)
-                               .orElse(null);
-            }
-        };
-    }
-
-    @Bean
-    public DefaultEntityResultWrapperFactory defaultEntityResultWrapperFactory(EntityManager entityManager) {
-        return new DefaultEntityResultWrapperFactory(entityManager);
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public EntityTableMetadataResolver entityTableMappingResolver(List parsers) {
-        CompositeEntityTableMetadataResolver resolver = new CompositeEntityTableMetadataResolver();
-        parsers.forEach(resolver::addParser);
-        return resolver;
-    }
-
-    @Bean
-    @ConditionalOnMissingBean
-    public EntityTableMetadataParser jpaEntityTableMetadataParser(RDBDatabaseMetadata metadata) {
-        JpaEntityTableMetadataParser parser = new JpaEntityTableMetadataParser();
-        parser.setDatabaseMetadata(metadata);
-
-        return parser;
-    }
-
     @Bean
     @ConditionalOnMissingBean
     @SuppressWarnings("all")
@@ -182,4 +146,80 @@ public CurrentTimeGenerator currentTimeGenerator() {
         return new CurrentTimeGenerator();
     }
 
+    @Configuration
+    public static class EntityTableMetadataParserConfiguration {
+
+        @Bean
+        public DefaultEntityResultWrapperFactory defaultEntityResultWrapperFactory(EntityManager entityManager) {
+            return new DefaultEntityResultWrapperFactory(entityManager);
+        }
+
+        @Bean
+        @ConditionalOnMissingBean
+        public EntityManager entityManager(EntityTableMetadataResolver resolver, EntityFactory entityFactory) {
+            return new EntityManager() {
+                @Override
+                @SneakyThrows
+                public  E newInstance(Class type) {
+                    return entityFactory.newInstance(type);
+                }
+
+                @Override
+                public EntityColumnMapping getMapping(Class entity) {
+
+                    return resolver.resolve(entityFactory.getInstanceType(entity, true))
+                                   .getFeature(MappingFeatureType.columnPropertyMapping.createFeatureId(entity))
+                                   .map(EntityColumnMapping.class::cast)
+                                   .orElse(null);
+                }
+            };
+        }
+
+        @Bean
+        @ConditionalOnMissingBean
+        public EntityTableMetadataResolver entityTableMappingResolver(ObjectProvider parsers) {
+            CompositeEntityTableMetadataResolver resolver = new CompositeEntityTableMetadataResolver();
+            parsers.forEach(resolver::addParser);
+            return resolver;
+        }
+
+        @Bean
+        @ConditionalOnMissingBean
+        public EntityTableMetadataParser jpaEntityTableMetadataParser(RDBDatabaseMetadata metadata,
+                                                                      ObjectProvider customizers) {
+
+            JpaEntityTableMetadataParser parser = new JpaEntityTableMetadataParser() {
+
+                @Override
+                public Optional parseTableMetadata(Class entityType) {
+                    Optional tableOpt = super.parseTableMetadata(entityType);
+                    tableOpt.ifPresent(table -> {
+                        for (TableMetadataCustomizer customizer : customizers) {
+                            customizer.customTable(entityType, table);
+                        }
+                    });
+                    return tableOpt;
+                }
+
+                @Override
+                protected JpaEntityTableMetadataParserProcessor createProcessor(RDBTableMetadata table, Class type) {
+                    return new JpaEntityTableMetadataParserProcessor(table, type) {
+                        @Override
+                        protected void customColumn(PropertyDescriptor descriptor,
+                                                    Field field,
+                                                    RDBColumnMetadata column,
+                                                    Set annotations) {
+                            super.customColumn(descriptor, field, column, annotations);
+                            for (TableMetadataCustomizer customizer : customizers) {
+                                customizer.customColumn(type, descriptor, field, annotations, column);
+                            }
+                        }
+                    };
+                }
+            };
+            parser.setDatabaseMetadata(metadata);
+
+            return parser;
+        }
+    }
 }
diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/TableMetadataCustomizer.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/TableMetadataCustomizer.java
new file mode 100644
index 000000000..f31786433
--- /dev/null
+++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/TableMetadataCustomizer.java
@@ -0,0 +1,41 @@
+package org.hswebframework.web.crud.configuration;
+
+import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata;
+import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata;
+
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Set;
+
+/**
+ * 表结构自定义器,实现此接口来自定义表结构.
+ *
+ * @author zhouhao
+ * @since 4.0.14
+ */
+public interface TableMetadataCustomizer {
+
+    /**
+     * 自定义列,在列被解析后调用.
+     *
+     * @param entityType  实体类型
+     * @param descriptor  字段描述
+     * @param field       字段
+     * @param column      列定义
+     * @param annotations 字段上的注解
+     */
+    void customColumn(Class entityType,
+                      PropertyDescriptor descriptor,
+                      Field field,
+                      Set annotations,
+                      RDBColumnMetadata column);
+
+    /**
+     * 自定义表,在实体类被解析完成后调用.
+     *
+     * @param entityType 字段类型
+     * @param table      表结构
+     */
+    void customTable(Class entityType, RDBTableMetadata table);
+}
diff --git a/pom.xml b/pom.xml
index 7747c72c5..a2b0328d3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
         3.2.2
         1.6.12
 
-        4.0.12
+        4.0.14-SNAPSHOT
         3.0.2
         3.0.2
         2.7.0

From e57a9a48e2c7f215b801dcf6560e98d8d8774945 Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Wed, 9 Feb 2022 17:45:26 +0800
Subject: [PATCH 032/416] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?=
 =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BD=BF=E7=94=A8=E5=8E=9F=E5=A7=8B=E6=96=87?=
 =?UTF-8?q?=E4=BB=B6=E5=90=8D=E5=AD=98=E5=82=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../web/file/FileUploadProperties.java        | 21 ++++++++++++++-----
 .../file/service/LocalFileStorageService.java |  4 +++-
 .../file/web/ReactiveFileControllerTest.java  |  1 +
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java
index c1ccb742b..7412302de 100644
--- a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java
+++ b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java
@@ -22,6 +22,9 @@ public class FileUploadProperties {
 
     private String staticLocation = "/static";
 
+    //是否使用原始文件名进行存储
+    private boolean useOriginalFileName = false;
+
     private Set allowFiles;
 
     private Set denyFiles;
@@ -51,7 +54,7 @@ public boolean denied(String name, MediaType mediaType) {
             if (denyMediaType.contains(mediaType.toString())) {
                 return true;
             }
-            defaultDeny =  false;
+            defaultDeny = false;
         }
 
         if (CollectionUtils.isNotEmpty(allowMediaType)) {
@@ -67,16 +70,24 @@ public boolean denied(String name, MediaType mediaType) {
     public StaticFileInfo createStaticSavePath(String name) {
         String fileName = IDGenerator.SNOW_FLAKE_STRING.generate();
         String filePath = DateFormatter.toString(new Date(), "yyyyMMdd");
-        String absPath = staticFilePath.concat("/").concat(filePath);
+
         //文件后缀
         String suffix = name.contains(".") ?
                 name.substring(name.lastIndexOf(".")) : "";
 
-        new File(absPath).mkdirs();
         StaticFileInfo info = new StaticFileInfo();
 
-        info.location = staticLocation + "/" + filePath + "/" + fileName + suffix;
-        info.savePath = absPath + "/" + fileName + suffix;
+        if (useOriginalFileName) {
+            filePath = filePath + "/" + fileName;
+            fileName = name;
+        } else {
+            fileName = fileName + suffix;
+        }
+        String absPath = staticFilePath.concat("/").concat(filePath);
+        new File(absPath).mkdirs();
+
+        info.location = staticLocation + "/" + filePath + "/" + fileName;
+        info.savePath = absPath + "/" + fileName;
 
         return info;
     }
diff --git a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java
index de16cda82..4d46cd7db 100644
--- a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java
+++ b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java
@@ -5,6 +5,7 @@
 import org.hswebframework.web.file.FileUploadProperties;
 import org.springframework.http.codec.multipart.FilePart;
 import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
 
 import java.io.File;
 import java.io.InputStream;
@@ -55,6 +56,7 @@ public Mono saveFile(InputStream inputStream, String fileType) {
                         }
                         return info.getLocation();
                     }
-                });
+                })
+                .subscribeOn(Schedulers.boundedElastic());
     }
 }
diff --git a/hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/ReactiveFileControllerTest.java b/hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/ReactiveFileControllerTest.java
index 4b2211a5a..67ff2654a 100644
--- a/hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/ReactiveFileControllerTest.java
+++ b/hsweb-system/hsweb-system-file/src/test/java/org/hswebframework/web/file/web/ReactiveFileControllerTest.java
@@ -29,6 +29,7 @@ public class ReactiveFileControllerTest {
 
     static {
         System.setProperty("hsweb.file.upload.static-file-path","./target/upload");
+//        System.setProperty("hsweb.file.upload.use-original-file-name","true");
     }
 
     @Autowired

From a3543b34f237f15a59cbb7db419258e749778554 Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Mon, 21 Feb 2022 14:27:36 +0800
Subject: [PATCH 033/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E6=9C=9F?=
 =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hswebframework/web/bean/FastBeanCopier.java  | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
index a4930a267..23c6919c8 100644
--- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
+++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
@@ -88,7 +88,7 @@ public boolean contains(Object o) {
     }
 
     public static Object getProperty(Object source, String key) {
-        SingleValueMap map = new SingleValueMap<>();
+        SingleValueMap map = new SingleValueMap<>();
         copy(source, map, include(key));
         return map.getValue();
     }
@@ -542,7 +542,11 @@ public  T convert(Object source, Class targetClass, Class[] genericType) {
             }
             if (targetClass == Date.class) {
                 if (source instanceof String) {
-                    return (T) DateFormatter.fromString((String) source);
+                    T parsed = (T) DateFormatter.fromString((String) source);
+                    if (parsed == null) {
+                        return (T) converterByApache(Date.class, source);
+                    }
+                    return parsed;
                 }
                 if (source instanceof Number) {
                     return (T) new Date(((Number) source).longValue());
@@ -629,6 +633,14 @@ public  T convert(Object source, Class targetClass, Class[] genericType) {
             }
 //            return null;
         }
+
+        private Object converterByApache(Class targetClass, Object source) {
+            org.apache.commons.beanutils.Converter converter = convertUtils.lookup(targetClass);
+            if (null != converter) {
+                return converter.convert(targetClass, source);
+            }
+            return null;
+        }
     }
 
     @AllArgsConstructor

From d952c29e4dfd96e9d2e80a4045bfc6802b65fcda Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Mon, 7 Mar 2022 11:49:10 +0800
Subject: [PATCH 034/416] =?UTF-8?q?=E6=9D=83=E9=99=90=E5=A2=9E=E5=8A=A0?=
 =?UTF-8?q?=E5=88=9B=E5=BB=BA=E4=BA=BA=E5=92=8C=E4=BF=AE=E6=94=B9=E4=BA=BA?=
 =?UTF-8?q?=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../api/entity/PermissionEntity.java          | 23 ++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
index b3957ddd0..1e62c5554 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
@@ -7,7 +7,10 @@
 import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
 import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
+import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
+import org.hswebframework.web.api.crud.entity.RecordModifierEntity;
 import org.hswebframework.web.bean.FastBeanCopier;
+import org.hswebframework.web.crud.generator.Generators;
 import org.hswebframework.web.validator.CreateGroup;
 import org.springframework.util.CollectionUtils;
 
@@ -27,7 +30,7 @@
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class PermissionEntity extends GenericEntity {
+public class PermissionEntity extends GenericEntity implements RecordCreationEntity, RecordModifierEntity {
 
     @Override
     @Pattern(regexp = "^[0-9a-zA-Z_\\-]+$", message = "ID只能由数字,字母,下划线和中划线组成", groups = CreateGroup.class)
@@ -80,6 +83,24 @@ public String getId() {
     @Schema(description = "其他配置")
     private Map properties;
 
+    @Schema(description = "创建时间")
+    @Column(updatable = false)
+    @DefaultValue(generator = Generators.CURRENT_TIME)
+    private Long createTime;
+
+    @Schema(description = "创建人ID")
+    @Column(length = 64, updatable = false)
+    private String creatorId;
+
+    @Schema(description = "修改时间")
+    @Column
+    @DefaultValue(generator = Generators.CURRENT_TIME)
+    private Long modifyTime;
+
+    @Schema(description = "修改人ID")
+    @Column(length = 64, updatable = false)
+    private String modifierId;
+
     public PermissionEntity copy(Predicate actionFilter,
                                  Predicate fieldFilter) {
         PermissionEntity entity = FastBeanCopier.copy(this, new PermissionEntity());

From 82cb6877f5efa947c1e2f547e384ab07c173f2d9 Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Fri, 11 Mar 2022 16:31:17 +0800
Subject: [PATCH 035/416] fixed #197: upgrade spring-framework version

---
 pom.xml | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index a2b0328d3..3b9d30506 100644
--- a/pom.xml
+++ b/pom.xml
@@ -79,7 +79,7 @@
         1.8
         ${java.version}
 
-        2.3.11.RELEASE
+        2.3.12.RELEASE
 
         3.20.0-GA
         5.19.0.2
@@ -96,6 +96,7 @@
         2.7.0
 
         Arabba-SR10
+        5.2.19.RELEASE
     
 
     
@@ -399,6 +400,14 @@
                 1.9.4
             
 
+            
+                org.springframework
+                spring-framework-bom
+                ${spring-framework.version}
+                pom
+                import
+            
+
             
                 org.springframework.boot
                 spring-boot-dependencies

From 88f029b503ff0aadd98f22bc61897fe6dbd5a3b6 Mon Sep 17 00:00:00 2001
From: zhangji <125540670@qq.com>
Date: Fri, 11 Mar 2022 16:37:50 +0800
Subject: [PATCH 036/416] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=95=B0=E6=8D=AE?=
 =?UTF-8?q?=E8=A1=A8=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../authorization/api/entity/AuthorizationSettingEntity.java | 2 ++
 .../web/system/authorization/api/entity/DimensionEntity.java | 1 +
 .../system/authorization/api/entity/DimensionTypeEntity.java | 1 +
 .../system/authorization/api/entity/DimensionUserEntity.java | 1 +
 .../system/authorization/api/entity/PermissionEntity.java    | 1 +
 .../web/system/authorization/api/entity/UserEntity.java      | 5 +++++
 .../hswebframework/web/oauth2/entity/OAuth2ClientEntity.java | 2 ++
 .../web/dictionary/entity/DictionaryEntity.java              | 2 ++
 .../web/dictionary/entity/DictionaryItemEntity.java          | 2 ++
 9 files changed, 17 insertions(+)

diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java
index 435663f8a..753fec7e1 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/AuthorizationSettingEntity.java
@@ -26,6 +26,7 @@
         @Index(name = "idx_sasi_dss", columnList = "dimension_type,dimension_target,state desc"),
         @Index(name = "idx_sasi_pdd", columnList = "permission,dimension_type,dimension_target",unique = true)
 })
+@Comment("授权信息")
 @Getter
 @Setter
 @EnableEntityEvent
@@ -33,6 +34,7 @@ public class AuthorizationSettingEntity implements Entity {
     @Id
     @Column(length = 32)
     @GeneratedValue(generator = "md5")
+    @Schema(description = "ID")
     private String id;
 
     @Column(length = 32, nullable = false, updatable = false)
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
index d4ec1e83f..e7b383780 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
@@ -25,6 +25,7 @@
 @Table(name = "s_dimension", indexes = {
         @Index(name = "idx_dims_path", columnList = "path")
 })
+@Comment("权限纬度")
 @EnableEntityEvent
 public class DimensionEntity extends GenericTreeSortSupportEntity {
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
index 216c45b6d..eb6274a43 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
@@ -15,6 +15,7 @@
 @Getter
 @Setter
 @Table(name = "s_dimension_type")
+@Comment("纬度类型")
 public class DimensionTypeEntity extends GenericEntity implements DimensionType {
 
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
index 827d5a744..31972c751 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
@@ -27,6 +27,7 @@
         @Index(name = "idx_dimsu_user_id", columnList = "user_id"),
 
 })
+@Comment("用户纬度关联表")
 @EnableEntityEvent
 public class DimensionUserEntity extends GenericEntity {
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
index b3957ddd0..b170a998a 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/PermissionEntity.java
@@ -22,6 +22,7 @@
 import java.util.stream.Collectors;
 
 @Table(name = "s_permission")
+@Comment("权限信息")
 @Getter
 @Setter
 @Builder
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java
index 0b05f6c9d..d903669aa 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java
@@ -6,6 +6,7 @@
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.codec.digest.DigestUtils;
+import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
 import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
 import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
@@ -32,6 +33,7 @@
 @Table(name = "s_user",
         indexes = @Index(name = "user_username_idx", columnList = "username", unique = true)
 )
+@Comment("用户信息")
 public class UserEntity extends GenericEntity implements RecordCreationEntity {
 
     @Column(length = 128, nullable = false)
@@ -54,6 +56,7 @@ public class UserEntity extends GenericEntity implements RecordCreationE
     @Column(nullable = false)
     @ToString.Ignore(cover = false)
     @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+    @Schema(description = "加密盐值")
     @Hidden
     private String salt;
 
@@ -67,11 +70,13 @@ public class UserEntity extends GenericEntity implements RecordCreationE
     private Byte status;
 
     @Column(name = "creator_id", updatable = false)
+    @Schema(description = "创建者ID")
     @Hidden
     private String creatorId;
 
     @Column(name = "create_time", updatable = false)
     @DefaultValue(generator = "current_time")
+    @Schema(description = "创建时间")
     @Hidden
     private Long createTime;
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/entity/OAuth2ClientEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/entity/OAuth2ClientEntity.java
index 88274fc54..ca8677b09 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/entity/OAuth2ClientEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/entity/OAuth2ClientEntity.java
@@ -4,6 +4,7 @@
 import lombok.Getter;
 import lombok.Setter;
 import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
+import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
 import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
 import org.hswebframework.ezorm.rdb.mapping.annotation.EnumCodec;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
@@ -17,6 +18,7 @@
 import javax.validation.constraints.NotBlank;
 
 @Table(name = "s_oauth2_client")
+@Comment("OAuth2客户端")
 @Getter
 @Setter
 public class OAuth2ClientEntity extends GenericEntity {
diff --git a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java
index 6b95b7e37..7930d759f 100644
--- a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java
+++ b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryEntity.java
@@ -20,6 +20,7 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
+import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
 import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
 import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
@@ -37,6 +38,7 @@
  * @author hsweb-generator-online
  */
 @Table(name = "s_dictionary")
+@Comment("数据字典")
 @Getter
 @Setter
 public class DictionaryEntity extends GenericEntity implements RecordCreationEntity {
diff --git a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java
index ef74f9f2e..cdd4b3e11 100644
--- a/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java
+++ b/hsweb-system/hsweb-system-dictionary/src/main/java/org/hswebframework/web/dictionary/entity/DictionaryItemEntity.java
@@ -20,6 +20,7 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
+import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
 import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
 import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
 import org.hswebframework.web.dict.EnumDict;
@@ -39,6 +40,7 @@
         @Index(name = "idx_dic_item_ordinal",columnList = "ordinal"),
         @Index(name = "idx_dic_item_path",columnList = "path")
 })
+@Comment("数据字典选项")
 public class DictionaryItemEntity extends GenericTreeSortSupportEntity implements EnumDict {
     //字典id
     @Column(name = "dict_id", length = 64, updatable = false, nullable = false)

From 0db32e8598da7cd03b743004d262500b5cb6307e Mon Sep 17 00:00:00 2001
From: zhangji <125540670@qq.com>
Date: Fri, 11 Mar 2022 16:57:01 +0800
Subject: [PATCH 037/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=99=E5=AD=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../web/system/authorization/api/entity/DimensionEntity.java    | 2 +-
 .../system/authorization/api/entity/DimensionTypeEntity.java    | 2 +-
 .../system/authorization/api/entity/DimensionUserEntity.java    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
index e7b383780..78ee7f731 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
@@ -25,7 +25,7 @@
 @Table(name = "s_dimension", indexes = {
         @Index(name = "idx_dims_path", columnList = "path")
 })
-@Comment("权限纬度")
+@Comment("权限维度")
 @EnableEntityEvent
 public class DimensionEntity extends GenericTreeSortSupportEntity {
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
index eb6274a43..765230147 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionTypeEntity.java
@@ -15,7 +15,7 @@
 @Getter
 @Setter
 @Table(name = "s_dimension_type")
-@Comment("纬度类型")
+@Comment("维度类型")
 public class DimensionTypeEntity extends GenericEntity implements DimensionType {
 
 
diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
index 31972c751..c4cb157ba 100644
--- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
+++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionUserEntity.java
@@ -27,7 +27,7 @@
         @Index(name = "idx_dimsu_user_id", columnList = "user_id"),
 
 })
-@Comment("用户纬度关联表")
+@Comment("用户维度关联表")
 @EnableEntityEvent
 public class DimensionUserEntity extends GenericEntity {
 

From 789b5303d0fbe890f9bed67585706b730dbd92f6 Mon Sep 17 00:00:00 2001
From: zhouhao 
Date: Thu, 17 Mar 2022 11:40:46 +0800
Subject: [PATCH 038/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AF=B4=E6=98=8E?=
 =?UTF-8?q?=E9=94=99=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../authorization/ReactiveAuthenticationHolder.java  | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
index de756e4aa..ce7d204ae 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
@@ -29,13 +29,13 @@
 import java.util.stream.Collectors;
 
 /**
- * 权限获取器,用于静态方式获取当前登录用户的权限信息.
+ * 响应式权限保持器,用于响应式方式获取当前登录用户的权限信息.
  * 例如:
- * 
- *     @RequestMapping("/example")
- *     public ResponseMessage example(){
- *         Authorization auth = AuthorizationHolder.get();
- *         return ResponseMessage.ok();
+ * 
{@code
+ *     @RequestMapping("/example")
+ *     public Mono example(){
+ *         return ReactiveAuthenticationHolder.get();
+ *     }
  *     }
  * 
* From ddfe97e64130cf7f059d315218dbc7639533f23c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 17 Mar 2022 19:20:16 +0800 Subject: [PATCH 039/416] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8indexer=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EasyormRepositoryRegistrar.java | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java index 9fe25ff59..2beddadfc 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java @@ -23,11 +23,13 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import javax.persistence.Table; +import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.*; @@ -40,7 +42,16 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - private final MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(); + private final MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(); + + private String getResourceClassName(Resource resource) { + try { + return metadataReaderFactory.getMetadataReader(resource) + .getClassMetadata().getClassName(); + } catch (IOException e) { + return null; + } + } @SneakyThrows private Stream doGetResources(String packageStr) { @@ -50,6 +61,22 @@ private Stream doGetResources(String packageStr) { return Arrays.stream(resourcePatternResolver.getResources(path)); } + protected Set scanEntities(String[] packageStr) { + CandidateComponentsIndex index = CandidateComponentsIndexLoader.loadIndex(org.springframework.util.ClassUtils.getDefaultClassLoader()); + if (null == index) { + return Stream + .of(packageStr) + .flatMap(this::doGetResources) + .map(this::getResourceClassName) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + return Stream + .of(packageStr) + .flatMap(pkg -> index.getCandidateTypes(pkg, Table.class.getName()).stream()) + .collect(Collectors.toSet()); + } + @Override @SneakyThrows @SuppressWarnings("all") @@ -63,26 +90,12 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B boolean nonReactiveEnabled = Boolean.TRUE.equals(attr.get("nonReactive")); String[] arr = (String[]) attr.get("value"); -// Set resources = Arrays -// .stream(arr) -// .flatMap(this::doGetResources) -// .collect(Collectors.toSet()); Class[] anno = (Class[]) attr.get("annotation"); Set entityInfos = new HashSet<>(); CandidateComponentsIndex index = CandidateComponentsIndexLoader.loadIndex(org.springframework.util.ClassUtils.getDefaultClassLoader()); - Set entities = Stream - .of(arr) - .flatMap(_package -> { - return index - .getCandidateTypes(_package, Table.class.getName()) - .stream(); - }) - .collect(Collectors.toSet()); - for (String className : entities) { -// MetadataReader reader = metadataReaderFactory.getMetadataReader(resource); -// String className = reader.getClassMetadata().getClassName(); + for (String className : scanEntities(arr)) { Class entityType = org.springframework.util.ClassUtils.forName(className, null); if (Arrays.stream(anno) .noneMatch(ann -> AnnotationUtils.findAnnotation(entityType, ann) != null)) { From 33f83a24de00456a6dd8eee9b24de2c03c901711 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 18 Mar 2022 19:52:36 +0800 Subject: [PATCH 040/416] =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=93=8D=E5=BA=94=E5=BC=8F=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/ReactiveAopAccessLoggerSupport.java | 37 +++++++++++-------- .../hsweb-access-logging-api/pom.xml | 8 ++++ .../events/AccessLoggerAfterEvent.java | 3 +- .../events/AccessLoggerBeforeEvent.java | 3 +- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index 7afb1a897..09ac21852 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -9,6 +9,7 @@ import org.hswebframework.web.logging.AccessLoggerListener; import org.hswebframework.web.logging.LoggerDefine; import org.hswebframework.web.logging.events.AccessLoggerAfterEvent; +import org.hswebframework.web.logging.events.AccessLoggerBeforeEvent; import org.hswebframework.web.utils.ReactiveWebUtils; import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; import org.springframework.beans.factory.annotation.Autowired; @@ -67,37 +68,41 @@ private Mono currentRequestInfo() { .handle((context, sink) -> { if (context.hasKey(RequestInfo.class)) { RequestInfo info = context.get(RequestInfo.class); - ReactiveLogger.log(context, info::setContext); + ReactiveLogger.log(context, ctx -> info.setContext(new HashMap<>(ctx))); sink.next(info); } }); } protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { - return this + + Flux cache = this .currentRequestInfo() .doOnNext(loggerInfo::putAccessInfo) + .then(Mono.defer(() -> new AccessLoggerBeforeEvent(loggerInfo).publish(eventPublisher))) .thenMany(flux) - .doOnError(loggerInfo::setException) - .doFinally(f -> { + .cache(); + + return cache + .flatMap(ignore -> Mono.empty()) + .then(Mono.defer(() -> { loggerInfo.setResponseTime(System.currentTimeMillis()); - eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo)); + return new AccessLoggerAfterEvent(loggerInfo).publish(eventPublisher); + })) + .thenMany(cache) + .onErrorResume(err -> { + loggerInfo.setException(err); + loggerInfo.setResponseTime(System.currentTimeMillis()); + return new AccessLoggerAfterEvent(loggerInfo) + .publish(eventPublisher) + .then(Mono.error(err)); }) .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); } protected Mono wrapMonoResponse(Mono mono, AccessLoggerInfo loggerInfo) { - return this - .currentRequestInfo() - .doOnNext(loggerInfo::putAccessInfo) - .then(mono) - .doOnError(loggerInfo::setException) - .doOnSuccess(loggerInfo::setResponse) - .doFinally(f -> { - loggerInfo.setResponseTime(System.currentTimeMillis()); - eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo)); - }) - .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + return wrapFluxResponse(mono.flux(), loggerInfo) + .singleOrEmpty(); } private LoggerDefine createDefine(MethodInterceptorHolder holder) { diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index 323d43ddb..72dd5b811 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -13,5 +13,13 @@ hsweb-access-logging-api 访问日志API模块 + + + org.hswebframework.web + hsweb-core + ${project.version} + compile + + \ No newline at end of file diff --git a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerAfterEvent.java b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerAfterEvent.java index 1129a2eac..5cd153ef1 100644 --- a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerAfterEvent.java +++ b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerAfterEvent.java @@ -2,11 +2,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import org.hswebframework.web.event.DefaultAsyncEvent; import org.hswebframework.web.logging.AccessLoggerInfo; @AllArgsConstructor @Getter -public class AccessLoggerAfterEvent { +public class AccessLoggerAfterEvent extends DefaultAsyncEvent { private AccessLoggerInfo logger; } diff --git a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerBeforeEvent.java b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerBeforeEvent.java index f927cbc84..bf2c4b77b 100644 --- a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerBeforeEvent.java +++ b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/events/AccessLoggerBeforeEvent.java @@ -2,11 +2,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import org.hswebframework.web.event.DefaultAsyncEvent; import org.hswebframework.web.logging.AccessLoggerInfo; @AllArgsConstructor @Getter -public class AccessLoggerBeforeEvent { +public class AccessLoggerBeforeEvent extends DefaultAsyncEvent { private AccessLoggerInfo logger; } From 0da2441a6924f00049f3899b9e37251eb190c175 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 21 Mar 2022 18:25:12 +0800 Subject: [PATCH 041/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/event/AsyncEvent.java | 6 ++++++ .../web/event/DefaultAsyncEvent.java | 19 +++++++++++++++---- .../aop/ReactiveAopAccessLoggerSupport.java | 14 +++++++------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java b/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java index 100748047..774e24ef0 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java @@ -4,6 +4,8 @@ import org.springframework.context.ApplicationEventPublisher; import reactor.core.publisher.Mono; +import java.util.function.Function; + /** * 异步事件,使用响应式编程进行事件监听时,请使用此事件接口 * @@ -27,6 +29,10 @@ public interface AsyncEvent { */ void first(Publisher publisher); + void first(Function,Publisher> mapper); + + void async(Function,Publisher> mapper); + /** * 推送事件到 ApplicationEventPublisher * diff --git a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java index 0cc0d64a6..a076ee5ce 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java @@ -1,14 +1,15 @@ package org.hswebframework.web.event; -import lombok.Getter; import org.reactivestreams.Publisher; import org.springframework.context.ApplicationEventPublisher; import reactor.core.publisher.Mono; +import java.util.function.Function; + public class DefaultAsyncEvent implements AsyncEvent { - private Mono async = Mono.empty(); - private Mono first = Mono.empty(); + private Mono async = Mono.empty(); + private Mono first = Mono.empty(); private boolean hasListener; @@ -23,9 +24,19 @@ public synchronized void first(Publisher publisher) { this.first = Mono.from(publisher).then(first); } + @Override + public void first(Function, Publisher> mapper) { + this.first = Mono.from(mapper.apply(this.first)); + } + + @Override + public void async(Function, Publisher> mapper) { + this.async = Mono.from(mapper.apply(this.async)); + } + @Override public Mono getAsync() { - return this.first.then(this.async); + return this.first.then(this.async).then(); } @Override diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index 09ac21852..b033de238 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -76,15 +76,15 @@ private Mono currentRequestInfo() { protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { - Flux cache = this + Flux cache = flux.cache(); + return this .currentRequestInfo() .doOnNext(loggerInfo::putAccessInfo) - .then(Mono.defer(() -> new AccessLoggerBeforeEvent(loggerInfo).publish(eventPublisher))) - .thenMany(flux) - .cache(); - - return cache - .flatMap(ignore -> Mono.empty()) + .then(Mono.defer(() -> { + AccessLoggerBeforeEvent event = new AccessLoggerBeforeEvent(loggerInfo); + event.first(cache); + return event.publish(eventPublisher); + })) .then(Mono.defer(() -> { loggerInfo.setResponseTime(System.currentTimeMillis()); return new AccessLoggerAfterEvent(loggerInfo).publish(eventPublisher); From 7666ea5f099737a298cdcdfe5417dc5c79d3285c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 24 Mar 2022 16:48:53 +0800 Subject: [PATCH 042/416] =?UTF-8?q?=E4=BC=98=E5=8C=96i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/I18nSupportException.java | 21 +++++++++- .../web/exception/ValidationException.java | 42 ++++++++++++++----- .../web/validator/ValidatorUtilsTest.java | 30 +++++++++---- 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java index ea77021c3..2218c4972 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java @@ -5,6 +5,10 @@ import lombok.Getter; import lombok.Setter; import org.hswebframework.web.i18n.LocaleUtils; +import reactor.core.publisher.Mono; + +import java.util.Locale; +import java.util.Objects; /** * 支持国际化消息的异常,code为 @@ -45,11 +49,24 @@ public I18nSupportException(String code, Throwable cause, Object... args) { @Override public String getMessage() { + if (Objects.equals(super.getMessage(), this.getI18nCode())) { + return getLocalizedMessage(); + } return super.getMessage() != null ? super.getMessage() : getLocalizedMessage(); } @Override - public String getLocalizedMessage() { - return LocaleUtils.resolveMessage(i18nCode, args); + public final String getLocalizedMessage() { + return getLocalizedMessage(LocaleUtils.current()); + } + + public String getLocalizedMessage(Locale locale) { + return LocaleUtils.resolveMessage(i18nCode, locale, getMessage(), args); + } + + public final Mono getLocalizedMessageReactive() { + return LocaleUtils + .currentReactive() + .map(this::getLocalizedMessage); } } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java index fc62966ed..2a1b0ba13 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java @@ -6,10 +6,13 @@ import lombok.Setter; import org.hswebframework.web.i18n.LocaleUtils; import org.springframework.http.HttpStatus; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ResponseStatus; import javax.validation.ConstraintViolation; import java.util.*; +import java.util.stream.Collectors; @Getter @Setter @@ -31,9 +34,6 @@ public ValidationException(String property, String message, Object... args) { public ValidationException(String message, List details, Object... args) { super(message, args); this.details = details; - for (Detail detail : this.details) { - detail.translateI18n(args); - } } public ValidationException(Set> violations) { @@ -48,23 +48,44 @@ public ValidationException(Set> violations) { //{0} 属性 ,{1} 验证消息 //property也支持国际化? - String resolveMessage = propertyI18nEnabled ? - LocaleUtils.resolveMessage(first.getRootBeanClass().getName() + "." + property, property) + String propertyI18n = propertyI18nEnabled ? + first.getRootBeanClass().getName() + "." + property : property; - setArgs(new Object[]{resolveMessage, first.getMessage()}); + setArgs(new Object[]{propertyI18n, first.getMessage()}); details = new ArrayList<>(violations.size()); for (ConstraintViolation violation : violations) { - details.add(new Detail(violation.getPropertyPath().toString(), violation.getMessage(), null)); + details.add(new Detail(violation.getPropertyPath().toString(), + violation.getMessage(), + null)); } } + public List getDetails(Locale locale) { + return CollectionUtils.isEmpty(details) + ? Collections.emptyList() + : details + .stream() + .map(detail -> detail.translateI18n(locale)) + .collect(Collectors.toList()); + } + + @Override + public String getLocalizedMessage(Locale locale) { + if (propertyI18nEnabled && "validation.property_validate_failed".equals(getI18nCode()) && getArgs().length > 0) { + Object[] args = getArgs().clone(); + args[0] = LocaleUtils.resolveMessage(String.valueOf(args[0]), locale, String.valueOf(args[0])); + return LocaleUtils.resolveMessage(getI18nCode(), locale, getMessage(), args); + } + return super.getLocalizedMessage(locale); + } @Getter @Setter @AllArgsConstructor public static class Detail { + @Schema(description = "字段") String property; @@ -74,10 +95,11 @@ public static class Detail { @Schema(description = "详情") Object detail; - public void translateI18n(Object... args) { - if (message.contains(".")) { - message = LocaleUtils.resolveMessage(message, message, args); + public Detail translateI18n(Locale locale) { + if (StringUtils.hasText(message) && message.contains(".")) { + return new Detail(property, LocaleUtils.resolveMessage(message, locale, message), detail); } + return this; } } } diff --git a/hsweb-core/src/test/java/org/hswebframework/web/validator/ValidatorUtilsTest.java b/hsweb-core/src/test/java/org/hswebframework/web/validator/ValidatorUtilsTest.java index 07ac1d5b9..ca8975c58 100644 --- a/hsweb-core/src/test/java/org/hswebframework/web/validator/ValidatorUtilsTest.java +++ b/hsweb-core/src/test/java/org/hswebframework/web/validator/ValidatorUtilsTest.java @@ -4,7 +4,9 @@ import lombok.Setter; import org.hswebframework.web.exception.ValidationException; import org.hswebframework.web.i18n.LocaleUtils; +import org.hswebframework.web.i18n.MessageSourceInitializer; import org.junit.Test; +import org.springframework.context.support.StaticMessageSource; import javax.validation.constraints.NotBlank; @@ -14,27 +16,39 @@ public class ValidatorUtilsTest { + static { + System.setProperty("i18n.validation.property.enabled", "true"); + } @Test - public void test(){ - test(Locale.CHINA,"不能为空"); - test(Locale.ENGLISH,"must not be blank"); + public void test() { + StaticMessageSource source = new StaticMessageSource(); + source.addMessage("validation.property_validate_failed", Locale.CHINA, "{0} {1}"); + source.addMessage("validation.property_validate_failed", Locale.ENGLISH, "{0} {1}"); + + source.addMessage(TestEntity.class.getName() + ".notBlank", Locale.ENGLISH, "Test"); + source.addMessage(TestEntity.class.getName() + ".notBlank", Locale.CHINA, "测试"); + + MessageSourceInitializer.init(source); + test(Locale.CHINA, "不能为空", "测试 不能为空"); + test(Locale.ENGLISH, "must not be blank", "Test must not be blank"); } - public void test(Locale locale,String msg){ + public void test(Locale locale, String msg, String msg2) { try { - LocaleUtils.doWith(locale,en->{ + LocaleUtils.doWith(locale, en -> { ValidatorUtils.tryValidate(new TestEntity()); }); throw new IllegalStateException(); - }catch (ValidationException e){ - assertEquals(msg,e.getDetails().get(0).getMessage()); + } catch (ValidationException e) { + assertEquals(msg, e.getDetails().get(0).getMessage()); + assertEquals(msg2, e.getLocalizedMessage(locale)); } } @Getter @Setter - public static class TestEntity{ + public static class TestEntity { @NotBlank private String notBlank; From 533d86e52a4395355ef86c1fd007b1d4db7b0028 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 24 Mar 2022 16:49:02 +0800 Subject: [PATCH 043/416] =?UTF-8?q?=E4=BC=98=E5=8C=96i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/web/CommonErrorControllerAdvice.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java index 0d4b0b77e..f3b4617ad 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java @@ -88,10 +88,12 @@ public Mono> handleException(NotFoundException e) { @ResponseStatus(HttpStatus.BAD_REQUEST) public Mono>> handleException(ValidationException e) { return LocaleUtils - .resolveThrowable(e, (err, msg) -> ResponseMessage - .>error(400, CodeConstants.Error.illegal_argument, msg) - .result(e.getDetails())) - ; + .currentReactive() + .map(locale -> ResponseMessage + .>error(400, + CodeConstants.Error.illegal_argument, + e.getLocalizedMessage(locale)) + .result(e.getDetails(locale))); } @ExceptionHandler @@ -250,9 +252,8 @@ public Mono>> handleException(S @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) public Mono> handleException(I18nSupportException e) { - return LocaleUtils - .resolveThrowable(e, - (err, msg) -> ResponseMessage.error(400, err.getI18nCode(), msg)); + return e.getLocalizedMessageReactive() + .map(msg -> ResponseMessage.error(400, e.getI18nCode(), msg)); } } From 630583a2b7b723fab30d64402a3288622b988f28 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 24 Mar 2022 16:49:12 +0800 Subject: [PATCH 044/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/hswebframework/web/event/AsyncEvent.java | 4 ++-- .../java/org/hswebframework/web/event/DefaultAsyncEvent.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java b/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java index 774e24ef0..19f78d79c 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/event/AsyncEvent.java @@ -29,9 +29,9 @@ public interface AsyncEvent { */ void first(Publisher publisher); - void first(Function,Publisher> mapper); + void transformFirst(Function,Publisher> mapper); - void async(Function,Publisher> mapper); + void transform(Function,Publisher> mapper); /** * 推送事件到 ApplicationEventPublisher diff --git a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java index a076ee5ce..298c0ff12 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java @@ -25,12 +25,12 @@ public synchronized void first(Publisher publisher) { } @Override - public void first(Function, Publisher> mapper) { + public void transformFirst(Function, Publisher> mapper) { this.first = Mono.from(mapper.apply(this.first)); } @Override - public void async(Function, Publisher> mapper) { + public void transform(Function, Publisher> mapper) { this.async = Mono.from(mapper.apply(this.async)); } From e8db04361c1da2615c35eb88e8ec3458178c872c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 29 Mar 2022 16:53:28 +0800 Subject: [PATCH 045/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=8D=95=E4=B8=AA=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/api/crud/entity/Entity.java | 21 +++++++++++++++++++ .../web/validator/ValidatorUtils.java | 12 +++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java index 9d69f33e6..6797afaa9 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java @@ -19,6 +19,7 @@ package org.hswebframework.web.api.crud.entity; +import org.hswebframework.ezorm.core.StaticMethodReferenceColumn; import org.hswebframework.web.bean.FastBeanCopier; import org.hswebframework.web.validator.ValidatorUtils; @@ -42,6 +43,26 @@ default void tryValidate(Class... groups) { ValidatorUtils.tryValidate(this, groups); } + /** + * 使用jsr303对当前实体类的指定属性进行验证,如果未通过验证则会抛出{@link org.hswebframework.web.exception.ValidationException}异常 + * + * @param groups 分组 + * @see org.hswebframework.web.exception.ValidationException + */ + default void tryValidate(String property, Class... groups) { + ValidatorUtils.tryValidate(this, property, groups); + } + + /** + * 使用jsr303对当前实体类的指定属性进行验证,如果未通过验证则会抛出{@link org.hswebframework.web.exception.ValidationException}异常 + * + * @param groups 分组 + * @see org.hswebframework.web.exception.ValidationException + */ + default void tryValidate(StaticMethodReferenceColumn property, Class... groups) { + tryValidate(property.getColumn(), groups); + } + /** * 将当前实体类复制到指定其他类型中,类型将会被自动实例化,在类型明确时,建议使用{@link Entity#copyFrom(Object, String...)}. * diff --git a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java index e578f1b4d..7fa113a47 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java @@ -32,8 +32,7 @@ public static Validator getValidator() { return validator; } - @SuppressWarnings("all") - public static T tryValidate(T bean, Class... group) { + public static T tryValidate(T bean, Class... group) { Set> violations = getValidator().validate(bean, group); if (!violations.isEmpty()) { throw new ValidationException(violations); @@ -42,4 +41,13 @@ public static T tryValidate(T bean, Class... group) { return bean; } + public static T tryValidate(T bean, String property, Class... group) { + Set> violations = getValidator().validateProperty(bean, property, group); + if (!violations.isEmpty()) { + throw new ValidationException(violations); + } + + return bean; + } + } From 5f515953a5877ee5af772486d7b37946bac71142 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 29 Mar 2022 16:53:46 +0800 Subject: [PATCH 046/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/I18nSupportException.java | 9 +++++---- .../web/exception/ValidationException.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java index 2218c4972..45e7dcf0d 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java @@ -47,11 +47,12 @@ public I18nSupportException(String code, Throwable cause, Object... args) { this.i18nCode = code; } + public String getOriginalMessage() { + return super.getMessage(); + } + @Override public String getMessage() { - if (Objects.equals(super.getMessage(), this.getI18nCode())) { - return getLocalizedMessage(); - } return super.getMessage() != null ? super.getMessage() : getLocalizedMessage(); } @@ -61,7 +62,7 @@ public final String getLocalizedMessage() { } public String getLocalizedMessage(Locale locale) { - return LocaleUtils.resolveMessage(i18nCode, locale, getMessage(), args); + return LocaleUtils.resolveMessage(i18nCode, locale, getOriginalMessage(), args); } public final Mono getLocalizedMessageReactive() { diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java index 2a1b0ba13..97d61f2c7 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java @@ -76,7 +76,7 @@ public String getLocalizedMessage(Locale locale) { if (propertyI18nEnabled && "validation.property_validate_failed".equals(getI18nCode()) && getArgs().length > 0) { Object[] args = getArgs().clone(); args[0] = LocaleUtils.resolveMessage(String.valueOf(args[0]), locale, String.valueOf(args[0])); - return LocaleUtils.resolveMessage(getI18nCode(), locale, getMessage(), args); + return LocaleUtils.resolveMessage(getI18nCode(), locale, getOriginalMessage(), args); } return super.getLocalizedMessage(locale); } From 90255abc9df0bbc0e62b869af2482bebca290515 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 30 Mar 2022 14:20:26 +0800 Subject: [PATCH 047/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/api/crud/entity/Entity.java | 2 +- .../api/crud/entity/TreeSupportEntity.java | 36 ++--------- .../web/api/crud/entity/TreeUtils.java | 60 +++++++++++++++++++ .../web/bean/DefaultToStringOperator.java | 19 +++--- .../web/validator/ValidatorUtils.java | 10 ++++ 5 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java index 6797afaa9..b49ce9df9 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java @@ -59,7 +59,7 @@ default void tryValidate(String property, Class... groups) { * @param groups 分组 * @see org.hswebframework.web.exception.ValidationException */ - default void tryValidate(StaticMethodReferenceColumn property, Class... groups) { + default void tryValidate(StaticMethodReferenceColumn property, Class... groups) { tryValidate(property.getColumn(), groups); } diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java index fd3e4e4f9..10dc2f3b9 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java @@ -269,37 +269,11 @@ static , PK> List list2tree(Collection dat static , PK> List list2tree(final Collection dataList, final BiConsumer> childConsumer, final Function, Predicate> predicateFunction) { - Objects.requireNonNull(dataList, "source list can not be null"); - Objects.requireNonNull(childConsumer, "child consumer can not be null"); - Objects.requireNonNull(predicateFunction, "root predicate function can not be null"); - - Supplier> streamSupplier = () -> dataList.stream(); - // id,node - Map cache = new HashMap<>(); - // parentId,children - Map> treeCache = streamSupplier.get() - .peek(node -> cache.put(node.getId(), node)) - .filter(e -> e.getParentId() != null) - .collect(Collectors.groupingBy(TreeSupportEntity::getParentId)); - - Predicate rootNodePredicate = predicateFunction.apply(new TreeHelper() { - @Override - public List getChildren(PK parentId) { - return treeCache.get(parentId); - } - - @Override - public N getNode(PK id) { - return cache.get(id); - } - }); - - return streamSupplier.get() - //设置每个节点的子节点 - .peek(node -> childConsumer.accept(node, treeCache.get(node.getId()))) - //获取根节点 - .filter(rootNodePredicate) - .collect(Collectors.toList()); + return TreeUtils.list2tree(dataList, + TreeSupportEntity::getId, + TreeSupportEntity::getParentId, + childConsumer, + (helper, node) -> predicateFunction.apply(helper).test(node)); } /** diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java new file mode 100644 index 000000000..04f8233eb --- /dev/null +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java @@ -0,0 +1,60 @@ +package org.hswebframework.web.api.crud.entity; + +import com.google.common.collect.Maps; + +import java.util.*; +import java.util.function.*; +import java.util.stream.Collectors; + +public class TreeUtils { + + /** + * 列表结构转为树结构,并返回根节点集合 + * + * @param dataList 数据集合 + * @param childConsumer 子节点消费接口,用于设置子节点 + * @param predicateFunction 根节点判断函数,传入helper,获取一个判断是否为跟节点的函数 + * @param 元素类型 + * @param 主键类型 + * @return 根节点集合 + */ + public static List list2tree(Collection dataList, + Function idGetter, + Function parentIdGetter, + BiConsumer> childConsumer, + BiPredicate, N> predicateFunction) { + Objects.requireNonNull(dataList, "source list can not be null"); + Objects.requireNonNull(childConsumer, "child consumer can not be null"); + Objects.requireNonNull(predicateFunction, "root predicate function can not be null"); + + // id,node + Map cache = Maps.newHashMapWithExpectedSize(dataList.size()); + // parentId,children + Map> treeCache = dataList + .stream() + .peek(node -> cache.put(idGetter.apply(node), node)) + .filter(e -> parentIdGetter.apply(e) != null) + .collect(Collectors.groupingBy(parentIdGetter)); + + TreeSupportEntity.TreeHelper helper = new TreeSupportEntity.TreeHelper() { + @Override + public List getChildren(PK parentId) { + return treeCache.get(parentId); + } + + @Override + public N getNode(PK id) { + return cache.get(id); + } + }; + + return dataList + .stream() + //设置每个节点的子节点 + .peek(node -> childConsumer.accept(node, treeCache.get(idGetter.apply(node)))) + //获取根节点 + .filter(node -> predicateFunction.test(helper, node)) + .collect(Collectors.toList()); + } + +} diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java index adca3b506..9ee75955a 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java @@ -26,7 +26,7 @@ @Slf4j public class DefaultToStringOperator implements ToStringOperator { - private PropertyDescriptor[] descriptors; + private final PropertyDescriptor[] descriptors; private Set defaultIgnoreProperties; @@ -36,10 +36,9 @@ public class DefaultToStringOperator implements ToStringOperator { private Map> converts; - private Function coverStringConvert = (o) -> coverString(String.valueOf(o), 80); + private final Function coverStringConvert = (o) -> coverString(String.valueOf(o), 80); - - private Function> simpleConvertBuilder = type -> { + private final Function, BiFunction> simpleConvertBuilder = type -> { if (Date.class.isAssignableFrom(type)) { return (value, f) -> DateFormatter.toString(((Date) value), "yyyy-MM-dd HH:mm:ss"); } else { @@ -47,13 +46,14 @@ public class DefaultToStringOperator implements ToStringOperator { } }; - private Predicate simpleTypePredicate = ((Predicate) String.class::isAssignableFrom) + private final Predicate> simpleTypePredicate = ((Predicate>) String.class::isAssignableFrom) .or(Class::isEnum) .or(Class::isPrimitive) .or(Date.class::isAssignableFrom) .or(Number.class::isAssignableFrom) .or(Boolean.class::isAssignableFrom); - private Class targetType; + + private final Class targetType; public DefaultToStringOperator(Class targetType) { this.targetType = targetType; @@ -228,10 +228,9 @@ protected void init() { } } - class ConvertConfig { + static class ConvertConfig { long features; Set ignoreProperty; - } protected Map convertMap(Map obj, long features, Set ignoreProperty) { @@ -255,7 +254,7 @@ protected Map convertMap(Map obj, long features, } continue; } - Class type = value.getClass(); + Class type = value.getClass(); if (simpleTypePredicate.test(type)) { value = simpleConvertBuilder.apply(type).apply(value, null); if (ignoreProperty.contains(entry.getKey())) { @@ -292,7 +291,7 @@ protected Map toMap(T target, long features, Set ignoreP if (ToString.Feature.hasFeature(features, ToString.Feature.nullPropertyToEmpty)) { boolean isSimpleType = false; PropertyDescriptor propertyDescriptor = descriptorMap.get(entry.getKey()); - Class propertyType = null; + Class propertyType = null; if (propertyDescriptor != null) { propertyType = propertyDescriptor.getPropertyType(); isSimpleType = simpleTypePredicate.test(propertyType); diff --git a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java index 7fa113a47..3db2fad56 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java @@ -17,6 +17,9 @@ private ValidatorUtils() { public static Validator getValidator() { if (validator == null) { synchronized (ValidatorUtils.class) { + if (validator != null) { + return validator; + } Configuration configuration = Validation .byDefaultProvider() .configure(); @@ -50,4 +53,11 @@ public static T tryValidate(T bean, String property, Class... group) { return bean; } + public static void tryValidate(Class bean, String property, Object value, Class... group) { + Set> violations = getValidator().validateValue(bean, property, value, group); + if (!violations.isEmpty()) { + throw new ValidationException(violations); + } + } + } From 2b656b59435f4f14ff006e4a4591d7cca297d6af Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 30 Mar 2022 14:20:51 +0800 Subject: [PATCH 048/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E7=B1=BB=E8=87=AA=E5=AE=9A=E4=B9=89=E6=8B=93=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/configuration/AutoDDLProcessor.java | 16 +++--- .../DetectEntityColumnMapping.java | 56 +++++++++++++++++++ .../configuration/EasyormConfiguration.java | 19 +++++-- .../EasyormRepositoryRegistrar.java | 54 ++++++------------ .../web/crud/configuration/EntityInfo.java | 6 +- .../entity/factory/MapperEntityFactory.java | 5 ++ .../crud/generator/DefaultIdGenerator.java | 15 ++--- .../hswebframework/web/crud/CrudTests.java | 26 ++++++--- .../web/crud/TestApplication.java | 8 ++- .../web/crud/entity/CustomTestEntity.java | 26 +++++++++ .../web/crud/entity/TestEntity.java | 2 + .../web/crud/service/CustomTestCustom.java | 15 +++++ .../web/crud/service/TestEntityService.java | 9 +++ 13 files changed, 184 insertions(+), 73 deletions(-) create mode 100644 hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java create mode 100644 hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/CustomTestEntity.java create mode 100644 hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/CustomTestCustom.java diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java index ce99ab329..7f420a448 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/AutoDDLProcessor.java @@ -49,13 +49,11 @@ public class AutoDDLProcessor implements InitializingBean { @Override @SneakyThrows public void afterPropertiesSet() { - if (entityFactory instanceof MapperEntityFactory) { - MapperEntityFactory factory = ((MapperEntityFactory) entityFactory); - for (EntityInfo entity : entities) { - factory.addMapping(entity.getEntityType(), MapperEntityFactory.defaultMapper(entity.getRealType())); - } - } - List entities = this.entities.stream().map(EntityInfo::getRealType).collect(Collectors.toList()); + + List> entities = this.entities + .stream() + .map(e -> entityFactory.getInstanceType(e.getRealType(), true)) + .collect(Collectors.toList()); if (properties.isAutoDdl()) { //加载全部表信息 if (reactive) { @@ -63,7 +61,7 @@ public void afterPropertiesSet() { .doOnNext(type -> log.trace("auto ddl for {}", type)) .map(type -> { RDBTableMetadata metadata = resolver.resolve(type); - EntityDDLEvent event = new EntityDDLEvent(this,type,metadata); + EntityDDLEvent event = new EntityDDLEvent<>(this, type, metadata); eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, event, type)); return metadata; }) @@ -83,7 +81,7 @@ public void afterPropertiesSet() { log.trace("auto ddl for {}", type); try { RDBTableMetadata metadata = resolver.resolve(type); - EntityDDLEvent event = new EntityDDLEvent(this,type,metadata); + EntityDDLEvent event = new EntityDDLEvent<>(this, type, metadata); eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, event, type)); operator.ddl() .createOrAlter(metadata) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java new file mode 100644 index 000000000..dbe2cf036 --- /dev/null +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java @@ -0,0 +1,56 @@ +package org.hswebframework.web.crud.configuration; + +import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping; +import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType; +import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; + +import java.util.Map; +import java.util.Optional; + +class DetectEntityColumnMapping implements EntityColumnMapping { + private final String id; + private final Class type; + private final EntityColumnMapping mapping; + + public DetectEntityColumnMapping(Class type, + EntityColumnMapping mapping) { + this.id = MappingFeatureType.columnPropertyMapping.createFeatureId(type); + this.type = type; + this.mapping = mapping; + } + + @Override + public Class getEntityType() { + return type; + } + + @Override + public Optional getColumnByProperty(String property) { + return mapping.getColumnByProperty(property); + } + + @Override + public Optional getPropertyByColumnName(String columnName) { + return mapping.getPropertyByColumnName(columnName); + } + + @Override + public Optional getColumnByName(String columnName) { + return mapping.getColumnByName(columnName); + } + + @Override + public Map getColumnPropertyMapping() { + return mapping.getColumnPropertyMapping(); + } + + @Override + public String getId() { + return id; + } + + @Override + public String getName() { + return getId(); + } +} diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java index 15714adf8..bedc725fd 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java @@ -6,6 +6,7 @@ import org.hswebframework.ezorm.rdb.events.EventListener; import org.hswebframework.ezorm.rdb.executor.SyncSqlExecutor; import org.hswebframework.ezorm.rdb.executor.reactive.ReactiveSqlExecutor; +import org.hswebframework.ezorm.rdb.mapping.DefaultEntityColumnMapping; import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping; import org.hswebframework.ezorm.rdb.mapping.EntityManager; import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType; @@ -186,16 +187,25 @@ public EntityTableMetadataResolver entityTableMappingResolver(ObjectProvider customizers) { JpaEntityTableMetadataParser parser = new JpaEntityTableMetadataParser() { @Override public Optional parseTableMetadata(Class entityType) { - Optional tableOpt = super.parseTableMetadata(entityType); + Class realType = factory.getInstanceType(entityType, true); + Optional tableOpt = super.parseTableMetadata(realType); tableOpt.ifPresent(table -> { + if (realType != entityType) { + table.addFeature(new DetectEntityColumnMapping( + entityType, + table.findFeatureNow( + MappingFeatureType.columnPropertyMapping.createFeatureId(realType) + ))); + } for (TableMetadataCustomizer customizer : customizers) { - customizer.customTable(entityType, table); + customizer.customTable(realType, table); } }); return tableOpt; @@ -203,7 +213,8 @@ public Optional parseTableMetadata(Class entityType) { @Override protected JpaEntityTableMetadataParserProcessor createProcessor(RDBTableMetadata table, Class type) { - return new JpaEntityTableMetadataParserProcessor(table, type) { + Class realType = factory.getInstanceType(type, true); + return new JpaEntityTableMetadataParserProcessor(table, realType) { @Override protected void customColumn(PropertyDescriptor descriptor, Field field, @@ -211,7 +222,7 @@ protected void customColumn(PropertyDescriptor descriptor, Set annotations) { super.customColumn(descriptor, field, column, annotations); for (TableMetadataCustomizer customizer : customizers) { - customizer.customColumn(type, descriptor, field, annotations, column); + customizer.customColumn(realType, descriptor, field, annotations, column); } } }; diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java index 2beddadfc..bd6575bb7 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java @@ -46,8 +46,10 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar private String getResourceClassName(Resource resource) { try { - return metadataReaderFactory.getMetadataReader(resource) - .getClassMetadata().getClassName(); + return metadataReaderFactory + .getMetadataReader(resource) + .getClassMetadata() + .getClassName(); } catch (IOException e) { return null; } @@ -98,46 +100,31 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B for (String className : scanEntities(arr)) { Class entityType = org.springframework.util.ClassUtils.forName(className, null); if (Arrays.stream(anno) - .noneMatch(ann -> AnnotationUtils.findAnnotation(entityType, ann) != null)) { + .noneMatch(ann -> AnnotationUtils.getAnnotation(entityType, ann) != null)) { continue; } - ImplementFor implementFor = AnnotationUtils.findAnnotation(entityType, ImplementFor.class); Reactive reactive = AnnotationUtils.findAnnotation(entityType, Reactive.class); - Class genericType = Optional - .ofNullable(implementFor) - .map(ImplementFor::value) - .orElseGet(() -> { - return Stream - .of(entityType.getInterfaces()) - .filter(e -> GenericEntity.class.isAssignableFrom(e)) - .findFirst() - .orElse(entityType); - }); Class idType = null; - if (implementFor == null || implementFor.idType() == Void.class) { - try { - if (GenericEntity.class.isAssignableFrom(entityType)) { - idType = ClassUtils.getGenericType(entityType); - } - if (idType == null) { - Method getId = org.springframework.util.ClassUtils.getMethod(entityType, "getId"); - idType = getId.getReturnType(); - } - } catch (Exception e) { - idType = String.class; + try { + if (GenericEntity.class.isAssignableFrom(entityType)) { + idType = ClassUtils.getGenericType(entityType); } - } else { - idType = implementFor.idType(); + if (idType == null) { + Method getId = org.springframework.util.ClassUtils.getMethod(entityType, "getId"); + idType = getId.getReturnType(); + } + } catch (Exception e) { + idType = String.class; } - EntityInfo entityInfo = new EntityInfo(genericType, + EntityInfo entityInfo = new EntityInfo(entityType, entityType, idType, reactiveEnabled, nonReactiveEnabled); - if (!entityInfos.contains(entityInfo) || implementFor != null) { + if (!entityInfos.contains(entityInfo)) { entityInfos.add(entityInfo); } @@ -187,15 +174,6 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B registry.registerBeanDefinition(AutoDDLProcessor.class.getName() + "_" + count.incrementAndGet(), definition); } -// try { -// BeanDefinition definition = registry.getBeanDefinition(AutoDDLProcessor.class.getName()); -// Set infos = (Set) definition.getPropertyValues().get("entities"); -// infos.addAll(entityInfos); -// } catch (NoSuchBeanDefinitionException e) { -// -// } - - } static AtomicInteger count = new AtomicInteger(); diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EntityInfo.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EntityInfo.java index 179dd4c3f..c9ca892f6 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EntityInfo.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EntityInfo.java @@ -10,11 +10,11 @@ @EqualsAndHashCode(of = "entityType") @AllArgsConstructor public class EntityInfo { - private Class entityType; + private Class entityType; - private Class realType; + private Class realType; - private Class idType; + private Class idType; private boolean reactive; diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java index 1d2667584..c61c6f805 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java @@ -73,6 +73,11 @@ public MapperEntityFactory addMapping(Class target, Mapper m return this; } + public MapperEntityFactory addMappingIfAbsent(Class target, Mapper mapper) { + realTypeMapper.putIfAbsent(target, mapper); + return this; + } + public MapperEntityFactory addCopier(PropertyCopier copier) { Class source = (Class) ClassUtils.getGenericType(copier.getClass(), 0); Class target = (Class) ClassUtils.getGenericType(copier.getClass(), 1); diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/DefaultIdGenerator.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/DefaultIdGenerator.java index b8dfee3a2..983e57bf4 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/DefaultIdGenerator.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/generator/DefaultIdGenerator.java @@ -8,13 +8,14 @@ import org.hswebframework.ezorm.core.DefaultValueGenerator; import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; import org.hswebframework.web.id.IDGenerator; +import org.springframework.util.StringUtils; import reactor.core.publisher.Mono; import java.util.HashMap; import java.util.Map; @Slf4j -public class DefaultIdGenerator implements DefaultValueGenerator { +public class DefaultIdGenerator implements DefaultValueGenerator { @Getter @Setter @@ -32,14 +33,10 @@ public String getSortId() { @Override @SneakyThrows public DefaultValue generate(RDBColumnMetadata metadata) { - return Mono.justOrEmpty(mappings.get(metadata.getOwner().getName())) - .switchIfEmpty(Mono.justOrEmpty(defaultId)) - .flatMap(id->Mono.justOrEmpty(metadata.findFeature(DefaultValueGenerator.createId(id)))) - .doOnNext(gen-> log.debug("use default id generator : {} for column : {}", gen.getSortId(), metadata.getFullName())) - .map(gen->gen.generate(metadata)) - .switchIfEmpty(Mono.error(()->new UnsupportedOperationException("不支持的生成器:" + defaultId))) - .toFuture() - .get(); + String genId = mappings.getOrDefault(metadata.getOwner().getName(), defaultId); + DefaultValueGenerator generator = metadata.findFeatureNow(DefaultValueGenerator.createId(genId)); + log.debug("use default id generator : {} for column : {}", generator.getSortId(), metadata.getFullName()); + return generator.generate(metadata); } @Override diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java index becf82e82..e172ea4ab 100644 --- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/CrudTests.java @@ -1,5 +1,6 @@ package org.hswebframework.web.crud; +import org.hswebframework.web.crud.entity.CustomTestEntity; import org.hswebframework.web.crud.entity.TestEntity; import org.hswebframework.web.crud.service.TestEntityService; import org.junit.Assert; @@ -13,22 +14,31 @@ @SpringBootTest @RunWith(SpringJUnit4ClassRunner.class) -public class CrudTests { +public class CrudTests { @Autowired private TestEntityService service; @Test - public void test(){ - - TestEntity entity = TestEntity.of("test",100); + public void test() { + CustomTestEntity entity = new CustomTestEntity(); + entity.setExt("xxx"); + entity.setAge(1); + entity.setName("test"); + Mono.just(entity) - .as(service::insert) - .as(StepVerifier::create) - .expectNext(1) - .verifyComplete(); + .cast(TestEntity.class) + .as(service::insert) + .as(StepVerifier::create) + .expectNext(1) + .verifyComplete(); Assert.assertNotNull(entity.getId()); + + service.findById(entity.getId()) + .as(StepVerifier::create) + .expectNextMatches(e -> e instanceof CustomTestEntity) + .verifyComplete(); } } diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java index 1b2c011f3..ebe8f483b 100644 --- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/TestApplication.java @@ -1,7 +1,9 @@ package org.hswebframework.web.crud; import org.hswebframework.web.api.crud.entity.EntityFactory; +import org.hswebframework.web.crud.entity.factory.EntityMappingCustomizer; import org.hswebframework.web.crud.entity.factory.MapperEntityFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; @@ -13,7 +15,9 @@ public class TestApplication { @Bean - public EntityFactory entityFactory(){ - return new MapperEntityFactory(); + public EntityFactory entityFactory(ObjectProvider customizers) { + MapperEntityFactory factory = new MapperEntityFactory(); + customizers.forEach(customizer -> customizer.custom(factory)); + return factory; } } diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/CustomTestEntity.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/CustomTestEntity.java new file mode 100644 index 000000000..a66d07edb --- /dev/null +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/CustomTestEntity.java @@ -0,0 +1,26 @@ +package org.hswebframework.web.crud.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.bean.ToString; +import org.hswebframework.web.crud.generator.Generators; + +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.Table; + +@Getter +@Setter +@AllArgsConstructor(staticName = "of") +@NoArgsConstructor +public class CustomTestEntity extends TestEntity { + + + @Column + @ToString.Ignore + private String ext; + +} diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/TestEntity.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/TestEntity.java index 7ab89919d..f34e50de0 100644 --- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/TestEntity.java +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/entity/TestEntity.java @@ -5,6 +5,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.crud.annotation.EnableEntityEvent; import org.hswebframework.web.crud.generator.Generators; import javax.persistence.Column; @@ -16,6 +17,7 @@ @Table(name = "s_test") @AllArgsConstructor(staticName = "of") @NoArgsConstructor +@EnableEntityEvent public class TestEntity extends GenericEntity { @Column(length = 32) diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/CustomTestCustom.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/CustomTestCustom.java new file mode 100644 index 000000000..0f60ec701 --- /dev/null +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/CustomTestCustom.java @@ -0,0 +1,15 @@ +package org.hswebframework.web.crud.service; + +import org.hswebframework.web.crud.entity.CustomTestEntity; +import org.hswebframework.web.crud.entity.TestEntity; +import org.hswebframework.web.crud.entity.factory.EntityMappingCustomizer; +import org.hswebframework.web.crud.entity.factory.MapperEntityFactory; +import org.springframework.stereotype.Component; + +@Component +public class CustomTestCustom implements EntityMappingCustomizer { + @Override + public void custom(MapperEntityFactory factory) { + factory.addMapping(TestEntity.class, new MapperEntityFactory.Mapper<>(CustomTestEntity.class,CustomTestEntity::new)); + } +} diff --git a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/TestEntityService.java b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/TestEntityService.java index 236a8d8a4..e813fa099 100644 --- a/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/TestEntityService.java +++ b/hsweb-commons/hsweb-commons-crud/src/test/java/org/hswebframework/web/crud/service/TestEntityService.java @@ -1,10 +1,19 @@ package org.hswebframework.web.crud.service; import org.hswebframework.web.crud.entity.TestEntity; +import org.hswebframework.web.crud.events.EntityCreatedEvent; import org.hswebframework.web.id.IDGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; @Service public class TestEntityService extends GenericReactiveCrudService { + + @EventListener + public void handleEvent(EntityCreatedEvent event){ + + System.out.println(event.getEntity()); + } } From 85ccb75eff98fe04dc099a696cfb1dca7595df7b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 1 Apr 2022 17:27:55 +0800 Subject: [PATCH 049/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E5=88=9B=E5=BB=BA=E4=BA=BA=E5=92=8C=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E4=BA=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/EasyormConfiguration.java | 5 + .../web/crud/events/CreatorEventListener.java | 99 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java index bedc725fd..26701527d 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java @@ -125,6 +125,11 @@ public ValidateEventListener validateEventListener() { return new ValidateEventListener(); } + @Bean + public CreatorEventListener creatorEventListener() { + return new CreatorEventListener(); + } + @Bean @ConfigurationProperties(prefix = "easyorm.default-value-generator") public DefaultIdGenerator defaultIdGenerator() { diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java new file mode 100644 index 000000000..2ce37eaa0 --- /dev/null +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java @@ -0,0 +1,99 @@ +package org.hswebframework.web.crud.events; + +import org.hswebframework.ezorm.rdb.events.EventContext; +import org.hswebframework.ezorm.rdb.events.EventListener; +import org.hswebframework.ezorm.rdb.events.EventType; +import org.hswebframework.ezorm.rdb.mapping.events.MappingContextKeys; +import org.hswebframework.ezorm.rdb.mapping.events.MappingEventTypes; +import org.hswebframework.ezorm.rdb.mapping.events.ReactiveResultHolder; +import org.hswebframework.web.api.crud.entity.Entity; +import org.hswebframework.web.api.crud.entity.RecordCreationEntity; +import org.hswebframework.web.api.crud.entity.RecordModifierEntity; +import org.hswebframework.web.authorization.Authentication; +import org.hswebframework.web.validator.CreateGroup; +import org.hswebframework.web.validator.UpdateGroup; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Mono; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.function.Consumer; + +/** + * 自动填充创建人和修改人信息 + */ +public class CreatorEventListener implements EventListener { + + @Override + public String getId() { + return "creator-listener"; + } + + @Override + public String getName() { + return "创建者监听器"; + } + + @Override + public void onEvent(EventType type, EventContext context) { + Optional resultHolder = context.get(MappingContextKeys.reactiveResultHolder); + if (type == MappingEventTypes.insert_before + || type == MappingEventTypes.save_before + || type == MappingEventTypes.update_before) { + if (resultHolder.isPresent()) { + resultHolder + .ifPresent(holder -> holder + .before( + Authentication + .currentReactive() + .doOnNext(auth -> doApplyCreator(type, context, auth)) + .then() + )); + } else { + Authentication + .current() + .ifPresent(auth -> doApplyCreator(type, context, auth)); + } + } + } + + protected void doApplyCreator(EventType type, EventContext context, Authentication auth) { + context.get(MappingContextKeys.instance) + .ifPresent(obj -> { + if (obj instanceof Collection) { + applyCreator(auth, ((Collection) obj), type != MappingEventTypes.update_before); + } else { + applyCreator(auth, obj, type != MappingEventTypes.update_before); + } + }); + } + + public void applyCreator(Authentication auth, Object entity, boolean updateCreator) { + if (updateCreator && entity instanceof RecordCreationEntity) { + RecordCreationEntity e = (RecordCreationEntity) entity; + if (ObjectUtils.isEmpty(e.getCreatorId())) { + e.setCreatorId(auth.getUser().getId()); + e.setCreatorName(auth.getUser().getName()); + e.setCreateTimeNow(); + } + + } + if (entity instanceof RecordModifierEntity) { + RecordModifierEntity e = (RecordModifierEntity) entity; + if (ObjectUtils.isEmpty(e.getModifierId())) { + e.setModifierId(auth.getUser().getId()); + e.setModifierName(auth.getUser().getName()); + e.setModifyTimeNow(); + } + } + } + + public void applyCreator(Authentication auth, Collection entities, boolean updateCreator) { + for (Object entity : entities) { + applyCreator(auth, entity, updateCreator); + } + + } +} From 377c480e9e681e0439b4ab4f963cd5441ce769f1 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 1 Apr 2022 17:28:04 +0800 Subject: [PATCH 050/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/AuthenticationHolder.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java index 3fc9d1c08..d782b6b52 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java @@ -51,14 +51,17 @@ public final class AuthenticationHolder { private static final ReadWriteLock lock = new ReentrantReadWriteLock(); private static Optional get(Function> function) { - - return Flux.fromStream(suppliers.stream().map(function)) - .filter(Optional::isPresent) - .map(Optional::get) - .reduceWith(SimpleAuthentication::new, SimpleAuthentication::merge) - .filter(auth->auth.getUser()!=null) - .map(Authentication.class::cast) - .blockOptional(); + if (suppliers.size() == 1) { + return suppliers.get(0).get(); + } + SimpleAuthentication merge = new SimpleAuthentication(); + for (AuthenticationSupplier supplier : suppliers) { + supplier.get().ifPresent(merge::merge); + } + if (merge.getUser() == null) { + return Optional.empty(); + } + return Optional.of(merge); } /** From 838e66ef962bfebbb1ef96ba2364f25a34caf09f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 1 Apr 2022 17:29:08 +0800 Subject: [PATCH 051/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/authorization/AuthenticationHolder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java index d782b6b52..d9c254eee 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java @@ -51,12 +51,16 @@ public final class AuthenticationHolder { private static final ReadWriteLock lock = new ReentrantReadWriteLock(); private static Optional get(Function> function) { - if (suppliers.size() == 1) { + int size = suppliers.size(); + if (size == 0) { + return Optional.empty(); + } + if (size == 1) { return suppliers.get(0).get(); } SimpleAuthentication merge = new SimpleAuthentication(); for (AuthenticationSupplier supplier : suppliers) { - supplier.get().ifPresent(merge::merge); + function.apply(supplier).ifPresent(merge::merge); } if (merge.getUser() == null) { return Optional.empty(); From e7015f1a16d85a2d667fe329d557177341c5f8f5 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 1 Apr 2022 17:29:28 +0800 Subject: [PATCH 052/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/authorization/AuthenticationHolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java index d9c254eee..c917ef15a 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationHolder.java @@ -56,7 +56,7 @@ private static Optional get(Function Date: Wed, 6 Apr 2022 09:50:58 +0800 Subject: [PATCH 053/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E8=8E=B7?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReactiveTokenAuthenticationSupplier.java | 13 ++++-------- ...erTokenReactiveAuthenticationSupplier.java | 13 ++++-------- .../basic/web/UserTokenWebFilter.java | 7 ++----- .../aop/ReactiveAopAccessLoggerSupport.java | 17 ++++++++++++++-- .../web/logging/AccessLoggerInfo.java | 20 ++++++++++++++++++- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/ReactiveTokenAuthenticationSupplier.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/ReactiveTokenAuthenticationSupplier.java index 97efdb45a..6b43c1da5 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/ReactiveTokenAuthenticationSupplier.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/ReactiveTokenAuthenticationSupplier.java @@ -20,15 +20,10 @@ public Mono get(String userId) { @Override public Mono get() { - return ContextUtils - .reactiveContext() - .flatMap(context -> context - .get(ContextKey.of(ParsedToken.class)) + return Mono + .deferWithContext(context -> context + .getOrEmpty(ParsedToken.class) .map(t -> tokenManager.getByToken(t.getToken())) - .orElseGet(Mono::empty)) - .flatMap(auth -> ReactiveLogger - .mdc("userId", auth.getUser().getId(), - "username", auth.getUser().getName()) - .thenReturn(auth)); + .orElse(Mono.empty())); } } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java index 894a78f8c..0b2e9dd59 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java @@ -68,10 +68,9 @@ protected Mono get(ReactiveAuthenticationManager authenticationM @Override public Mono get() { - return ContextUtils - .reactiveContext() - .flatMap(context -> context - .get(ContextKey.of(ParsedToken.class)) + return Mono + .deferWithContext(context -> context + .getOrEmpty(ParsedToken.class) .map(t -> userTokenManager .getByToken(t.getToken()) .filter(UserToken::validate) @@ -82,11 +81,7 @@ public Mono get() { } return before.then(get(thirdPartAuthenticationManager.get(token.getType()), token.getUserId())); })) - .orElseGet(Mono::empty)) - .flatMap(auth -> ReactiveLogger - .mdc("userId", auth.getUser().getId(), - "username", auth.getUser().getName()) - .thenReturn(auth)) + .orElse(Mono.empty())) ; } diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java index d8b24a621..c98edba8c 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java @@ -19,6 +19,7 @@ import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import reactor.util.context.Context; import java.util.ArrayList; import java.util.HashMap; @@ -47,11 +48,7 @@ public Mono filter(@NonNull ServerWebExchange exchange, WebFilterChain cha .next() .map(token -> chain .filter(exchange) - .subscriberContext( - ContextUtils.acceptContext( - context -> context.put(ParsedToken.class, token) - ) - )) + .subscriberContext(Context.of(ParsedToken.class, token))) .defaultIfEmpty(chain.filter(exchange)) .flatMap(Function.identity()) .subscriberContext(ReactiveLogger.start("requestId", exchange.getRequest().getId())); diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index b033de238..f982d3ec8 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -2,6 +2,7 @@ import org.aopalliance.intercept.MethodInterceptor; import org.hswebframework.web.aop.MethodInterceptorHolder; +import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.id.IDGenerator; import org.hswebframework.web.logger.ReactiveLogger; import org.hswebframework.web.logging.RequestInfo; @@ -83,7 +84,19 @@ protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { .then(Mono.defer(() -> { AccessLoggerBeforeEvent event = new AccessLoggerBeforeEvent(loggerInfo); event.first(cache); - return event.publish(eventPublisher); + return Authentication + .currentReactive() + .flatMap(auth -> { + loggerInfo.putContext("userId", auth.getUser().getId()); + loggerInfo.putContext("username", auth.getUser().getUsername()); + loggerInfo.putContext("userName", auth.getUser().getName()); + return ReactiveLogger + .mdc("userId", auth.getUser().getId(), + "username", auth.getUser().getUsername(), + "userName", auth.getUser().getName()) + .thenReturn(auth); + }) + .then(event.publish(eventPublisher)); })) .then(Mono.defer(() -> { loggerInfo.setResponseTime(System.currentTimeMillis()); @@ -166,7 +179,7 @@ protected AccessLoggerInfo createLogger(MethodInterceptorHolder holder) { @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE; + return Ordered.LOWEST_PRECEDENCE; } @Override diff --git a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java index 696022374..153aa4105 100644 --- a/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java +++ b/hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java @@ -7,6 +7,7 @@ import java.io.Serializable; import java.io.StringWriter; import java.lang.reflect.Method; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.StringJoiner; @@ -115,7 +116,10 @@ public Map toSimpleMap(Function objectFilt Class[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { - methodAppender.add(parameterTypes[i].getSimpleName().concat(" ").concat(parameterNames.length > i ? parameterNames[i] : ("arg" + i))); + methodAppender.add(parameterTypes[i] + .getSimpleName() + .concat(" ") + .concat(parameterNames.length > i ? parameterNames[i] : ("arg" + i))); } map.put("method", methodAppender.toString()); } @@ -153,4 +157,18 @@ public void putAccessInfo(RequestInfo info) { setUrl(info.getPath()); setContext(info.getContext()); } + + public void putContext(Map context) { + if (this.context == null) { + this.context = new HashMap<>(); + } + this.context.putAll(context); + } + + public void putContext(String key, Object value) { + if (this.context == null) { + this.context = new HashMap<>(); + } + this.context.put(key, String.valueOf(value)); + } } From 6d486b6b3bdf6133c64bec19b250310b87b79667 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 6 Apr 2022 17:51:12 +0800 Subject: [PATCH 054/416] =?UTF-8?q?=E4=BC=98=E5=8C=96TreeUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/api/crud/entity/TreeUtils.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java index 04f8233eb..fc0ca0093 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java @@ -1,6 +1,7 @@ package org.hswebframework.web.api.crud.entity; import com.google.common.collect.Maps; +import org.springframework.util.ObjectUtils; import java.util.*; import java.util.function.*; @@ -8,6 +9,33 @@ public class TreeUtils { + + /** + * 列表结构转为树结构,并返回根节点集合. + *

+ * 根节点判断逻辑: parentId为空或者对应的节点数据没有在list中 + * + * @param dataList 数据集合 + * @param childConsumer 子节点消费接口,用于设置子节点 + * @param 元素类型 + * @param 主键类型 + * @return 根节点集合 + */ + public static List list2tree(Collection dataList, + Function idGetter, + Function parentIdGetter, + BiConsumer> childConsumer) { + return list2tree(dataList, + idGetter, + parentIdGetter, + childConsumer, + (helper, node) -> { + PK parentId = parentIdGetter.apply(node); + return ObjectUtils.isEmpty(parentId) + || helper.getNode(parentId) == null; + }); + } + /** * 列表结构转为树结构,并返回根节点集合 * From 7f95784e5beea3ea1e2696b32ded8c751226e94f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 6 Apr 2022 21:15:23 +0800 Subject: [PATCH 055/416] =?UTF-8?q?=E4=BC=98=E5=8C=96token=E8=8E=B7?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/authorization/AuthenticationTests.java | 3 ++- .../basic/web/ReactiveUserTokenController.java | 4 ++-- .../auth/ReactiveOAuth2AccessTokenParser.java | 13 ++++--------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java b/hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java index 9e4df5c31..01c4c4ebf 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java +++ b/hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java @@ -12,6 +12,7 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.SignalType; import reactor.test.StepVerifier; +import reactor.util.context.Context; import java.util.Collections; import java.util.Set; @@ -138,7 +139,7 @@ public String getType() { .doOnEach(ReactiveLogger.on(SignalType.ON_NEXT,(ctx,signal)->{ System.out.println(ctx); })) - .subscriberContext(acceptContext(ctx -> ctx.put(ContextKey.of(ParsedToken.class), parsedToken))) + .subscriberContext(Context.of(ParsedToken.class, parsedToken)) .subscriberContext(ReactiveLogger.start("rid","1")) .as(StepVerifier::create) .expectNext("admin") diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java index 1316853c2..470401ea2 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/ReactiveUserTokenController.java @@ -47,8 +47,8 @@ public void setAuthenticationManager(ReactiveAuthenticationManager authenticatio @Authorize(merge = false) @Operation(summary = "重置当前用户的令牌") public Mono resetToken() { - return ContextUtils.reactiveContext() - .map(context -> context.get(ContextKey.of(ParsedToken.class)).orElseThrow(UnAuthorizedException::new)) + return Mono + .deferWithContext(ctx -> Mono.justOrEmpty(ctx.getOrEmpty(ParsedToken.class))) .flatMap(token -> userTokenManager.signOutByToken(token.getToken())) .thenReturn(true); } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/auth/ReactiveOAuth2AccessTokenParser.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/auth/ReactiveOAuth2AccessTokenParser.java index dedcfe752..549d291bc 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/auth/ReactiveOAuth2AccessTokenParser.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/auth/ReactiveOAuth2AccessTokenParser.java @@ -47,16 +47,11 @@ public Mono get(String userId) { @Override public Mono get() { - return ContextUtils - .reactiveContext() - .flatMap(context -> context - .get(ContextKey.of(ParsedToken.class)) + return Mono + .deferWithContext(context -> context + .getOrEmpty(ParsedToken.class) .filter(token -> "oauth2".equals(token.getType())) .map(t -> accessTokenManager.getAuthenticationByToken(t.getToken())) - .orElse(Mono.empty())) - .flatMap(auth -> ReactiveLogger - .mdc("userId", auth.getUser().getId(), - "username", auth.getUser().getName()) - .thenReturn(auth)); + .orElse(Mono.empty())); } } From 8efd19e65d6ad2c2e1f77259f8748a5b86328ffe Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 8 Apr 2022 22:05:09 +0800 Subject: [PATCH 056/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/DefaultEntityResultWrapperFactory.java | 4 ++-- .../web/crud/configuration/DetectEntityColumnMapping.java | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DefaultEntityResultWrapperFactory.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DefaultEntityResultWrapperFactory.java index 5f9b42d7b..20fbec0e2 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DefaultEntityResultWrapperFactory.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DefaultEntityResultWrapperFactory.java @@ -5,6 +5,7 @@ import org.hswebframework.ezorm.rdb.executor.wrapper.ResultWrapper; import org.hswebframework.ezorm.rdb.mapping.EntityManager; import org.hswebframework.ezorm.rdb.mapping.wrapper.EntityResultWrapper; +import org.hswebframework.ezorm.rdb.mapping.wrapper.NestedEntityResultWrapper; @AllArgsConstructor public class DefaultEntityResultWrapperFactory implements EntityResultWrapperFactory { @@ -14,8 +15,7 @@ public class DefaultEntityResultWrapperFactory implements EntityResultWrapperFac @Override @SneakyThrows public ResultWrapper getWrapper(Class tClass) { - return new EntityResultWrapper<>(() -> entityManager.newInstance(tClass), - entityManager.getMapping(tClass)); + return new NestedEntityResultWrapper<>(entityManager.getMapping(tClass)); } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java index dbe2cf036..0638d3726 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java @@ -3,6 +3,7 @@ import org.hswebframework.ezorm.rdb.mapping.EntityColumnMapping; import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType; import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; +import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata; import java.util.Map; import java.util.Optional; @@ -44,6 +45,11 @@ public Map getColumnPropertyMapping() { return mapping.getColumnPropertyMapping(); } + @Override + public TableOrViewMetadata getTable() { + return mapping.getTable(); + } + @Override public String getId() { return id; From 6b0ba45630ff9c331cd7920f1e0b601687e79989 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 8 Apr 2022 22:21:34 +0800 Subject: [PATCH 057/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/configuration/DetectEntityColumnMapping.java | 11 ++++++++++- .../web/crud/configuration/EasyormConfiguration.java | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java index 0638d3726..d2ddc0bc6 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/DetectEntityColumnMapping.java @@ -4,6 +4,7 @@ import org.hswebframework.ezorm.rdb.mapping.MappingFeatureType; import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata; +import org.hswebframework.web.api.crud.entity.EntityFactory; import java.util.Map; import java.util.Optional; @@ -12,12 +13,15 @@ class DetectEntityColumnMapping implements EntityColumnMapping { private final String id; private final Class type; private final EntityColumnMapping mapping; + private final EntityFactory entityFactory; public DetectEntityColumnMapping(Class type, - EntityColumnMapping mapping) { + EntityColumnMapping mapping, + EntityFactory entityFactory) { this.id = MappingFeatureType.columnPropertyMapping.createFeatureId(type); this.type = type; this.mapping = mapping; + this.entityFactory = entityFactory; } @Override @@ -50,6 +54,11 @@ public TableOrViewMetadata getTable() { return mapping.getTable(); } + @Override + public Object newInstance() { + return entityFactory.newInstance(getEntityType()); + } + @Override public String getId() { return id; diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java index 26701527d..9042b6c9d 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java @@ -173,7 +173,7 @@ public E newInstance(Class type) { @Override public EntityColumnMapping getMapping(Class entity) { - return resolver.resolve(entityFactory.getInstanceType(entity, true)) + return resolver.resolve(entity) .getFeature(MappingFeatureType.columnPropertyMapping.createFeatureId(entity)) .map(EntityColumnMapping.class::cast) .orElse(null); @@ -207,7 +207,7 @@ public Optional parseTableMetadata(Class entityType) { entityType, table.findFeatureNow( MappingFeatureType.columnPropertyMapping.createFeatureId(realType) - ))); + ),factory)); } for (TableMetadataCustomizer customizer : customizers) { customizer.customTable(realType, table); From f361f0c1cb1c4dd183f434ac6e3bb48b90c85097 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 13 Apr 2022 15:56:34 +0800 Subject: [PATCH 058/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/hswebframework/web/exception/I18nSupportException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java index 45e7dcf0d..6213a36c8 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java @@ -48,7 +48,7 @@ public I18nSupportException(String code, Throwable cause, Object... args) { } public String getOriginalMessage() { - return super.getMessage(); + return super.getMessage() != null ? super.getMessage() : getI18nCode(); } @Override From 69ac98c9859bd747c56db0ee446a7e03d6fb0a2f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 21 Apr 2022 13:45:51 +0800 Subject: [PATCH 059/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=A1=AB=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/crud/events/CreatorEventListener.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java index 2ce37eaa0..9662899d3 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java @@ -76,6 +76,8 @@ public void applyCreator(Authentication auth, Object entity, boolean updateCreat if (ObjectUtils.isEmpty(e.getCreatorId())) { e.setCreatorId(auth.getUser().getId()); e.setCreatorName(auth.getUser().getName()); + } + if (e.getCreateTime() == null) { e.setCreateTimeNow(); } @@ -85,6 +87,8 @@ public void applyCreator(Authentication auth, Object entity, boolean updateCreat if (ObjectUtils.isEmpty(e.getModifierId())) { e.setModifierId(auth.getUser().getId()); e.setModifierName(auth.getUser().getName()); + } + if (e.getModifyTime() == null) { e.setModifyTimeNow(); } } From b51c7cae955ebf2bd2a30c3f6fd5f3e0f38b80a8 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 21 Apr 2022 13:46:05 +0800 Subject: [PATCH 060/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/file/web/ReactiveFileController.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/web/ReactiveFileController.java b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/web/ReactiveFileController.java index b4a54fdab..c55a3ee2f 100644 --- a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/web/ReactiveFileController.java +++ b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/web/ReactiveFileController.java @@ -43,16 +43,19 @@ public ReactiveFileController(FileUploadProperties properties, FileStorageServic @ResourceAction(id = "upload-static", name = "静态文件") @Operation(summary = "上传静态文件") public Mono uploadStatic(@RequestPart("file") - @Parameter(name = "file", description = "文件", style = ParameterStyle.FORM) Part part) { - if (part instanceof FilePart) { - FilePart filePart = ((FilePart) part); - if (properties.denied(filePart.filename(), filePart.headers().getContentType())) { - throw new AccessDenyException(); - } - return fileStorageService.saveFile(filePart); - } else { - return Mono.error(() -> new IllegalArgumentException("[file] part is not a file")); - } + @Parameter(name = "file", description = "文件", style = ParameterStyle.FORM) Mono partMono) { + return partMono + .flatMap(part -> { + if (part instanceof FilePart) { + FilePart filePart = ((FilePart) part); + if (properties.denied(filePart.filename(), filePart.headers().getContentType())) { + return Mono.error( new AccessDenyException()); + } + return fileStorageService.saveFile(filePart); + } else { + return Mono.error(() -> new IllegalArgumentException("[file] part is not a file")); + } + }); } From dd92471f63f5a72e98a693853be32e0fc176f00e Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 27 Apr 2022 16:15:30 +0800 Subject: [PATCH 061/416] =?UTF-8?q?=E4=BD=BF=E7=94=A8share=E4=BB=A3?= =?UTF-8?q?=E6=9B=BFcache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/logging/aop/ReactiveAopAccessLoggerSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index f982d3ec8..c44831e54 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -77,7 +77,7 @@ private Mono currentRequestInfo() { protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { - Flux cache = flux.cache(); + Flux cache = flux.share(); return this .currentRequestInfo() .doOnNext(loggerInfo::putAccessInfo) From 9ba15121831037f928e0cc45a141ffea052fbb1b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 27 Apr 2022 16:16:13 +0800 Subject: [PATCH 062/416] jakarta.el --- hsweb-core/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 9e83cf5aa..00c463942 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -96,8 +96,7 @@ org.glassfish - javax.el - 3.0.0 + jakarta.el From 16da624c1a08eaf20cf8b506b41824ef193b6249 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 27 Apr 2022 19:45:53 +0800 Subject: [PATCH 063/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=AF=BC=E8=87=B4=E6=97=A0=E6=B3=95=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E6=B5=81onCancel=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/utils/FluxCache.java | 30 ++++++++ .../aop/ReactiveAopAccessLoggerSupport.java | 70 ++++++++++--------- 2 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/utils/FluxCache.java diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/FluxCache.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/FluxCache.java new file mode 100644 index 000000000..a8c40c33a --- /dev/null +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/FluxCache.java @@ -0,0 +1,30 @@ +package org.hswebframework.web.utils; + +import org.reactivestreams.Publisher; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.function.Function; + +public class FluxCache { + + + public static Flux cache(Flux source, Function, Publisher> handler) { + Disposable[] ref = new Disposable[1]; + Flux cache = source + .doFinally((s) -> ref[0] = null) + .replay() + .autoConnect(1, dis -> ref[0] = dis); + return Mono + .from(handler.apply(cache)) + .thenMany(cache) + .doFinally((s) -> { + if (ref[0] != null) { + ref[0].dispose(); + } + }); + + } + +} diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index c44831e54..9ec6fbb60 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -1,5 +1,6 @@ package org.hswebframework.web.logging.aop; +import lombok.SneakyThrows; import org.aopalliance.intercept.MethodInterceptor; import org.hswebframework.web.aop.MethodInterceptorHolder; import org.hswebframework.web.authorization.Authentication; @@ -11,6 +12,7 @@ import org.hswebframework.web.logging.LoggerDefine; import org.hswebframework.web.logging.events.AccessLoggerAfterEvent; import org.hswebframework.web.logging.events.AccessLoggerBeforeEvent; +import org.hswebframework.web.utils.FluxCache; import org.hswebframework.web.utils.ReactiveWebUtils; import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; import org.springframework.beans.factory.annotation.Autowired; @@ -22,13 +24,16 @@ import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; +import reactor.core.Disposable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.context.Context; import java.lang.reflect.Method; +import java.time.Duration; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; /** * 使用AOP记录访问日志,并触发{@link AccessLoggerListener#onLogger(AccessLoggerInfo)} @@ -76,41 +81,40 @@ private Mono currentRequestInfo() { } protected Flux wrapFluxResponse(Flux flux, AccessLoggerInfo loggerInfo) { + return Flux.deferWithContext(ctx -> this + .currentRequestInfo() + .doOnNext(loggerInfo::putAccessInfo) + .then(beforeRequest(loggerInfo)) + .thenMany(flux) + .doOnError(loggerInfo::setException) + .doFinally(signal -> completeRequest(loggerInfo, ctx))) + .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + } - Flux cache = flux.share(); - return this - .currentRequestInfo() - .doOnNext(loggerInfo::putAccessInfo) - .then(Mono.defer(() -> { - AccessLoggerBeforeEvent event = new AccessLoggerBeforeEvent(loggerInfo); - event.first(cache); - return Authentication - .currentReactive() - .flatMap(auth -> { - loggerInfo.putContext("userId", auth.getUser().getId()); - loggerInfo.putContext("username", auth.getUser().getUsername()); - loggerInfo.putContext("userName", auth.getUser().getName()); - return ReactiveLogger - .mdc("userId", auth.getUser().getId(), - "username", auth.getUser().getUsername(), - "userName", auth.getUser().getName()) - .thenReturn(auth); - }) - .then(event.publish(eventPublisher)); - })) - .then(Mono.defer(() -> { - loggerInfo.setResponseTime(System.currentTimeMillis()); - return new AccessLoggerAfterEvent(loggerInfo).publish(eventPublisher); - })) - .thenMany(cache) - .onErrorResume(err -> { - loggerInfo.setException(err); - loggerInfo.setResponseTime(System.currentTimeMillis()); - return new AccessLoggerAfterEvent(loggerInfo) - .publish(eventPublisher) - .then(Mono.error(err)); + private Mono beforeRequest(AccessLoggerInfo loggerInfo) { + + AccessLoggerBeforeEvent event = new AccessLoggerBeforeEvent(loggerInfo); + return Authentication + .currentReactive() + .flatMap(auth -> { + loggerInfo.putContext("userId", auth.getUser().getId()); + loggerInfo.putContext("username", auth.getUser().getUsername()); + loggerInfo.putContext("userName", auth.getUser().getName()); + return ReactiveLogger + .mdc("userId", auth.getUser().getId(), + "username", auth.getUser().getUsername(), + "userName", auth.getUser().getName()) + .thenReturn(auth); }) - .subscriberContext(ReactiveLogger.start("accessLogId", loggerInfo.getId())); + .then(event.publish(eventPublisher)); + } + + private void completeRequest(AccessLoggerInfo loggerInfo, Context ctx) { + loggerInfo.setResponseTime(System.currentTimeMillis()); + new AccessLoggerAfterEvent(loggerInfo) + .publish(eventPublisher) + .subscriberContext(ctx) + .subscribe(); } protected Mono wrapMonoResponse(Mono mono, AccessLoggerInfo loggerInfo) { From 2e4628eef1c4b8c568cb04445b631d2310c212dc Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 27 Apr 2022 19:48:04 +0800 Subject: [PATCH 064/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8DAccessLogger=E5=A4=B1?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../logging/aop/ReactiveAopAccessLoggerSupport.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index 9ec6fbb60..adecd16d8 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -6,10 +6,7 @@ import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.id.IDGenerator; import org.hswebframework.web.logger.ReactiveLogger; -import org.hswebframework.web.logging.RequestInfo; -import org.hswebframework.web.logging.AccessLoggerInfo; -import org.hswebframework.web.logging.AccessLoggerListener; -import org.hswebframework.web.logging.LoggerDefine; +import org.hswebframework.web.logging.*; import org.hswebframework.web.logging.events.AccessLoggerAfterEvent; import org.hswebframework.web.logging.events.AccessLoggerBeforeEvent; import org.hswebframework.web.utils.FluxCache; @@ -18,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.Ordered; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.ClassUtils; import org.springframework.util.ConcurrentReferenceHashMap; @@ -188,6 +186,10 @@ public int getOrder() { @Override public boolean matches(Method method, Class aClass) { + AccessLogger ann = AnnotationUtils.findAnnotation(method, AccessLogger.class); + if (ann != null && ann.ignore()) { + return false; + } return loggerParsers .stream() .anyMatch(parser -> parser.support(aClass, method)); From ab06d54ee085b4697a4681c4bcc0bcc922463686 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 28 Apr 2022 18:03:19 +0800 Subject: [PATCH 065/416] =?UTF-8?q?=E4=BC=98=E5=8C=96token=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/oauth2/server/OAuth2Properties.java | 20 +++++++++++++++++++ .../server/OAuth2ServerAutoConfiguration.java | 10 ++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2Properties.java diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2Properties.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2Properties.java new file mode 100644 index 000000000..8956781c1 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2Properties.java @@ -0,0 +1,20 @@ +package org.hswebframework.web.oauth2.server; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.time.Duration; + +@ConfigurationProperties(prefix = "hsweb.oauth2") +@Getter +@Setter +public class OAuth2Properties { + + //token有效期 + private Duration tokenExpireIn = Duration.ofSeconds(7200); + + //refreshToken有效期 + private Duration refreshTokenIn = Duration.ofDays(30); + +} diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java index 66228cc79..6003a593f 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java @@ -18,11 +18,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; @Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(OAuth2Properties.class) public class OAuth2ServerAutoConfiguration { @@ -46,8 +48,12 @@ static class ReactiveOAuth2ServerAutoConfiguration { @Bean @ConditionalOnMissingBean - public AccessTokenManager accessTokenManager(ReactiveRedisConnectionFactory redisConnectionFactory) { - return new RedisAccessTokenManager(redisConnectionFactory); + public AccessTokenManager accessTokenManager(ReactiveRedisConnectionFactory redisConnectionFactory, + OAuth2Properties properties) { + RedisAccessTokenManager manager = new RedisAccessTokenManager(redisConnectionFactory); + manager.setTokenExpireIn((int) properties.getTokenExpireIn().getSeconds()); + manager.setRefreshExpireIn((int) properties.getRefreshTokenIn().getSeconds()); + return manager; } @Bean From a12289af5370eeac8dda5c1e9d9f80ed2e83a5c2 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 6 May 2022 10:19:00 +0800 Subject: [PATCH 066/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0exists=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReactiveServiceQueryController.java | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java index 51eed4f7f..d798dacad 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceQueryController.java @@ -167,7 +167,7 @@ default Mono> queryPager(@RequestBody Mono quer @QueryAction @Operation(summary = "使用POST方式查询总数") default Mono count(@RequestBody Mono query) { - return query.flatMap(this::count); + return getService().count(query); } /** @@ -175,7 +175,7 @@ default Mono count(@RequestBody Mono query) { * *

      *
-     *    GET /_query/_count?pageIndex=0&pageSize=20&where=name is 张三&orderBy=id desc
+     *    GET /_count?pageIndex=0&pageSize=20&where=name is 张三&orderBy=id desc
      *
      * 
* @@ -187,10 +187,39 @@ default Mono count(@RequestBody Mono query) { @QueryAction @QueryNoPagingOperation(summary = "使用GET方式查询总数") default Mono count(@Parameter(hidden = true) QueryParamEntity query) { - return getService() - .createQuery() - .setParam(query) - .count(); + return Mono.defer(() -> getService().count(query)); + } + + @PostMapping("/_exists") + @QueryAction + @Operation(summary = "使用POST方式判断数据是否存在") + default Mono exists(@RequestBody Mono query) { + return query + .flatMap(param -> getService() + .createQuery() + .setParam(param) + .fetchOne() + .hasElement()); + } + + /** + * 使用GET方式判断数据是否存在. + * + *
+     *
+     *    GET /_exists?where=name is 张三
+     *
+     * 
+ * + * @param query 查询条件 + * @return 查询结果 + * @see QueryParamEntity + */ + @GetMapping("/_exists") + @QueryAction + @QueryNoPagingOperation(summary = "使用GET方式判断数据是否存在") + default Mono exists(@Parameter(hidden = true) QueryParamEntity query) { + return exists(Mono.just(query)); } /** From d8a890a253b6e70c120a4e7ce92304f48d1948cd Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 17 May 2022 15:41:45 +0800 Subject: [PATCH 067/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hsweb-core/pom.xml | 3 ++- pom.xml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 00c463942..b38151361 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -18,7 +18,7 @@ org.javassist javassist - 3.28.0-GA + 3.29.0-GA @@ -51,6 +51,7 @@ org.slf4j slf4j-api + commons-beanutils commons-beanutils diff --git a/pom.xml b/pom.xml index 3b9d30506..9f4ceee33 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ 3.20.0-GA 5.19.0.2 - 1.2.74 + 1.2.80 1.4.200 5.1.39 3.2.2 @@ -96,7 +96,7 @@ 2.7.0 Arabba-SR10 - 5.2.19.RELEASE + 5.2.22.RELEASE From 6b99d542b991dcd537f0950a3162caeb899b74d2 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 19 May 2022 19:08:22 +0800 Subject: [PATCH 068/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=8F=8F=E8=BF=B0=E5=8F=AF=E8=83=BD=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/ReactiveAopAccessLoggerSupport.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index adecd16d8..76b5cf295 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -1,6 +1,6 @@ package org.hswebframework.web.logging.aop; -import lombok.SneakyThrows; +import lombok.*; import org.aopalliance.intercept.MethodInterceptor; import org.hswebframework.web.aop.MethodInterceptorHolder; import org.hswebframework.web.authorization.Authentication; @@ -47,7 +47,7 @@ public class ReactiveAopAccessLoggerSupport extends StaticMethodMatcherPointcutA @Autowired private ApplicationEventPublisher eventPublisher; - private final Map defineCache = new ConcurrentReferenceHashMap<>(); + private final Map defineCache = new ConcurrentReferenceHashMap<>(); private static final LoggerDefine UNSUPPORTED = new LoggerDefine(); @@ -135,7 +135,9 @@ protected AccessLoggerInfo createLogger(MethodInterceptorHolder holder) { info.setId(IDGenerator.MD5.generate()); info.setRequestTime(System.currentTimeMillis()); - LoggerDefine define = defineCache.computeIfAbsent(holder.getMethod(), method -> createDefine(holder)); + LoggerDefine define = defineCache.computeIfAbsent(new CacheKey( + ClassUtils.getUserClass(holder.getTarget()), + holder.getMethod()), method -> createDefine(holder)); if (define != null) { info.setAction(define.getAction()); @@ -215,4 +217,10 @@ private RequestInfo createAccessInfo(ServerWebExchange exchange) { return info; } + @AllArgsConstructor + @EqualsAndHashCode + private static class CacheKey{ + private Class type; + private Method method; + } } From 1a6108de2831d0fb0c3cb70ca54f41470a51cc11 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 19 May 2022 19:08:27 +0800 Subject: [PATCH 069/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/hswebframework/web/utils/HttpParameterConverter.java | 5 ++--- .../defaults/service/DefaultAuthorizationSettingService.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/utils/HttpParameterConverter.java b/hsweb-core/src/main/java/org/hswebframework/web/utils/HttpParameterConverter.java index 46257aa19..d61c1b0aa 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/utils/HttpParameterConverter.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/utils/HttpParameterConverter.java @@ -2,6 +2,7 @@ import org.apache.commons.beanutils.BeanMap; import org.hswebframework.utils.time.DateFormatter; +import org.hswebframework.web.bean.FastBeanCopier; import java.util.*; import java.util.function.Function; @@ -61,9 +62,7 @@ public HttpParameterConverter(Object bean) { if (bean instanceof Map) { beanMap = ((Map) bean); } else { - beanMap = new HashMap<>((Map) new BeanMap(bean)); - beanMap.remove("class"); - beanMap.remove("declaringClass"); + beanMap = FastBeanCopier.copy(bean,new HashMap<>()); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java index b71960930..1a9fe3d43 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java @@ -86,7 +86,7 @@ protected Mono clearUserAuthCache(List setting provider.getAllType() .map(DimensionType::getId) .map(t -> Tuples.of(t, provider))) - .collect(Collectors.toMap(Tuple2::getT1, Tuple2::getT2)) + .collectMap(Tuple2::getT1, Tuple2::getT2) .flatMapMany(typeProviderMapping -> Flux .fromIterable(settings)//根据维度获取所有userId .flatMap(setting -> Mono From 23e3da23a30ee65ed7249148e5959c9618fa92ad Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 20 May 2022 09:50:44 +0800 Subject: [PATCH 070/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../token/UserTokenReactiveAuthenticationSupplier.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java index 0b2e9dd59..c796c13fd 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java @@ -73,8 +73,14 @@ public Mono get() { .getOrEmpty(ParsedToken.class) .map(t -> userTokenManager .getByToken(t.getToken()) - .filter(UserToken::validate) .flatMap(token -> { + //已过期则返回空 + if (token.isExpired()) { + return Mono.empty(); + } + if(!token.validate()){ + return Mono.empty(); + } Mono before = userTokenManager.touch(token.getToken()); if (token instanceof AuthenticationUserToken) { return before.thenReturn(((AuthenticationUserToken) token).getAuthentication()); From cf9541a7f3fb9078ea141a9671442939bb76811d Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 23 May 2022 15:36:17 +0800 Subject: [PATCH 071/416] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E7=9A=84=E6=95=B0=E6=8D=AE=E8=BF=94=E5=9B=9E404?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/web/reactive/ReactiveServiceSaveController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java index cf82b783b..7d86b4510 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/reactive/ReactiveServiceSaveController.java @@ -9,6 +9,7 @@ import org.hswebframework.web.authorization.annotation.Authorize; import org.hswebframework.web.authorization.annotation.SaveAction; import org.hswebframework.web.crud.service.ReactiveCrudService; +import org.hswebframework.web.exception.NotFoundException; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -174,6 +175,11 @@ default Mono update(@PathVariable K id, @RequestBody Mono payload) { .flatMap(auth -> payload.map(entity -> applyAuthentication(entity, auth))) .switchIfEmpty(payload) .flatMap(entity -> getService().updateById(id, Mono.just(entity))) + .doOnNext(i -> { + if (i == 0) { + throw new NotFoundException(); + } + }) .thenReturn(true); } From ebe5a2e8d16c78e01ee5c90e4a03396296b40ba0 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 24 May 2022 14:39:49 +0800 Subject: [PATCH 072/416] fastjson 1.2.83 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f4ceee33..ca388f1e6 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ 3.20.0-GA 5.19.0.2 - 1.2.80 + 1.2.83 1.4.200 5.1.39 3.2.2 From 03b72a585be5944d6253decfb6c0f051fb0801c2 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 24 May 2022 15:52:29 +0800 Subject: [PATCH 073/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-starter/pom.xml | 13 ++++++++++++- pom.xml | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index e8b562365..13481ca8d 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -41,9 +41,9 @@ com.google.code.findbugs jsr305 - 3.0.2 compile + commons-codec commons-codec diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 5970be36b..4ee82b842 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -21,6 +21,12 @@ org.hswebframework hsweb-expands-script ${hsweb.expands.version} + + + junit + junit + + @@ -45,35 +51,40 @@ spring-test test + org.springframework.boot spring-boot-test-autoconfigure test + org.springframework.boot spring-boot-starter-test test + org.springframework.boot spring-boot-test test + org.springframework.boot spring-boot-starter-data-r2dbc test + io.r2dbc r2dbc-h2 test + com.google.code.findbugs jsr305 - 3.0.2 compile diff --git a/pom.xml b/pom.xml index ca388f1e6..cd1496d88 100644 --- a/pom.xml +++ b/pom.xml @@ -325,6 +325,13 @@ + + + com.google.code.findbugs + jsr305 + 3.0.2 + + io.r2dbc r2dbc-bom From a7c68770748357e390eef9c00eee254dcf4a757c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 7 Jun 2022 17:02:48 +0800 Subject: [PATCH 074/416] ignore EntityFactory aware error --- .../crud/entity/EntityFactoryHolderConfiguration.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java index 8dc3d6ceb..84074bfcc 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/EntityFactoryHolderConfiguration.java @@ -1,5 +1,6 @@ package org.hswebframework.web.api.crud.entity; +import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,7 +11,13 @@ public class EntityFactoryHolderConfiguration { @Bean public ApplicationContextAware entityFactoryHolder() { - return context -> EntityFactoryHolder.FACTORY = context.getBean(EntityFactory.class); + return context -> { + try { + EntityFactoryHolder.FACTORY = context.getBean(EntityFactory.class); + } catch (BeansException ignore) { + + } + }; } } From d134cda07b735c65302d2f22cd8ca07972a09a92 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 7 Jun 2022 17:06:22 +0800 Subject: [PATCH 075/416] jacoco 0.8.8 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cd1496d88..592e7028c 100644 --- a/pom.xml +++ b/pom.xml @@ -178,7 +178,7 @@ org.jacoco jacoco-maven-plugin - 0.8.0 + 0.8.8 @@ -221,7 +221,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.10.1 ${project.build.jdk} ${project.build.jdk} From c5a380f222bbb5d0bc3cbcb075e8ef923cea9cf0 Mon Sep 17 00:00:00 2001 From: Winston Date: Tue, 14 Jun 2022 20:07:14 +0800 Subject: [PATCH 076/416] AsyncEvent must not cancel the source past the first element --- .../web/event/DefaultAsyncEvent.java | 8 +++--- .../hswebframework/web/event/EventTest.java | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 hsweb-core/src/test/java/org/hswebframework/web/event/EventTest.java diff --git a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java index 298c0ff12..5ee7d9020 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/event/DefaultAsyncEvent.java @@ -15,23 +15,23 @@ public class DefaultAsyncEvent implements AsyncEvent { public synchronized void async(Publisher publisher) { hasListener = true; - this.async = async.then(Mono.from(publisher).then()); + this.async = async.then(Mono.fromDirect(publisher).then()); } @Override public synchronized void first(Publisher publisher) { hasListener = true; - this.first = Mono.from(publisher).then(first); + this.first = Mono.fromDirect(publisher).then(first); } @Override public void transformFirst(Function, Publisher> mapper) { - this.first = Mono.from(mapper.apply(this.first)); + this.first = Mono.fromDirect(mapper.apply(this.first)); } @Override public void transform(Function, Publisher> mapper) { - this.async = Mono.from(mapper.apply(this.async)); + this.async = Mono.fromDirect(mapper.apply(this.async)); } @Override diff --git a/hsweb-core/src/test/java/org/hswebframework/web/event/EventTest.java b/hsweb-core/src/test/java/org/hswebframework/web/event/EventTest.java new file mode 100644 index 000000000..1c9bbb5b0 --- /dev/null +++ b/hsweb-core/src/test/java/org/hswebframework/web/event/EventTest.java @@ -0,0 +1,27 @@ +package org.hswebframework.web.event; + +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Slf4j +public class EventTest { + + @Test + public void testMonoFrom() { + Flux source = Flux.just("1", "2", "3").doOnNext(s -> log.info("get {}", s)); + + Mono.from(source).subscribe(); + + Mono.fromDirect(source).subscribe(); + } + + @Test + public void testAsync() { + Flux source = Flux.just("1", "2", "3").doOnNext(s -> log.info("get {}", s)); + AsyncEvent event = new DefaultAsyncEvent(); + event.async(source); + event.getAsync().subscribe(); + } +} From 54e892375ee8727b880d530b3d9152eabb983af2 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 20 Jun 2022 11:50:27 +0800 Subject: [PATCH 077/416] easyorm 4.0.14 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 592e7028c..06b004dfe 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ 3.2.2 1.6.12 - 4.0.14-SNAPSHOT + 4.0.14 3.0.2 3.0.2 2.7.0 From 5b5ef55e65496b25d6b7b81bd2be677e03579b91 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 20 Jun 2022 13:49:46 +0800 Subject: [PATCH 078/416] 4.0.14 --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 2 +- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index b78ebb166..1c90aee12 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index 1d9548f1c..a0dbb5491 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index cfd6f7ffa..58eaba9ef 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index eae29abb9..1661afed4 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index 13481ca8d..219ea6baf 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index 3d80c02ed..dcaf82ba6 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index a95048ed0..81d29d19e 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index 27e913412..0aae21c47 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index 678172be7..c74a4c38d 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index b38151361..624b800ec 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index 017bd92ca..f2d290491 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 494446890..5abc007aa 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index 6d4b217fb..da091a257 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index c9449114e..491972668 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index 51d34eb87..7b76fe432 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index 72dd5b811..efae95a43 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index c0b0adaa1..78bce87e2 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 4ee82b842..93b2f5329 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index 0958d3092..c45a3a813 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index c5269c3f5..23b9932f1 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index 9a2488316..7dbdacf68 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index 081cf8074..ee7943885 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index 00ee64ca2..89f5fa072 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index c0f869ecc..0e45685db 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index eb48a52e7..db79806b6 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14-SNAPSHOT + 4.0.14 ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 06b004dfe..d59e18fc0 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.14-SNAPSHOT + 4.0.14 hsweb-starter hsweb-core From c655a20a357e27705ab63c6742954cc8227b15ca Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Jun 2022 09:54:52 +0800 Subject: [PATCH 079/416] 4.0.15-SNAPSHOT --- hsweb-authorization/hsweb-authorization-api/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-basic/pom.xml | 2 +- hsweb-authorization/hsweb-authorization-oauth2/pom.xml | 2 +- hsweb-authorization/pom.xml | 2 +- hsweb-commons/hsweb-commons-api/pom.xml | 2 +- hsweb-commons/hsweb-commons-crud/pom.xml | 2 +- hsweb-commons/pom.xml | 2 +- hsweb-concurrent/hsweb-concurrent-cache/pom.xml | 2 +- hsweb-concurrent/pom.xml | 2 +- hsweb-core/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-api/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-jta/pom.xml | 2 +- hsweb-datasource/hsweb-datasource-web/pom.xml | 2 +- hsweb-datasource/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-aop/pom.xml | 2 +- hsweb-logging/hsweb-access-logging-api/pom.xml | 2 +- hsweb-logging/pom.xml | 2 +- hsweb-starter/pom.xml | 2 +- .../hsweb-system-authorization-api/pom.xml | 2 +- .../hsweb-system-authorization-default/pom.xml | 2 +- .../hsweb-system-authorization-oauth2/pom.xml | 2 +- hsweb-system/hsweb-system-authorization/pom.xml | 2 +- hsweb-system/hsweb-system-dictionary/pom.xml | 2 +- hsweb-system/hsweb-system-file/pom.xml | 2 +- hsweb-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/pom.xml b/hsweb-authorization/hsweb-authorization-api/pom.xml index 1c90aee12..787d6abe2 100644 --- a/hsweb-authorization/hsweb-authorization-api/pom.xml +++ b/hsweb-authorization/hsweb-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-basic/pom.xml b/hsweb-authorization/hsweb-authorization-basic/pom.xml index a0dbb5491..615c07198 100644 --- a/hsweb-authorization/hsweb-authorization-basic/pom.xml +++ b/hsweb-authorization/hsweb-authorization-basic/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml index 58eaba9ef..f86d28db9 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/pom.xml +++ b/hsweb-authorization/hsweb-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-authorization/pom.xml b/hsweb-authorization/pom.xml index 1661afed4..e5a24f830 100644 --- a/hsweb-authorization/pom.xml +++ b/hsweb-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-api/pom.xml b/hsweb-commons/hsweb-commons-api/pom.xml index 219ea6baf..b4ac2168d 100644 --- a/hsweb-commons/hsweb-commons-api/pom.xml +++ b/hsweb-commons/hsweb-commons-api/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/hsweb-commons-crud/pom.xml b/hsweb-commons/hsweb-commons-crud/pom.xml index dcaf82ba6..e029e2a4e 100644 --- a/hsweb-commons/hsweb-commons-crud/pom.xml +++ b/hsweb-commons/hsweb-commons-crud/pom.xml @@ -5,7 +5,7 @@ hsweb-commons org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-commons/pom.xml b/hsweb-commons/pom.xml index 81d29d19e..a3fed49ca 100644 --- a/hsweb-commons/pom.xml +++ b/hsweb-commons/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml index 0aae21c47..fe2f8afce 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/pom.xml +++ b/hsweb-concurrent/hsweb-concurrent-cache/pom.xml @@ -5,7 +5,7 @@ hsweb-concurrent org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-concurrent/pom.xml b/hsweb-concurrent/pom.xml index c74a4c38d..4b6c20efb 100644 --- a/hsweb-concurrent/pom.xml +++ b/hsweb-concurrent/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-core/pom.xml b/hsweb-core/pom.xml index 624b800ec..e432f92e6 100644 --- a/hsweb-core/pom.xml +++ b/hsweb-core/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-datasource/hsweb-datasource-api/pom.xml b/hsweb-datasource/hsweb-datasource-api/pom.xml index f2d290491..c7782bc93 100644 --- a/hsweb-datasource/hsweb-datasource-api/pom.xml +++ b/hsweb-datasource/hsweb-datasource-api/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-jta/pom.xml b/hsweb-datasource/hsweb-datasource-jta/pom.xml index 5abc007aa..a758c5894 100644 --- a/hsweb-datasource/hsweb-datasource-jta/pom.xml +++ b/hsweb-datasource/hsweb-datasource-jta/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/hsweb-datasource-web/pom.xml b/hsweb-datasource/hsweb-datasource-web/pom.xml index da091a257..fc4644372 100644 --- a/hsweb-datasource/hsweb-datasource-web/pom.xml +++ b/hsweb-datasource/hsweb-datasource-web/pom.xml @@ -5,7 +5,7 @@ hsweb-datasource org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml diff --git a/hsweb-datasource/pom.xml b/hsweb-datasource/pom.xml index 491972668..f125b2e11 100644 --- a/hsweb-datasource/pom.xml +++ b/hsweb-datasource/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml diff --git a/hsweb-logging/hsweb-access-logging-aop/pom.xml b/hsweb-logging/hsweb-access-logging-aop/pom.xml index 7b76fe432..0f7157c35 100644 --- a/hsweb-logging/hsweb-access-logging-aop/pom.xml +++ b/hsweb-logging/hsweb-access-logging-aop/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/hsweb-access-logging-api/pom.xml b/hsweb-logging/hsweb-access-logging-api/pom.xml index efae95a43..3313185c8 100644 --- a/hsweb-logging/hsweb-access-logging-api/pom.xml +++ b/hsweb-logging/hsweb-access-logging-api/pom.xml @@ -5,7 +5,7 @@ hsweb-logging org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-logging/pom.xml b/hsweb-logging/pom.xml index 78bce87e2..3b773da34 100644 --- a/hsweb-logging/pom.xml +++ b/hsweb-logging/pom.xml @@ -23,7 +23,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-starter/pom.xml b/hsweb-starter/pom.xml index 93b2f5329..d45ac4ec7 100644 --- a/hsweb-starter/pom.xml +++ b/hsweb-starter/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml index c45a3a813..c867f8768 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml index 23b9932f1..bbb0f6646 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml index 7dbdacf68..32095d63b 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml @@ -5,7 +5,7 @@ hsweb-system-authorization org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/hsweb-system/hsweb-system-authorization/pom.xml b/hsweb-system/hsweb-system-authorization/pom.xml index ee7943885..bc4bbd91b 100644 --- a/hsweb-system/hsweb-system-authorization/pom.xml +++ b/hsweb-system/hsweb-system-authorization/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 pom diff --git a/hsweb-system/hsweb-system-dictionary/pom.xml b/hsweb-system/hsweb-system-dictionary/pom.xml index 89f5fa072..7ebc9237b 100644 --- a/hsweb-system/hsweb-system-dictionary/pom.xml +++ b/hsweb-system/hsweb-system-dictionary/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-system/hsweb-system-file/pom.xml b/hsweb-system/hsweb-system-file/pom.xml index 0e45685db..e15b4a25f 100644 --- a/hsweb-system/hsweb-system-file/pom.xml +++ b/hsweb-system/hsweb-system-file/pom.xml @@ -5,7 +5,7 @@ hsweb-system org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT 4.0.0 diff --git a/hsweb-system/pom.xml b/hsweb-system/pom.xml index db79806b6..8dba5961d 100644 --- a/hsweb-system/pom.xml +++ b/hsweb-system/pom.xml @@ -5,7 +5,7 @@ hsweb-framework org.hswebframework.web - 4.0.14 + 4.0.15-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index d59e18fc0..8854cd5de 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ org.hswebframework.web hsweb-framework - 4.0.14 + 4.0.15-SNAPSHOT hsweb-starter hsweb-core From 9788fd80464d983f3baab3c5721f52846e50e596 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 27 Jun 2022 09:55:03 +0800 Subject: [PATCH 080/416] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=87=E4=BB=B6=E6=9D=83=E9=99=90=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/file/FileUploadProperties.java | 25 +++++++++++++++++++ .../file/service/LocalFileStorageService.java | 6 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java index 7412302de..88eb89afe 100644 --- a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java +++ b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/FileUploadProperties.java @@ -9,6 +9,13 @@ import org.springframework.http.MediaType; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Collections; import java.util.Date; import java.util.Locale; import java.util.Set; @@ -33,6 +40,24 @@ public class FileUploadProperties { private Set denyMediaType; + private Set permissions; + + public void applyFilePermission(File file) { + + if (CollectionUtils.isEmpty(permissions)) { + return; + } + try { + Path path = Paths.get(file.toURI()); + PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class); + view.setPermissions(permissions); + } catch (Throwable ignore) { + + } + + + } + public boolean denied(String name, MediaType mediaType) { String suffix = (name.contains(".") ? name.substring(name.lastIndexOf(".") + 1) : "").toLowerCase(Locale.ROOT); boolean defaultDeny = false; diff --git a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java index 4d46cd7db..e30b34db5 100644 --- a/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java +++ b/hsweb-system/hsweb-system-file/src/main/java/org/hswebframework/web/file/service/LocalFileStorageService.java @@ -24,8 +24,11 @@ public class LocalFileStorageService implements FileStorageService { @Override public Mono saveFile(FilePart filePart) { FileUploadProperties.StaticFileInfo info = properties.createStaticSavePath(filePart.filename()); + File file = new File(info.getSavePath()); + return (filePart) - .transferTo(new File(info.getSavePath())) + .transferTo(file) + .then(Mono.fromRunnable(()->properties.applyFilePermission(file))) .thenReturn(info.getLocation()); } @@ -57,6 +60,7 @@ public Mono saveFile(InputStream inputStream, String fileType) { return info.getLocation(); } }) + .doOnSuccess((ignore)-> properties.applyFilePermission(new File(info.getSavePath()))) .subscribeOn(Schedulers.boundedElastic()); } } From 1da33b79d225bec82972ba08bfbb189710316d86 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 30 Jun 2022 19:43:21 +0800 Subject: [PATCH 081/416] =?UTF-8?q?ClearUserAuthorizationCacheEvent=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=93=8D=E5=BA=94=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ClearUserAuthorizationCacheEvent.java | 19 +++++++- .../DefaultAuthorizationSettingService.java | 3 +- .../service/DefaultDimensionUserService.java | 13 +++--- .../service/DefaultPermissionService.java | 18 +++++--- .../DefaultReactiveAuthenticationManager.java | 43 ++++++++++++------- .../service/DefaultReactiveUserService.java | 7 +-- 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java index 6f6dfc02c..685838bbd 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/event/ClearUserAuthorizationCacheEvent.java @@ -1,6 +1,9 @@ package org.hswebframework.web.system.authorization.api.event; import lombok.Getter; +import org.hswebframework.web.event.DefaultAsyncEvent; +import org.springframework.context.ApplicationEventPublisher; +import reactor.core.publisher.Mono; import java.util.Arrays; import java.util.Collection; @@ -13,11 +16,13 @@ * @since 3.0.0-RC */ @Getter -public class ClearUserAuthorizationCacheEvent { +public class ClearUserAuthorizationCacheEvent extends DefaultAsyncEvent { private Set userId; private boolean all; + private boolean async; + public static ClearUserAuthorizationCacheEvent of(Collection collection) { ClearUserAuthorizationCacheEvent event = new ClearUserAuthorizationCacheEvent(); if (collection == null || collection.isEmpty()) { @@ -32,6 +37,18 @@ public static ClearUserAuthorizationCacheEvent all() { return ClearUserAuthorizationCacheEvent.of((String[]) null); } + //兼容async + public ClearUserAuthorizationCacheEvent useAsync() { + this.async = true; + return this; + } + + @Override + public Mono publish(ApplicationEventPublisher eventPublisher) { + this.async = true; + return super.publish(eventPublisher); + } + public static ClearUserAuthorizationCacheEvent of(String... userId) { return of(userId == null ? null : Arrays.asList(userId)); diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java index 1a9fe3d43..3f3af051a 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultAuthorizationSettingService.java @@ -93,8 +93,7 @@ protected Mono clearUserAuthCache(List setting .justOrEmpty(typeProviderMapping.get(setting.getDimensionType())) .flatMapMany(provider -> provider.getUserIdByDimensionId(setting.getDimensionTarget())))) .collectList() - .map(ClearUserAuthorizationCacheEvent::of) - .doOnNext(eventPublisher::publishEvent) + .flatMap(lst-> ClearUserAuthorizationCacheEvent.of(lst).publish(eventPublisher)) .then(); } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java index 2ab396a51..af9489925 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java @@ -123,10 +123,11 @@ private Flux publishEvent(Publisher st return dimensionIdGroup .map(DimensionUserEntity::getUserId) .collectList() - .flatMap(userIdList -> { - eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of(userIdList)); - return event.apply(type, dimensionId, userIdList).publish(eventPublisher); - }); + .flatMap(userIdList -> ClearUserAuthorizationCacheEvent + .of(userIdList) + .publish(eventPublisher) + .then(event.apply(type, dimensionId, userIdList) + .publish(eventPublisher))); }); }) .thenMany(cache); @@ -137,9 +138,7 @@ private Mono clearUserCache(List entities) { .map(DimensionUserEntity::getUserId) .distinct() .collectList() - .map(ClearUserAuthorizationCacheEvent::of) - .doOnNext(eventPublisher::publishEvent) - .then(); + .flatMap(list -> ClearUserAuthorizationCacheEvent.of(list).publish(eventPublisher)); } } \ No newline at end of file diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultPermissionService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultPermissionService.java index a59a7fe32..bdd207544 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultPermissionService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultPermissionService.java @@ -19,31 +19,39 @@ public class DefaultPermissionService extends GenericReactiveCrudService save(Publisher entityPublisher) { return super.save(entityPublisher) - .doOnSuccess(r -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of())); + .flatMap(e -> ClearUserAuthorizationCacheEvent.all().publish(eventPublisher).thenReturn(e)); } @Override public Mono updateById(String id, Mono entityPublisher) { return super.updateById(id, entityPublisher) - .doOnSuccess(r -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of())); + .flatMap(e -> ClearUserAuthorizationCacheEvent.all().publish(eventPublisher).thenReturn(e)); } @Override public Mono deleteById(Publisher idPublisher) { return super.deleteById(idPublisher) - .doOnSuccess(r -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of())); + .flatMap(e -> ClearUserAuthorizationCacheEvent.all().publish(eventPublisher).thenReturn(e)); } @Override public ReactiveDelete createDelete() { return super.createDelete() - .onExecute((ignore,i) -> i.doOnSuccess(r -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of()))); + .onExecute((ignore, i) -> i + .flatMap(e -> ClearUserAuthorizationCacheEvent + .all() + .publish(eventPublisher) + .thenReturn(e))); } @Override public ReactiveUpdate createUpdate() { return super.createUpdate() - .onExecute((ignore,i) -> i.doOnSuccess(r -> eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of()))); + .onExecute((ignore, i) -> i + .flatMap(e -> ClearUserAuthorizationCacheEvent + .all() + .publish(eventPublisher) + .thenReturn(e))); } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java index cb4ec3b8c..a0eb4f30f 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationManager.java @@ -1,18 +1,17 @@ package org.hswebframework.web.system.authorization.defaults.service; import lombok.extern.slf4j.Slf4j; -import org.hswebframework.web.authorization.*; -import org.hswebframework.web.authorization.exception.AccessDenyException; +import org.hswebframework.web.authorization.Authentication; +import org.hswebframework.web.authorization.AuthenticationRequest; +import org.hswebframework.web.authorization.ReactiveAuthenticationInitializeService; +import org.hswebframework.web.authorization.ReactiveAuthenticationManagerProvider; import org.hswebframework.web.authorization.simple.PlainTextUsernamePasswordAuthenticationRequest; import org.hswebframework.web.cache.ReactiveCacheManager; import org.hswebframework.web.system.authorization.api.entity.UserEntity; import org.hswebframework.web.system.authorization.api.event.ClearUserAuthorizationCacheEvent; import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.CacheManager; -import org.springframework.cache.support.SimpleValueWrapper; import org.springframework.context.event.EventListener; -import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import reactor.core.publisher.Mono; @@ -32,18 +31,25 @@ public class DefaultReactiveAuthenticationManager implements ReactiveAuthenticat @EventListener public void handleClearAuthCache(ClearUserAuthorizationCacheEvent event) { if (cacheManager != null) { + Mono operator; if (event.isAll()) { - cacheManager.getCache("user-auth") + operator = cacheManager + .getCache("user-auth") .clear() .doOnSuccess(nil -> log.info("clear all user authentication cache success")) - .doOnError(err -> log.error(err.getMessage(), err)) - .subscribe(); + .doOnError(err -> log.error(err.getMessage(), err)); } else { - cacheManager.getCache("user-auth") + operator = cacheManager + .getCache("user-auth") .evictAll(event.getUserId()) .doOnError(err -> log.error(err.getMessage(), err)) - .doOnSuccess(__ -> log.info("clear user {} authentication cache success", event.getUserId())) - .subscribe(); + .doOnSuccess(__ -> log.info("clear user {} authentication cache success", event.getUserId())); + } + if (event.isAsync()) { + event.async(operator); + } else { + log.warn("please use async for ClearUserAuthorizationCacheEvent"); + operator.subscribe(); } } } @@ -62,11 +68,16 @@ public Mono authenticate(Mono request) { @Override public Mono getByUserId(String userId) { + if (userId == null) { + return Mono.empty(); + } + if (cacheManager == null) { + return initializeService.initUserAuthorization(userId); + } - return Mono.justOrEmpty(userId) - .flatMap(_id -> Mono.justOrEmpty(cacheManager) - .map(cm -> cacheManager.getCache("user-auth")) - .flatMap(cache -> cache.mono(userId).onCacheMissResume(() -> initializeService.initUserAuthorization(userId))) - .cast(Authentication.class)); + return cacheManager + .getCache("user-auth") + .mono(userId) + .onCacheMissResume(() -> initializeService.initUserAuthorization(userId)); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java index 2f771c7a3..b90247e24 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java @@ -110,9 +110,10 @@ protected Mono doUpdate(UserEntity userEntity) { .execute() .flatMap(__ -> new UserModifiedEvent(userEntity, passwordChanged).publish(eventPublisher)) .thenReturn(userEntity) - .doOnNext(e -> { - eventPublisher.publishEvent(ClearUserAuthorizationCacheEvent.of(e.getId())); - }); + .flatMap(e -> ClearUserAuthorizationCacheEvent + .of(e.getId()) + .publish(eventPublisher) + .thenReturn(e)); }); } From 6814c8305095852bd6393e347b91b8e8130a58ad Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 1 Jul 2022 18:20:18 +0800 Subject: [PATCH 082/416] =?UTF-8?q?=E4=BC=98=E5=8C=96token=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/authorization/token/LocalUserToken.java | 12 ++++++++++++ .../token/redis/SimpleUserToken.java | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/LocalUserToken.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/LocalUserToken.java index c562e1b0e..a157ee7f9 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/LocalUserToken.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/LocalUserToken.java @@ -74,9 +74,21 @@ public String getToken() { @Override public TokenState getState() { + if (state == TokenState.normal) { + checkExpired(); + } return state; } + @Override + public boolean checkExpired() { + if (UserToken.super.checkExpired()) { + setState(TokenState.expired); + return true; + } + return false; + } + public void setState(TokenState state) { this.state = state; } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/SimpleUserToken.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/SimpleUserToken.java index d986bda34..6e931ba73 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/SimpleUserToken.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/SimpleUserToken.java @@ -35,18 +35,25 @@ public class SimpleUserToken implements UserToken { public static SimpleUserToken of(Map map) { Object authentication = map.get("authentication"); - if(authentication instanceof Authentication){ + if (authentication instanceof Authentication) { return FastBeanCopier.copy(map, new SimpleAuthenticationUserToken(((Authentication) authentication))); } return FastBeanCopier.copy(map, new SimpleUserToken()); } + public TokenState getState() { + if (state == TokenState.normal) { + checkExpired(); + } + return state; + } + @Override - public boolean isNormal() { - if (checkExpired()) { + public boolean checkExpired() { + if (UserToken.super.checkExpired()) { setState(TokenState.expired); - return false; + return true; } - return UserToken.super.isNormal(); + return false; } } From 45059239f45afaf35dc6a081b4685709a508ee10 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 20 Jul 2022 18:36:39 +0800 Subject: [PATCH 083/416] =?UTF-8?q?=E4=BC=98=E5=8C=96autoinit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/starter/HswebAutoConfiguration.java | 36 +++++++++++-------- .../starter/initialize/SystemInitialize.java | 1 + 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java index f8e3f7009..f78873797 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/HswebAutoConfiguration.java @@ -37,9 +37,9 @@ public class HswebAutoConfiguration { @PostConstruct public void init() { engines = Stream.of("js", "groovy") - .map(DynamicScriptEngineFactory::getEngine) - .filter(Objects::nonNull) - .collect(Collectors.toList()); + .map(DynamicScriptEngineFactory::getEngine) + .filter(Objects::nonNull) + .collect(Collectors.toList()); addGlobalVariable("logger", LoggerFactory.getLogger("org.hswebframework.script")); @@ -48,11 +48,11 @@ public void init() { private void addGlobalVariable(String var, Object val) { engines.forEach(engine -> { - try { - engine.addGlobalVariable(Collections.singletonMap(var, val)); - } catch (NullPointerException ignore) { - } - } + try { + engine.addGlobalVariable(Collections.singletonMap(var, val)); + } catch (NullPointerException ignore) { + } + } ); } @@ -61,15 +61,21 @@ public CommandLineRunner systemInit(DatabaseOperator database, AppProperties properties) { addGlobalVariable("database", database); - addGlobalVariable("sqlExecutor", database.getMetadata().getFeature(SyncSqlExecutor.ID) - .orElseGet(() -> database.getMetadata().getFeature(ReactiveSqlExecutor.ID) - .map(ReactiveSyncSqlExecutor::of).orElse(null))); + addGlobalVariable("sqlExecutor", database + .getMetadata() + .getFeature(SyncSqlExecutor.ID) + .orElseGet(() -> database + .getMetadata() + .getFeature(ReactiveSqlExecutor.ID) + .map(ReactiveSyncSqlExecutor::of) + .orElse(null))); SystemVersion version = properties.build(); return args -> { - - SystemInitialize initialize = new SystemInitialize(database, version); - initialize.setExcludeTables(properties.getInitTableExcludes()); - initialize.install(); + if (properties.isAutoInit()) { + SystemInitialize initialize = new SystemInitialize(database, version); + initialize.setExcludeTables(properties.getInitTableExcludes()); + initialize.install(); + } }; } diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/initialize/SystemInitialize.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/initialize/SystemInitialize.java index b544fc23f..2c8dc32e9 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/initialize/SystemInitialize.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/initialize/SystemInitialize.java @@ -184,6 +184,7 @@ protected void initInstallInfo() { .addDecoder(ClobValueCodec.INSTANCE) .addDecoder(JsonValueCodec.ofCollection(List.class, Dependency.class)))).notNull().comment("依赖详情").commit() .comment("系统信息") + .allowAlter(false) .commit() .sync(); system = database.dml().createRepository("s_system"); From 5f3bc0fcaf23538b9c2f3ce1e9d787c89432bb82 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 21 Jul 2022 18:35:07 +0800 Subject: [PATCH 084/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/events/EntityEventListener.java | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index 9595da9cc..94e82b682 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -16,6 +16,7 @@ import org.hswebframework.ezorm.rdb.mapping.events.ReactiveResultHolder; import org.hswebframework.ezorm.rdb.metadata.RDBColumnMetadata; import org.hswebframework.ezorm.rdb.metadata.TableOrViewMetadata; +import org.hswebframework.ezorm.rdb.operator.builder.fragments.NativeSql; import org.hswebframework.web.api.crud.entity.Entity; import org.hswebframework.web.bean.FastBeanCopier; import org.hswebframework.web.event.AsyncEvent; @@ -147,30 +148,23 @@ protected List createAfterData(List olds, } for (Object old : olds) { Object newValue = context - .get(MappingContextKeys.instance) - .filter(Entity.class::isInstance) - .map(Entity.class::cast) - .orElseGet(() -> { - return context - .get(MappingContextKeys.updateColumnInstance) - .map(map -> { - Object data = FastBeanCopier.copy(map, FastBeanCopier.copy(old, mapping.getEntityType())); - //set null - for (Map.Entry stringObjectEntry : map.entrySet()) { - if (stringObjectEntry.getValue() == null || stringObjectEntry.getValue() instanceof NullValue) { - GlobalConfig - .getPropertyOperator() - .setProperty(data, stringObjectEntry.getKey(), null); - } - } - return data; - }) - .map(Entity.class::cast) - .orElse(null); + .get(MappingContextKeys.updateColumnInstance) + .map(map -> { + Object data = FastBeanCopier.copy(map, FastBeanCopier.copy(old, mapping.newInstance())); + for (Map.Entry entry : map.entrySet()) { + //set null + if (entry.getValue() == null + || entry.getValue() instanceof NullValue) { + GlobalConfig + .getPropertyOperator() + .setProperty(data, entry.getKey(), null); + } + } + return data; + }) + .orElseThrow(() -> { + return new IllegalArgumentException("can not get update instance"); }); - if (newValue != null) { - FastBeanCopier.copy(old, newValue, FastBeanCopier.include(idColumn.getAlias())); - } newValues.add(newValue); } return newValues; From 9b4280ade1dcf3bcca3d074a60dd316e1dde3e65 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 28 Jul 2022 15:18:57 +0800 Subject: [PATCH 085/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/bean/ClassDescription.java | 7 ++++ .../web/bean/ClassDescriptions.java | 4 +- .../web/bean/FastBeanCopier.java | 40 ++++++++++++++----- .../web/bean/SingleValueMap.java | 6 +-- .../org/hswebframework/web/dict/EnumDict.java | 24 +++++++---- .../web/bean/FastBeanCopierTest.java | 9 +++++ 6 files changed, 68 insertions(+), 22 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java index 9de02b6b0..df1893ed3 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescription.java @@ -15,6 +15,8 @@ public class ClassDescription { private final boolean enumDict; private final int fieldSize; + private final Object[] enums; + public ClassDescription(Class type) { this.type = type; collectionType = Collection.class.isAssignableFrom(type); @@ -22,6 +24,11 @@ public ClassDescription(Class type) { arrayType = type.isArray(); enumType = type.isEnum(); fieldSize = type.getDeclaredFields().length; + if (enumType) { + enums = type.getEnumConstants(); + } else { + enums = null; + } } } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java index c5af73b58..731a50b41 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/ClassDescriptions.java @@ -1,12 +1,12 @@ package org.hswebframework.web.bean; -import org.jctools.maps.NonBlockingHashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class ClassDescriptions { - private static final Map, ClassDescription> CACHE = new NonBlockingHashMap<>(); + private static final Map, ClassDescription> CACHE = new ConcurrentHashMap<>(); public static ClassDescription getDescription(Class type) { return CACHE.computeIfAbsent(type, ClassDescription::new); diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java index 23c6919c8..de0eea385 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java @@ -14,6 +14,7 @@ import org.jctools.maps.NonBlockingHashMap; import org.springframework.core.ResolvableType; import org.springframework.util.ClassUtils; +import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; import java.beans.PropertyDescriptor; @@ -88,6 +89,9 @@ public boolean contains(Object o) { } public static Object getProperty(Object source, String key) { + if (source instanceof Map) { + return ((Map) source).get(key); + } SingleValueMap map = new SingleValueMap<>(); copy(source, map, include(key)); return map.getValue(); @@ -117,7 +121,16 @@ public static T copy(S source, T target, Set ignore) { @SuppressWarnings("all") public static T copy(S source, T target, Converter converter, Set ignore) { if (source instanceof Map && target instanceof Map) { - ((Map) target).putAll(((Map) source)); + if (CollectionUtils.isEmpty(ignore)) { + ((Map) target).putAll(((Map) source)); + } else { + ((Map) source) + .forEach((k, v) -> { + if (!ignore.contains(k)) { + ((Map) target).put(k, v); + } + }); + } return target; } @@ -584,20 +597,29 @@ public T convert(Object source, Class targetClass, Class[] genericType) { if (target.isEnumType()) { if (target.isEnumDict()) { String strVal = String.valueOf(source); - - Object val = EnumDict.find((Class) targetClass, e -> { - return e.eq(source) || e.name().equalsIgnoreCase(strVal); - }).orElse(null); + Object val = null; + for (Object anEnum : target.getEnums()) { + EnumDict dic = ((EnumDict) anEnum); + Enum e = ((Enum) anEnum); + if (dic.eq(source) || e.name().equalsIgnoreCase(strVal)) { + val = (T) anEnum; + break; + } + } + if (val == null) { + return null; + } if (targetClass.isInstance(val)) { return ((T) val); } return convert(val, targetClass, genericType); } String strSource = String.valueOf(source); - for (T t : targetClass.getEnumConstants()) { - if (((Enum) t).name().equalsIgnoreCase(strSource) - || Objects.equals(String.valueOf(((Enum) t).ordinal()), strSource)) { - return t; + for (Object e : target.getEnums()) { + Enum t = ((Enum) e); + if ((t.name().equalsIgnoreCase(strSource) + || Objects.equals(String.valueOf(t.ordinal()), strSource))) { + return (T)e; } } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java index 08c024c61..b37221a38 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/SingleValueMap.java @@ -28,7 +28,7 @@ public boolean containsValue(Object value) { @Override public V get(Object key) { - return null; + return Objects.equals(key, this.key) ? value : null; } @Override @@ -50,9 +50,9 @@ public V remove(Object key) { } @Override - public void putAll(Map m) { + public void putAll(Map m) { if (m.size() > 0) { - Map.Entry entry = m.entrySet().iterator().next(); + Map.Entry entry = m.entrySet().iterator().next(); this.key = entry.getKey(); this.value = entry.getValue(); } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java b/hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java index ac5494c0b..5d4e1137a 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/dict/EnumDict.java @@ -19,6 +19,8 @@ import lombok.NoArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.hswebframework.web.bean.ClassDescription; +import org.hswebframework.web.bean.ClassDescriptions; import org.hswebframework.web.exception.ValidationException; import org.hswebframework.web.i18n.LocaleUtils; import org.springframework.beans.BeanUtils; @@ -135,20 +137,25 @@ default String getComments() { * @param 枚举类型 * @return 查找到的结果 */ + @SuppressWarnings("all") static Optional find(Class type, Predicate predicate) { - if (type.isEnum()) { - for (T enumDict : type.getEnumConstants()) { - if (predicate.test(enumDict)) { - return Optional.of(enumDict); + ClassDescription description = ClassDescriptions.getDescription(type); + if (description.isEnumType()) { + for (Object enumDict : description.getEnums()) { + if (predicate.test((T) enumDict)) { + return Optional.of((T) enumDict); } } } return Optional.empty(); } + @SuppressWarnings("all") static List findList(Class type, Predicate predicate) { - if (type.isEnum()) { - return Arrays.stream(type.getEnumConstants()) + ClassDescription description = ClassDescriptions.getDescription(type); + if (description.isEnumType()) { + return Arrays.stream(description.getEnums()) + .map(v -> (T) v) .filter(predicate) .collect(Collectors.toList()); } @@ -199,7 +206,8 @@ static long toMask(T... t) { @SafeVarargs static boolean in(T target, T... t) { - Enum[] all = target.getClass().getEnumConstants(); + ClassDescription description= ClassDescriptions.getDescription(target.getClass()); + Object[] all = description.getEnums(); if (all.length >= 64) { List list = Arrays.asList(t); @@ -385,7 +393,7 @@ public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOE return e.name(); }).collect(Collectors.toList()); - return new ValidationException(currentName,"validation.parameter_does_not_exist_in_enums", currentName); + return new ValidationException(currentName, "validation.parameter_does_not_exist_in_enums", currentName); }; if (EnumDict.class.isAssignableFrom(findPropertyType) && findPropertyType.isEnum()) { if (node.isObject()) { diff --git a/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java b/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java index f04d33f0f..fe7e177e4 100644 --- a/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java +++ b/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java @@ -1,5 +1,7 @@ package org.hswebframework.web.bean; +import com.google.common.collect.ImmutableMap; +import jdk.nashorn.internal.objects.annotations.Getter; import org.junit.Assert; import org.junit.Test; @@ -113,6 +115,13 @@ public void testProxy() { Assert.assertEquals(reference.get(),source.getName()); } + @Test + public void testGetProperty(){ + + Assert.assertEquals(1,FastBeanCopier.getProperty(ImmutableMap.of("a",1,"b",2),"a")); + + } + public interface ProxyTest { String getName(); From 4f30e44f1104707685df902902122c12a4ccaf1f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 29 Jul 2022 16:42:26 +0800 Subject: [PATCH 086/416] =?UTF-8?q?=E5=A6=82=E6=9E=9C=E5=B7=B2=E7=BB=8F?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E4=BA=86=E6=8E=92=E5=BA=8F=E5=88=99=E4=B8=8D?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E5=BA=8F=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/api/crud/entity/TreeSupportEntity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java index 10dc2f3b9..9d01bca8f 100644 --- a/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java +++ b/hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java @@ -224,7 +224,9 @@ static , PK> void expandTree2List(T root, List Date: Fri, 29 Jul 2022 17:29:31 +0800 Subject: [PATCH 087/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/i18n/authentication/messages_zh.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/authentication/messages_zh.properties b/hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/authentication/messages_zh.properties index a9bd62303..4c349297b 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/authentication/messages_zh.properties +++ b/hsweb-authorization/hsweb-authorization-api/src/main/resources/i18n/authentication/messages_zh.properties @@ -1,4 +1,4 @@ -error.access_denied=权限不足,拒绝访问! +error.access_denied=暂无权限,请联系管理员! error.permission_denied=当前用户无权限[{0}]:{1} error.logged_in_elsewhere=该用户已在其他地方登陆 error.illegal_password=用户名或密码错误 From 63a15a1af37e6df8a94ca6fad5b7152f16bdc653 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Sat, 30 Jul 2022 10:08:54 +0800 Subject: [PATCH 088/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/web/CommonWebFluxConfiguration.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java index 9a2c8e7b6..dc3f338a4 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java @@ -1,6 +1,5 @@ package org.hswebframework.web.crud.web; -import io.r2dbc.spi.R2dbcDataIntegrityViolationException; import org.hswebframework.web.i18n.WebFluxLocaleFilter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -33,12 +32,6 @@ public ResponseMessageWrapper responseMessageWrapper(ServerCodecConfigurer codec return new ResponseMessageWrapper(codecConfigurer.getWriters(), resolver, registry); } - @Bean - public R2dbcDataIntegrityViolationException r2dbcDataIntegrityViolationException(){ - return new R2dbcDataIntegrityViolationException(); - } - - @Bean public WebFilter localeWebFilter() { return new WebFluxLocaleFilter(); From 3416fd24d6388701b111418bc11da1aa48d24097 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 3 Aug 2022 09:22:27 +0800 Subject: [PATCH 089/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E6=BA=AF=E6=BA=90=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/I18nSupportException.java | 2 +- .../web/exception/TraceSourceException.java | 50 +++++++++++++++++++ .../web/validator/ValidatorUtils.java | 6 +-- 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java index 6213a36c8..21341a0e9 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java @@ -19,7 +19,7 @@ */ @Getter @Setter(AccessLevel.PROTECTED) -public class I18nSupportException extends RuntimeException { +public class I18nSupportException extends TraceSourceException { /** * 消息code,在message.properties文件中定义的key diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java new file mode 100644 index 000000000..89174fa8e --- /dev/null +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java @@ -0,0 +1,50 @@ +package org.hswebframework.web.exception; + +import javax.annotation.Nullable; +import java.util.Optional; + +/** + * 支持溯源的异常,通过{@link TraceSourceException#withSource(Object) }来标识异常的源头. + * 在捕获异常的地方通过获取异常源来处理一些逻辑,比如判断是由哪条数据发生的错误等操作. + * + * @author zhouhao + * @since 4.0.15 + */ +public class TraceSourceException extends RuntimeException { + + private Object source; + + public TraceSourceException() { + + } + + public TraceSourceException(String message) { + super(message); + } + + public TraceSourceException(Throwable e) { + super(e); + } + + public TraceSourceException(String message, Throwable e) { + super(message, e); + } + + public Optional sourceOptional() { + return Optional.ofNullable(source); + } + + @Nullable + public Object getSource() { + return source; + } + + public TraceSourceException withSource(Object source) { + this.source = source; + return self(); + } + + protected TraceSourceException self() { + return this; + } +} diff --git a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java index 3db2fad56..4c5a1a748 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java @@ -38,7 +38,7 @@ public static Validator getValidator() { public static T tryValidate(T bean, Class... group) { Set> violations = getValidator().validate(bean, group); if (!violations.isEmpty()) { - throw new ValidationException(violations); + throw new ValidationException(violations).withSource(bean); } return bean; @@ -47,7 +47,7 @@ public static T tryValidate(T bean, Class... group) { public static T tryValidate(T bean, String property, Class... group) { Set> violations = getValidator().validateProperty(bean, property, group); if (!violations.isEmpty()) { - throw new ValidationException(violations); + throw new ValidationException(violations).withSource(bean); } return bean; @@ -56,7 +56,7 @@ public static T tryValidate(T bean, String property, Class... group) { public static void tryValidate(Class bean, String property, Object value, Class... group) { Set> violations = getValidator().validateValue(bean, property, value, group); if (!violations.isEmpty()) { - throw new ValidationException(violations); + throw new ValidationException(violations).withSource(value); } } From 1284a3ec21979824139fe67bcb05baa3e28020a5 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 3 Aug 2022 14:02:34 +0800 Subject: [PATCH 090/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/I18nSupportException.java | 26 ++++ .../web/exception/TraceSourceException.java | 117 +++++++++++++++++- 2 files changed, 139 insertions(+), 4 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java index 21341a0e9..2478ab72b 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.Setter; import org.hswebframework.web.i18n.LocaleUtils; +import org.springframework.util.StringUtils; import reactor.core.publisher.Mono; import java.util.Locale; @@ -70,4 +71,29 @@ public final Mono getLocalizedMessageReactive() { .currentReactive() .map(this::getLocalizedMessage); } + + public static String tryGetLocalizedMessage(Throwable error, Locale locale) { + if (error instanceof I18nSupportException) { + return ((I18nSupportException) error).getLocalizedMessage(locale); + } + String msg = error.getMessage(); + + if (!StringUtils.hasText(msg)) { + msg = "error." + error.getClass().getSimpleName(); + } + if (msg.contains(".")) { + return LocaleUtils.resolveMessage(msg, locale, msg); + } + return msg; + } + + public static String tryGetLocalizedMessage(Throwable error) { + return tryGetLocalizedMessage(error, LocaleUtils.current()); + } + + public static Mono tryGetLocalizedMessageReactive(Throwable error) { + return LocaleUtils + .currentReactive() + .map(locale -> tryGetLocalizedMessage(error, locale)); + } } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java index 89174fa8e..28341cbbe 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java @@ -1,7 +1,14 @@ package org.hswebframework.web.exception; +import org.hswebframework.web.i18n.LocaleUtils; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Mono; +import reactor.util.context.Context; + import javax.annotation.Nullable; +import java.util.Locale; import java.util.Optional; +import java.util.function.Function; /** * 支持溯源的异常,通过{@link TraceSourceException#withSource(Object) }来标识异常的源头. @@ -12,6 +19,11 @@ */ public class TraceSourceException extends RuntimeException { + private static final String deepTraceKey = TraceSourceException.class.getName() + "_deep"; + private static final Context deepTraceContext = Context.of(deepTraceKey, true); + + private String operation; + private Object source; public TraceSourceException() { @@ -30,21 +42,118 @@ public TraceSourceException(String message, Throwable e) { super(message, e); } - public Optional sourceOptional() { - return Optional.ofNullable(source); - } - @Nullable public Object getSource() { return source; } + @Nullable + public String getOperation() { + return operation; + } + public TraceSourceException withSource(Object source) { this.source = source; return self(); } + public TraceSourceException withSource(String operation, Object source) { + this.operation = operation; + this.source = source; + return self(); + } + protected TraceSourceException self() { return this; } + + /** + * 深度溯源上下文,用来标识是否是深度溯源的异常.开启深度追踪后,会创建新的{@link TraceSourceException}对象. + * + * @return 上下文 + * @see reactor.core.publisher.Flux#subscriberContext(Context) + * @see Mono#subscriberContext(Context) + */ + public static Context deepTraceContext() { + return deepTraceContext; + } + + public static Function> transfer(Object source) { + return transfer(null, source); + } + + + /** + * 溯源异常转换器.通常配合{@link Mono#onErrorResume(Function)}使用. + *

+ * 转换逻辑: + *

+ * 1. 如果捕获的异常不是TraceSourceException,则直接创建新的TraceSourceException并返回. + *

+ * 2. 如果捕获的异常是TraceSourceException,并且上下文没有指定{@link TraceSourceException#deepTraceContext()}, + * 则修改捕获的TraceSourceException异常中的source.如果上下文中指定了{@link TraceSourceException#deepTraceContext()} + * 则创建新的TraceSourceException + * + *

{@code
+     *
+     *  doSomething()
+     *  .onErrorResume(TraceSourceException.transfer(data))
+     *
+     * }
+ * + * @param operation 操作名称 + * @param source 源 + * @param 泛型 + * @return 转换器 + * @see reactor.core.publisher.Flux#onErrorResume(Function) + * @see Mono#onErrorResume(Function) + */ + public static Function> transfer(String operation, Object source) { + if (source == null && operation == null) { + return Mono::error; + } + return err -> { + if (err instanceof TraceSourceException) { + return Mono + .deferWithContext(ctx -> { + if (ctx.hasKey(deepTraceKey)) { + return Mono.error(new TraceSourceException(err).withSource(operation,source)); + } else { + return Mono.error(((TraceSourceException) err).withSource(operation,source)); + } + }); + } + return Mono.error(new TraceSourceException(err).withSource(operation,source)); + }; + } + + public static Object tryGetSource(Throwable err) { + if (err instanceof TraceSourceException) { + return ((TraceSourceException) err).getSource(); + } + return null; + } + + public static String tryGetOperation(Throwable err) { + if (err instanceof TraceSourceException) { + return ((TraceSourceException) err).getOperation(); + } + return null; + } + + public static String tryGetOperationLocalized(Throwable err, Locale locale) { + String opt = tryGetOperation(err); + return StringUtils.hasText(opt) ? LocaleUtils.resolveMessage(opt, locale, opt) : opt; + } + + public static Mono tryGetOperationLocalizedReactive(Throwable err) { + return LocaleUtils + .currentReactive() + .handle((locale, sink) -> { + String opt = tryGetOperationLocalized(err, locale); + if (opt != null) { + sink.next(opt); + } + }); + } } From 1a707a29eb0520f5f9db3ab3d1659f71e9515c30 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 3 Aug 2022 15:18:25 +0800 Subject: [PATCH 091/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../basic/aop/AopAuthorizingController.java | 6 +++--- .../define/DefaultBasicAuthorizeDefinition.java | 13 ++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java index d1d59ba53..23171ebd2 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingController.java @@ -64,7 +64,8 @@ protected Publisher handleReactive0(AuthorizeDefinition definition, AuthorizingContext context, Supplier> invoker) { - return Authentication.currentReactive() + return Authentication + .currentReactive() .switchIfEmpty(Mono.error(UnAuthorizedException::new)) .flatMapMany(auth -> { context.setAuthentication(auth); @@ -133,8 +134,7 @@ public Object invoke(MethodInvocation methodInvocation) throws Throwable { context.setAuthentication(authentication); isControl = true; - Phased dataAccessPhased = null; - dataAccessPhased = definition.getResources().getPhased(); + Phased dataAccessPhased = definition.getResources().getPhased(); if (definition.getPhased() == Phased.before) { //RDAC before authorizingHandler.handRBAC(context); diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java index d5c556493..dd334acf8 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java @@ -38,7 +38,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition { private String message = "error.access_denied"; - private Phased phased; + private Phased phased = Phased.before; @Override public boolean isEmpty() { @@ -65,6 +65,7 @@ public void putAnnotation(Authorize ann) { getResources().getResources().clear(); getDimensions().getDimensions().clear(); } + setPhased(ann.phased()); getResources().setPhased(ann.phased()); for (Resource resource : ann.resources()) { putAnnotation(resource); @@ -97,6 +98,8 @@ public void putAnnotation(Resource ann) { putAnnotation(resource, action); } resource.setGroup(new ArrayList<>(Arrays.asList(ann.group()))); + setPhased(ann.phased()); + getResources().setPhased(ann.phased()); resources.addResource(resource, ann.merge()); } @@ -132,8 +135,8 @@ public void putAnnotation(ResourceActionDefinition definition, DataAccess ann) { return; } definition.getDataAccess() - .getDataAccessTypes() - .add(typeDefinition); + .getDataAccessTypes() + .add(typeDefinition); } public void putAnnotation(ResourceActionDefinition definition, DataAccessType dataAccessType) { @@ -147,8 +150,8 @@ public void putAnnotation(ResourceActionDefinition definition, DataAccessType da typeDefinition.setConfiguration(dataAccessType.configuration()); typeDefinition.setDescription(String.join("\n", dataAccessType.description())); definition.getDataAccess() - .getDataAccessTypes() - .add(typeDefinition); + .getDataAccessTypes() + .add(typeDefinition); } } From 69ab5f632d56cb71bbbba4fc412453068a7bdc02 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 3 Aug 2022 20:01:26 +0800 Subject: [PATCH 092/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=BB=A5=E5=8F=8A=E6=9D=83=E9=99=90=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../events/AuthorizationInitializeEvent.java | 5 +- .../simple/SimpleAuthentication.java | 18 ++-- ...activeAuthenticationInitializeService.java | 88 +++++++++++-------- 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizationInitializeEvent.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizationInitializeEvent.java index 6144f6c5f..93f9bb261 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizationInitializeEvent.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/events/AuthorizationInitializeEvent.java @@ -2,11 +2,14 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.Setter; import org.hswebframework.web.authorization.Authentication; +import org.hswebframework.web.event.DefaultAsyncEvent; @Getter +@Setter @AllArgsConstructor -public class AuthorizationInitializeEvent { +public class AuthorizationInitializeEvent extends DefaultAsyncEvent { private Authentication authentication; } diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java index 8d8ef7e7d..720e20c56 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java @@ -58,10 +58,16 @@ public Map getAttributes() { } public SimpleAuthentication merge(Authentication authentication) { - Map mePermissionGroup = permissions.stream() + Map mePermissionGroup = permissions + .stream() .collect(Collectors.toMap(Permission::getId, Function.identity())); - user = authentication.getUser(); + + if (authentication.getUser() != null) { + user = authentication.getUser(); + } + attributes.putAll(authentication.getAttributes()); + for (Permission permission : authentication.getPermissions()) { Permission me = mePermissionGroup.get(permission.getId()); if (me == null) { @@ -88,10 +94,10 @@ public Authentication copy(BiPredicate permissionFilter, authentication.setUser(user); authentication.setDimensions(dimensions.stream().filter(dimension).collect(Collectors.toList())); authentication.setPermissions(permissions - .stream() - .map(permission -> permission.copy(action -> permissionFilter.test(permission, action), conf -> true)) - .filter(per -> !per.getActions().isEmpty()) - .collect(Collectors.toList()) + .stream() + .map(permission -> permission.copy(action -> permissionFilter.test(permission, action), conf -> true)) + .filter(per -> !per.getActions().isEmpty()) + .collect(Collectors.toList()) ); return authentication; } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java index b3fc14096..44d431e14 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java @@ -10,6 +10,7 @@ import org.hswebframework.web.authorization.access.DataAccessConfig; import org.hswebframework.web.authorization.access.DataAccessType; import org.hswebframework.web.authorization.builder.DataAccessConfigBuilderFactory; +import org.hswebframework.web.authorization.events.AuthorizationInitializeEvent; import org.hswebframework.web.authorization.simple.SimpleAuthentication; import org.hswebframework.web.authorization.simple.SimplePermission; import org.hswebframework.web.authorization.simple.SimpleUser; @@ -21,6 +22,7 @@ import org.hswebframework.web.system.authorization.api.entity.UserEntity; import org.hswebframework.web.system.authorization.api.service.reactive.ReactiveUserService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -48,6 +50,9 @@ public class DefaultReactiveAuthenticationInitializeService @Autowired(required = false) private List dimensionProviders = new ArrayList<>(); + @Autowired + private ApplicationEventPublisher eventPublisher; + @Override public Mono initUserAuthorization(String userId) { return doInit(userService.findById(userId)); @@ -58,17 +63,23 @@ public Mono doInit(Mono userEntityMono) { return userEntityMono.flatMap(user -> { SimpleAuthentication authentication = new SimpleAuthentication(); authentication.setUser(SimpleUser - .builder() - .id(user.getId()) - .name(user.getName()) - .username(user.getUsername()) - .userType(user.getType()) - .build()); + .builder() + .id(user.getId()) + .name(user.getName()) + .username(user.getUsername()) + .userType(user.getType()) + .build()); return initPermission(authentication) .switchIfEmpty(Mono.just(authentication)) .onErrorResume(err -> { log.warn(err.getMessage(), err); return Mono.just(authentication); + }) + .flatMap(auth -> { + AuthorizationInitializeEvent event = new AuthorizationInitializeEvent(auth); + return event + .publish(eventPublisher) + .then(Mono.fromSupplier(event::getAuthentication)); }); }); @@ -76,31 +87,31 @@ public Mono doInit(Mono userEntityMono) { protected Flux getSettings(List dimensions) { return Flux.fromIterable(dimensions) - .filter(dimension -> dimension.getType() != null) - .groupBy(d -> d.getType().getId(), (Function) Dimension::getId) - .flatMap(group -> - group.collectList() - .flatMapMany(list -> settingRepository - .createQuery() - .where(AuthorizationSettingEntity::getState, 1) - .and(AuthorizationSettingEntity::getDimensionType, group.key()) - .in(AuthorizationSettingEntity::getDimensionTarget, list) - .fetch())); + .filter(dimension -> dimension.getType() != null) + .groupBy(d -> d.getType().getId(), (Function) Dimension::getId) + .flatMap(group -> + group.collectList() + .flatMapMany(list -> settingRepository + .createQuery() + .where(AuthorizationSettingEntity::getState, 1) + .and(AuthorizationSettingEntity::getDimensionType, group.key()) + .in(AuthorizationSettingEntity::getDimensionTarget, list) + .fetch())); } protected Mono initPermission(SimpleAuthentication authentication) { return Flux.fromIterable(dimensionProviders) - .flatMap(provider -> provider.getDimensionByUserId(authentication.getUser().getId())) - .cast(Dimension.class) - .collectList() - .doOnNext(authentication::setDimensions) - .flatMap(allDimension -> - Mono.zip( - getAllPermission() - , getSettings(allDimension) - .collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)) - , (_p, _s) -> handlePermission(authentication, allDimension, _p, _s) - )); + .flatMap(provider -> provider.getDimensionByUserId(authentication.getUser().getId())) + .cast(Dimension.class) + .collectList() + .doOnNext(authentication::setDimensions) + .flatMap(allDimension -> + Mono.zip( + getAllPermission() + , getSettings(allDimension) + .collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)) + , (_p, _s) -> handlePermission(authentication, allDimension, _p, _s) + )); } @@ -134,16 +145,19 @@ protected SimpleAuthentication handlePermission(SimpleAuthentication authenticat if (permissionSetting.getDataAccesses() != null) { permissionSetting.getDataAccesses() - .stream() - .map(conf -> { - DataAccessConfig config = builderFactory.create().fromMap(conf.toMap()).build(); - if (config == null) { - log.warn("unsupported data access:{}", conf.toMap()); - } - return config; - }) - .filter(Objects::nonNull) - .forEach(configs::add); + .stream() + .map(conf -> { + DataAccessConfig config = builderFactory + .create() + .fromMap(conf.toMap()) + .build(); + if (config == null) { + log.warn("unsupported data access:{}", conf.toMap()); + } + return config; + }) + .filter(Objects::nonNull) + .forEach(configs::add); } if (CollectionUtils.isNotEmpty(permissionSetting.getActions())) { permission.getActions().addAll(permissionSetting.getActions()); From c5b9adabbea1a8db161607f02ea18520d0383a03 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 10 Aug 2022 17:27:53 +0800 Subject: [PATCH 093/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9B=BD=E9=99=85?= =?UTF-8?q?=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/events/ValidateEventListener.java | 7 +- .../web/exception/TraceSourceException.java | 2 +- .../hswebframework/web/i18n/LocaleUtils.java | 116 ++++++++++++++++-- .../web/i18n/WebFluxLocaleFilter.java | 1 + .../web/i18n/LocaleUtilsTest.java | 32 ++++- .../jackson/CustomJackson2JsonDecoder.java | 45 +++---- .../jackson/CustomJackson2jsonEncoder.java | 115 ++++++++--------- 7 files changed, 208 insertions(+), 110 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java index be7e1fb00..342dc9e92 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java @@ -35,9 +35,10 @@ public void onEvent(EventType type, EventContext context) { resultHolder .ifPresent(holder -> holder .invoke(LocaleUtils - .currentReactive() - .doOnNext(locale -> LocaleUtils.doWith(locale, (l) -> tryValidate(type, context))) - .then() + .doInReactive(() -> { + tryValidate(type, context); + return null; + }) )); } else { tryValidate(type, context); diff --git a/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java index 28341cbbe..30ab58049 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/exception/TraceSourceException.java @@ -35,7 +35,7 @@ public TraceSourceException(String message) { } public TraceSourceException(Throwable e) { - super(e); + super(e.getMessage(),e); } public TraceSourceException(String message, Throwable e) { diff --git a/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java index d3c66ade3..156d4a989 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java @@ -1,15 +1,17 @@ package org.hswebframework.web.i18n; +import lombok.AllArgsConstructor; import org.hswebframework.web.exception.I18nSupportException; import org.reactivestreams.Publisher; +import org.reactivestreams.Subscription; import org.springframework.context.MessageSource; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.core.publisher.Signal; -import reactor.core.publisher.SignalType; +import reactor.core.CoreSubscriber; +import reactor.core.publisher.*; import reactor.util.context.Context; +import javax.annotation.Nonnull; import java.util.Locale; +import java.util.concurrent.Callable; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -23,7 +25,6 @@ *
  • {@link LocaleUtils#current()}
  • *
  • {@link LocaleUtils#currentReactive()}
  • *
  • {@link LocaleUtils#resolveMessageReactive(String, Object...)}
  • - *
  • {@link LocaleUtils#doOnNext(BiConsumer)}
  • * * * @author zhouhao @@ -63,11 +64,12 @@ public static Locale current() { * @return 返回值 */ public static R doWith(T data, Locale locale, BiFunction mapper) { + Locale old = CONTEXT_THREAD_LOCAL.get(); try { CONTEXT_THREAD_LOCAL.set(locale); return mapper.apply(data, locale); } finally { - CONTEXT_THREAD_LOCAL.remove(); + CONTEXT_THREAD_LOCAL.set(old); } } @@ -78,11 +80,12 @@ public static R doWith(T data, Locale locale, BiFunction ma * @param consumer 任务 */ public static void doWith(Locale locale, Consumer consumer) { + Locale old = CONTEXT_THREAD_LOCAL.get(); try { CONTEXT_THREAD_LOCAL.set(locale); consumer.accept(locale); } finally { - CONTEXT_THREAD_LOCAL.remove(); + CONTEXT_THREAD_LOCAL.set(old); } } @@ -112,6 +115,23 @@ public static Mono currentReactive() { .subscriberContext() .map(ctx -> ctx.getOrDefault(Locale.class, DEFAULT_LOCALE)); } + public static Mono doInReactive(Callable call) { + return currentReactive() + .handle((locale, sink) -> { + Locale old = CONTEXT_THREAD_LOCAL.get(); + try { + CONTEXT_THREAD_LOCAL.set(locale); + T data = call.call(); + if (data != null) { + sink.next(data); + } + } catch (Throwable e) { + sink.error(e); + } finally { + CONTEXT_THREAD_LOCAL.set(old); + } + }); + } /** * 响应式方式解析出异常的区域消息,并进行结果转换. @@ -450,4 +470,86 @@ public static > Function doOnError(BiConsumer operation.accept(s.getThrowable(), l)); } + public static Flux transform(Flux flux) { + return new LocaleFlux<>(flux); + } + + public static Mono transform(Mono mono) { + return new LocaleMono<>(mono); + } + + @AllArgsConstructor + static class LocaleMono extends Mono { + private final Mono source; + + @Override + public void subscribe(@Nonnull CoreSubscriber actual) { + doWith(actual, + actual.currentContext().getOrDefault(Locale.class, DEFAULT_LOCALE), + (a, l) -> { + source.subscribe( + new LocaleSwitchSubscriber<>(a) + ); + return null; + } + ); + } + } + + @AllArgsConstructor + static class LocaleFlux extends Flux { + private final Flux source; + + @Override + public void subscribe(@Nonnull CoreSubscriber actual) { + source.subscribe( + new LocaleSwitchSubscriber<>(actual) + ); + } + } + + @AllArgsConstructor + static class LocaleSwitchSubscriber extends BaseSubscriber { + private final CoreSubscriber actual; + + @Override + @Nonnull + public Context currentContext() { + return actual + .currentContext(); + } + + @Override + protected void hookOnSubscribe(@Nonnull Subscription subscription) { + actual.onSubscribe(this); + } + + private Locale current() { + return currentContext() + .getOrDefault(Locale.class, DEFAULT_LOCALE); + } + + @Override + protected void hookOnComplete() { + doWith(current(), (l) -> actual.onComplete()); + } + + @Override + protected void hookOnError(@Nonnull Throwable error) { + + doWith(error, current(), (v, l) -> { + actual.onError(v); + return null; + }); + } + + @Override + protected void hookOnNext(@Nonnull T value) { + + doWith(value, current(), (v, l) -> { + actual.onNext(v); + return null; + }); + } + } } diff --git a/hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java b/hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java index 748d7faee..61a34e1d6 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/i18n/WebFluxLocaleFilter.java @@ -15,6 +15,7 @@ public class WebFluxLocaleFilter implements WebFilter { public Mono filter(@NonNull ServerWebExchange exchange, WebFilterChain chain) { return chain .filter(exchange) + .as(LocaleUtils::transform) .subscriberContext(LocaleUtils.useLocale(getLocaleContext(exchange))); } diff --git a/hsweb-core/src/test/java/org/hswebframework/web/i18n/LocaleUtilsTest.java b/hsweb-core/src/test/java/org/hswebframework/web/i18n/LocaleUtilsTest.java index e68469bf4..0ce7042a2 100644 --- a/hsweb-core/src/test/java/org/hswebframework/web/i18n/LocaleUtilsTest.java +++ b/hsweb-core/src/test/java/org/hswebframework/web/i18n/LocaleUtilsTest.java @@ -2,6 +2,8 @@ import org.junit.Test; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import java.util.Locale; @@ -11,15 +13,35 @@ public class LocaleUtilsTest { @Test - public void testOnNext() { + public void testFlux() { Flux.just(1) - .as(LocaleUtils.doOnNext((i, l) -> { + .as(LocaleUtils::transform) + .doOnNext(i -> { assertEquals(i.intValue(), 1); - assertEquals(l, Locale.CHINA); - })) - .subscriberContext(LocaleUtils.useLocale(Locale.CHINA)) + assertEquals(LocaleUtils.current(), Locale.ENGLISH); + }) + .subscriberContext(LocaleUtils.useLocale(Locale.ENGLISH)) .blockLast(); } + @Test + public void testMono() { + Mono.just(1) + .doOnNext(i -> { + assertEquals(i.intValue(), 1); + assertEquals(LocaleUtils.current(), Locale.ENGLISH); + }) + .as(LocaleUtils::transform) + .subscriberContext(LocaleUtils.useLocale(Locale.ENGLISH)) + .block(); + + LocaleUtils + .doInReactive(()->{ + assertEquals(LocaleUtils.current(), Locale.ENGLISH); + return null; + }) + .subscriberContext(LocaleUtils.useLocale(Locale.ENGLISH)) + .block(); + } } \ No newline at end of file diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java index cbf0100b8..454933464 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2JsonDecoder.java @@ -28,12 +28,10 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import javax.annotation.Nonnull; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -70,23 +68,19 @@ public Flux decode(@NonNull Publisher input, @NonNull Resolv ObjectReader reader = getObjectReader(elementType, hints); - return LocaleUtils - .currentReactive() - .flatMapMany(locale -> tokens - .handle((tokenBuffer, sink) -> { - LocaleUtils.doWith(locale, l -> { - try { - Object value = reader.readValue(tokenBuffer.asParser(getObjectMapper())); - logValue(value, hints); - if (value != null) { - sink.next(value); - } - } catch (IOException ex) { - sink.error(processException(ex)); - } - }); - - })); + return tokens + .as(LocaleUtils::transform) + .handle((tokenBuffer, sink) -> { + try { + Object value = reader.readValue(tokenBuffer.asParser(getObjectMapper())); + logValue(value, hints); + if (value != null) { + sink.next(value); + } + } catch (IOException ex) { + sink.error(processException(ex)); + } + }); } @Override @@ -94,15 +88,10 @@ public Flux decode(@NonNull Publisher input, @NonNull Resolv public Mono decodeToMono(@NonNull Publisher input, @NonNull ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map hints) { - return LocaleUtils - .currentReactive() - .flatMap(locale -> DataBufferUtils - .join(input) - .map(dataBuffer -> LocaleUtils - .doWith(dataBuffer, - locale, - (buf, l) -> decode(buf, elementType, mimeType, hints))) - ); + return DataBufferUtils + .join(input) + .as(LocaleUtils::transform) + .map(dataBuffer -> decode(dataBuffer, elementType, mimeType, hints)); } @Override diff --git a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java index a999fb9f6..27c42a42d 100644 --- a/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java +++ b/hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/CustomJackson2jsonEncoder.java @@ -116,72 +116,55 @@ public Flux encode(Publisher inputStream, DataBufferFactory buffe Assert.notNull(bufferFactory, "'bufferFactory' must not be null"); Assert.notNull(elementType, "'elementType' must not be null"); - return LocaleUtils - .currentReactive() - .flatMapMany(locale -> { - if (inputStream instanceof Mono) { - return Mono.from(inputStream) - .map(value -> LocaleUtils - .doWith(value, locale, - ((val, loc) -> - encodeValue(val, bufferFactory, elementType, mimeType, hints) - ) - )) - .flux(); - } else { - byte[] separator = streamSeparator(mimeType); - if (separator != null) { // streaming - try { - ObjectWriter writer = createObjectWriter(elementType, mimeType, hints); - ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer - .getFactory() - ._getBufferRecycler()); - JsonEncoding encoding = getJsonEncoding(mimeType); - JsonGenerator generator = getObjectMapper() - .getFactory() - .createGenerator(byteBuilder, encoding); - SequenceWriter sequenceWriter = writer.writeValues(generator); - - return Flux - .from(inputStream) - .map(value -> LocaleUtils - .doWith(value, - locale, - ((val, loc) -> this - .encodeStreamingValue(val, - bufferFactory, - hints, - sequenceWriter, - byteBuilder, - separator) - ) - )) - .doAfterTerminate(() -> { - try { - byteBuilder.release(); - generator.close(); - } catch (IOException ex) { - logger.error("Could not close Encoder resources", ex); - } - }); - } catch (IOException ex) { - return Flux.error(ex); - } - } else { // non-streaming - ResolvableType listType = ResolvableType.forClassWithGenerics(List.class, elementType); - return Flux.from(inputStream) - .collectList() - .map(value -> LocaleUtils - .doWith(value, locale, - ((val, loc) -> - encodeValue(val, bufferFactory, listType, mimeType, hints) - ) - )) - .flux(); - } - - } - }); + if (inputStream instanceof Mono) { + return Mono.from(inputStream) + .as(LocaleUtils::transform) + .map(value -> encodeValue(value, bufferFactory, elementType, mimeType, hints)) + .flux(); + } else { + byte[] separator = streamSeparator(mimeType); + if (separator != null) { // streaming + try { + ObjectWriter writer = createObjectWriter(elementType, mimeType, hints); + ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer + .getFactory() + ._getBufferRecycler()); + JsonEncoding encoding = getJsonEncoding(mimeType); + JsonGenerator generator = getObjectMapper() + .getFactory() + .createGenerator(byteBuilder, encoding); + SequenceWriter sequenceWriter = writer.writeValues(generator); + + return Flux + .from(inputStream) + .as(LocaleUtils::transform) + .map(value -> this.encodeStreamingValue(value, + bufferFactory, + hints, + sequenceWriter, + byteBuilder, + separator)) + .doAfterTerminate(() -> { + try { + byteBuilder.release(); + generator.close(); + } catch (IOException ex) { + logger.error("Could not close Encoder resources", ex); + } + }); + } catch (IOException ex) { + return Flux.error(ex); + } + } else { // non-streaming + ResolvableType listType = ResolvableType.forClassWithGenerics(List.class, elementType); + return Flux.from(inputStream) + .collectList() + .as(LocaleUtils::transform) + .map(value -> encodeValue(value, bufferFactory, listType, mimeType, hints)) + .flux(); + } + + } } @Override From fa3b4dded9d33072e7053e4693d334a98196ce28 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 10 Aug 2022 17:40:46 +0800 Subject: [PATCH 094/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/hswebframework/web/i18n/LocaleUtils.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java b/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java index 156d4a989..44c524ae2 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java @@ -502,8 +502,14 @@ static class LocaleFlux extends Flux { @Override public void subscribe(@Nonnull CoreSubscriber actual) { - source.subscribe( - new LocaleSwitchSubscriber<>(actual) + doWith(actual, + actual.currentContext().getOrDefault(Locale.class, DEFAULT_LOCALE), + (a, l) -> { + source.subscribe( + new LocaleSwitchSubscriber<>(a) + ); + return null; + } ); } } From 03c47f12283d230caf21122730ed1add2cac85f0 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 17 Aug 2022 20:38:29 +0800 Subject: [PATCH 095/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../simple/SimpleAuthentication.java | 8 +- .../AuthorizingHandlerAutoConfiguration.java | 6 ++ .../basic/web/BearerTokenParser.java | 22 ++++++ .../basic/web/DefaultUserTokenGenPar.java | 12 +-- .../server/OAuth2ServerAutoConfiguration.java | 23 +++--- .../code/DefaultAuthorizationCodeGranter.java | 5 +- .../server/impl/RedisAccessTokenManager.java | 74 ++++++++++++++----- .../oauth2/server/utils/OAuth2ScopeUtils.java | 11 ++- .../authorization/api/entity/UserEntity.java | 12 ++- .../service/reactive/ReactiveUserService.java | 2 + ...AuthorizationServiceAutoConfiguration.java | 8 +- ...activeAuthenticationInitializeService.java | 4 +- .../service/DefaultReactiveUserService.java | 12 ++- 13 files changed, 147 insertions(+), 52 deletions(-) create mode 100644 hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/BearerTokenParser.java diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java index 720e20c56..e318c6c19 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java @@ -78,7 +78,6 @@ public SimpleAuthentication merge(Authentication authentication) { me.getDataAccesses().addAll(permission.getDataAccesses()); } - for (Dimension dimension : authentication.getDimensions()) { if (!getDimension(dimension.getType(), dimension.getId()).isPresent()) { dimensions.add(dimension); @@ -91,7 +90,6 @@ public SimpleAuthentication merge(Authentication authentication) { public Authentication copy(BiPredicate permissionFilter, Predicate dimension) { SimpleAuthentication authentication = new SimpleAuthentication(); - authentication.setUser(user); authentication.setDimensions(dimensions.stream().filter(dimension).collect(Collectors.toList())); authentication.setPermissions(permissions .stream() @@ -99,6 +97,12 @@ public Authentication copy(BiPredicate permissionFilter, .filter(per -> !per.getActions().isEmpty()) .collect(Collectors.toList()) ); + authentication.setUser(user); return authentication; } + + public void setUser(User user) { + this.user = user; + dimensions.add(user); + } } diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java index 50e4510a9..3ba9465d1 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/configuration/AuthorizingHandlerAutoConfiguration.java @@ -145,6 +145,12 @@ public ReactiveUserTokenController userTokenController() { return new ReactiveUserTokenController(); } + @Bean + @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) + public BearerTokenParser bearerTokenParser() { + return new BearerTokenParser(); + } + @Configuration public static class DataAccessHandlerProcessor implements BeanPostProcessor { diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/BearerTokenParser.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/BearerTokenParser.java new file mode 100644 index 000000000..d7c49d176 --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/BearerTokenParser.java @@ -0,0 +1,22 @@ +package org.hswebframework.web.authorization.basic.web; + +import org.hswebframework.web.authorization.token.ParsedToken; +import org.springframework.http.HttpHeaders; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class BearerTokenParser implements ReactiveUserTokenParser { + @Override + public Mono parseToken(ServerWebExchange exchange) { + + String token = exchange + .getRequest() + .getHeaders() + .getFirst(HttpHeaders.AUTHORIZATION); + + if (token != null && token.startsWith("Bearer ")) { + return Mono.just(ParsedToken.of("bearer", token.substring(7))); + } + return Mono.empty(); + } +} diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java index 0e4c1810f..b1948ef42 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/DefaultUserTokenGenPar.java @@ -62,16 +62,6 @@ public Mono parseToken(ServerWebExchange exchange) { if (token == null) { return Mono.empty(); } - return Mono.just(new ParsedToken() { - @Override - public String getToken() { - return token; - } - - @Override - public String getType() { - return getTokenType(); - } - }); + return Mono.just(ParsedToken.of(getTokenType(),token)); } } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java index 6003a593f..842e21125 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java @@ -3,6 +3,8 @@ import org.hswebframework.web.authorization.ReactiveAuthenticationHolder; import org.hswebframework.web.authorization.ReactiveAuthenticationManager; import org.hswebframework.web.authorization.basic.web.ReactiveUserTokenParser; +import org.hswebframework.web.authorization.token.UserToken; +import org.hswebframework.web.authorization.token.UserTokenManager; import org.hswebframework.web.oauth2.server.auth.ReactiveOAuth2AccessTokenParser; import org.hswebframework.web.oauth2.server.code.AuthorizationCodeGranter; import org.hswebframework.web.oauth2.server.code.DefaultAuthorizationCodeGranter; @@ -22,6 +24,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; +import org.springframework.data.redis.core.ReactiveRedisOperations; @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(OAuth2Properties.class) @@ -32,13 +35,13 @@ public class OAuth2ServerAutoConfiguration { @ConditionalOnClass(ReactiveUserTokenParser.class) static class ReactiveOAuth2AccessTokenParserConfiguration { - @Bean - @ConditionalOnBean(AccessTokenManager.class) - public ReactiveOAuth2AccessTokenParser reactiveOAuth2AccessTokenParser(AccessTokenManager accessTokenManager) { - ReactiveOAuth2AccessTokenParser parser = new ReactiveOAuth2AccessTokenParser(accessTokenManager); - ReactiveAuthenticationHolder.addSupplier(parser); - return parser; - } +// @Bean +// @ConditionalOnBean(AccessTokenManager.class) +// public ReactiveOAuth2AccessTokenParser reactiveOAuth2AccessTokenParser(AccessTokenManager accessTokenManager) { +// ReactiveOAuth2AccessTokenParser parser = new ReactiveOAuth2AccessTokenParser(accessTokenManager); +// ReactiveAuthenticationHolder.addSupplier(parser); +// return parser; +// } } @Configuration(proxyBeanMethods = false) @@ -48,9 +51,11 @@ static class ReactiveOAuth2ServerAutoConfiguration { @Bean @ConditionalOnMissingBean - public AccessTokenManager accessTokenManager(ReactiveRedisConnectionFactory redisConnectionFactory, + public AccessTokenManager accessTokenManager(ReactiveRedisOperations redis, + UserTokenManager tokenManager, OAuth2Properties properties) { - RedisAccessTokenManager manager = new RedisAccessTokenManager(redisConnectionFactory); + @SuppressWarnings("all") + RedisAccessTokenManager manager = new RedisAccessTokenManager((ReactiveRedisOperations) redis, tokenManager); manager.setTokenExpireIn((int) properties.getTokenExpireIn().getSeconds()); manager.setRefreshExpireIn((int) properties.getRefreshTokenIn().getSeconds()); return manager; diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranter.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranter.java index c3b53cabd..472cedfa0 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranter.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranter.java @@ -48,9 +48,12 @@ public Mono requestCode(AuthorizationCodeRequest requ request.getParameter(OAuth2Constants.scope).map(String::valueOf).ifPresent(codeCache::setScope); codeCache.setCode(code); codeCache.setClientId(client.getClientId()); + ScopePredicate permissionPredicate = OAuth2ScopeUtils.createScopePredicate(codeCache.getScope()); - codeCache.setAuthentication(authentication.copy((permission, action) -> permissionPredicate.test(permission.getId(), action), dimension -> true)); + codeCache.setAuthentication(authentication.copy( + (permission, action) -> permissionPredicate.test(permission.getId(), action), + dimension -> permissionPredicate.test(dimension.getType().getId(), dimension.getId()))); return redis diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java index e6a0a0ac6..fe1e9b39b 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java @@ -4,6 +4,9 @@ import lombok.Setter; import org.apache.commons.codec.digest.DigestUtils; import org.hswebframework.web.authorization.Authentication; +import org.hswebframework.web.authorization.token.AuthenticationUserToken; +import org.hswebframework.web.authorization.token.UserTokenManager; +import org.hswebframework.web.authorization.token.redis.RedisUserTokenManager; import org.hswebframework.web.oauth2.ErrorType; import org.hswebframework.web.oauth2.OAuth2Exception; import org.hswebframework.web.oauth2.server.AccessToken; @@ -13,6 +16,7 @@ import org.springframework.data.redis.core.ReactiveRedisTemplate; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.time.Duration; @@ -22,6 +26,8 @@ public class RedisAccessTokenManager implements AccessTokenManager { private final ReactiveRedisOperations tokenRedis; + private final UserTokenManager userTokenManager; + @Getter @Setter private int tokenExpireIn = 7200;//2小时 @@ -30,29 +36,32 @@ public class RedisAccessTokenManager implements AccessTokenManager { @Setter private int refreshExpireIn = 2592000; //30天 - public RedisAccessTokenManager(ReactiveRedisOperations tokenRedis) { + public RedisAccessTokenManager(ReactiveRedisOperations tokenRedis, + UserTokenManager userTokenManager) { this.tokenRedis = tokenRedis; + this.userTokenManager = userTokenManager; } @SuppressWarnings("all") public RedisAccessTokenManager(ReactiveRedisConnectionFactory connectionFactory) { - this(new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext + ReactiveRedisTemplate redis = new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext .newSerializationContext() .key((RedisSerializer) RedisSerializer.string()) .value(RedisSerializer.java()) .hashKey(RedisSerializer.string()) .hashValue(RedisSerializer.java()) - .build() - )); + .build()); + this.tokenRedis = redis; + this.userTokenManager = new RedisUserTokenManager(redis); } + @Override public Mono getAuthenticationByToken(String accessToken) { - - return tokenRedis - .opsForValue() - .get(createTokenRedisKey(accessToken)) - .map(RedisAccessToken::getAuthentication); + return userTokenManager + .getByToken(accessToken) + .filter(token -> token instanceof AuthenticationUserToken) + .map(t -> ((AuthenticationUserToken) t).getAuthentication()); } private String createTokenRedisKey(String token) { @@ -75,12 +84,36 @@ private Mono doCreateAccessToken(String clientId, Authenticati return storeToken(accessToken).thenReturn(accessToken); } + private Mono storeAuthToken(RedisAccessToken token) { + if (token.isSingleton()) { + return userTokenManager + .signIn(token.getAccessToken(), + "oauth2", + token.getAuthentication().getUser().getId(), + tokenExpireIn * 1000L) + .then(); + } else { + return userTokenManager + .signIn(token.getAccessToken(), + "oauth2", + token.getAuthentication().getUser().getId(), + tokenExpireIn * 1000L, + token.getAuthentication()) + .then(); + } + } + private Mono storeToken(RedisAccessToken token) { - return Mono - .zip( - tokenRedis.opsForValue().set(createTokenRedisKey(token.getAccessToken()), token, Duration.ofSeconds(tokenExpireIn)), - tokenRedis.opsForValue().set(createRefreshTokenRedisKey(token.getRefreshToken()), token, Duration.ofSeconds(refreshExpireIn)) - ).then(); + + return Flux + .merge(storeAuthToken(token), + tokenRedis + .opsForValue() + .set(createTokenRedisKey(token.getAccessToken()), token, Duration.ofSeconds(tokenExpireIn)), + tokenRedis + .opsForValue() + .set(createRefreshTokenRedisKey(token.getRefreshToken()), token, Duration.ofSeconds(refreshExpireIn))) + .then(); } private Mono doCreateSingletonAccessToken(String clientId, Authentication authentication) { @@ -129,10 +162,15 @@ public Mono refreshAccessToken(String clientId, String refreshToken .as(result -> { // 单例token if (token.isSingleton()) { - return tokenRedis - .opsForValue() - .set(createSingletonTokenRedisKey(clientId), token, Duration.ofSeconds(tokenExpireIn)) - .then(result); + return userTokenManager + .signOutByToken(token.getAccessToken()) + .then( + tokenRedis + .opsForValue() + .set(createSingletonTokenRedisKey(clientId), token, Duration.ofSeconds(tokenExpireIn)) + .then(result) + ) + ; } return result; }) diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/utils/OAuth2ScopeUtils.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/utils/OAuth2ScopeUtils.java index 4ac30fff0..40806f974 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/utils/OAuth2ScopeUtils.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/utils/OAuth2ScopeUtils.java @@ -6,6 +6,10 @@ import java.util.*; /** + *
    {@code
    + *   role:* user:* device-manager:*
    + * }
    + * * @author zhouhao * @since 4.0.8 */ @@ -23,10 +27,13 @@ public static ScopePredicate createScopePredicate(String scopeStr) { Set acts = actions.computeIfAbsent(per, k -> new HashSet<>()); acts.addAll(Arrays.asList(permissions).subList(1, permissions.length)); } - + //全部授权 + if (actions.containsKey("*")) { + return ((permission, action) -> true); + } return ((permission, action) -> Optional .ofNullable(actions.get(permission)) - .map(acts -> action.length == 0 || acts.containsAll(Arrays.asList(action))) + .map(acts -> action.length == 0 || acts.contains("*") || acts.containsAll(Arrays.asList(action))) .orElse(false)); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java index d903669aa..2e831be27 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/UserEntity.java @@ -1,5 +1,7 @@ package org.hswebframework.web.system.authorization.api.entity; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.media.Schema; @@ -9,15 +11,18 @@ import org.hswebframework.ezorm.rdb.mapping.annotation.Comment; import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue; import org.hswebframework.web.api.crud.entity.GenericEntity; +import org.hswebframework.web.api.crud.entity.QueryParamEntity; import org.hswebframework.web.api.crud.entity.RecordCreationEntity; import org.hswebframework.web.bean.ToString; import org.hswebframework.web.validator.CreateGroup; +import org.springframework.util.StringUtils; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.Index; import javax.persistence.Table; import javax.validation.constraints.NotBlank; +import java.util.Objects; /** * 系统用户实体 @@ -85,7 +90,10 @@ public String getId() { return super.getId(); } - public void generateId(){ - setId(DigestUtils.md5Hex(username)); + public void generateId() { + if (StringUtils.hasText(getId())) { + return; + } + setId(DigestUtils.md5Hex(username)); } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java index d7d3ace6d..209196cde 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/service/reactive/ReactiveUserService.java @@ -29,6 +29,8 @@ public interface ReactiveUserService { */ Mono saveUser(Mono userEntity); + Mono addUser(UserEntity userEntity); + /** * 根据用户名查询用户实体,如果用户不存在则返回{@link Mono#empty()} * diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java index 2d80c4fba..47f501d6f 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/configuration/AuthorizationServiceAutoConfiguration.java @@ -55,10 +55,10 @@ public DefaultDimensionService defaultDimensionService() { return new DefaultDimensionService(); } - @Bean - public UserDimensionProvider userPermissionDimensionProvider() { - return new UserDimensionProvider(); - } +// @Bean +// public UserDimensionProvider userPermissionDimensionProvider() { +// return new UserDimensionProvider(); +// } @Bean public DefaultDimensionUserService defaultDimensionUserService() { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java index 44d431e14..2cce5809b 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java @@ -69,8 +69,9 @@ public Mono doInit(Mono userEntityMono) { .username(user.getUsername()) .userType(user.getType()) .build()); + return initPermission(authentication) - .switchIfEmpty(Mono.just(authentication)) + .defaultIfEmpty(authentication) .onErrorResume(err -> { log.warn(err.getMessage(), err); return Mono.just(authentication); @@ -82,7 +83,6 @@ public Mono doInit(Mono userEntityMono) { .then(Mono.fromSupplier(event::getAuthentication)); }); }); - } protected Flux getSettings(List dimensions) { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java index b90247e24..7a730552a 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveUserService.java @@ -24,6 +24,7 @@ import reactor.core.publisher.Mono; import javax.validation.ValidationException; +import java.util.Objects; public class DefaultReactiveUserService extends GenericReactiveCrudService implements ReactiveUserService { @@ -61,10 +62,19 @@ public Mono saveUser(Mono request) { } return findById(userEntity.getId()) .flatMap(ignore -> doUpdate(userEntity)) - .switchIfEmpty(Mono.error(NotFoundException::new)); + .switchIfEmpty( + Objects.equals(userEntity.getId(),userEntity.getUsername()) ? + doAdd(userEntity) : + Mono.error(NotFoundException::new) + ); }).thenReturn(true); } + @Override + public Mono addUser(UserEntity userEntity) { + return doAdd(userEntity); + } + protected Mono doAdd(UserEntity userEntity) { return Mono From f728de139939a21f40a59fccead5bf4940233222 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 10:01:50 +0800 Subject: [PATCH 096/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=BC=98=E5=85=88=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aop/ReactiveAopAccessLoggerSupport.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java index 76b5cf295..f7130b11d 100644 --- a/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java +++ b/hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/logging/aop/ReactiveAopAccessLoggerSupport.java @@ -39,7 +39,7 @@ * @author zhouhao * @since 3.0 */ -public class ReactiveAopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor implements WebFilter { +public class ReactiveAopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor implements WebFilter{ @Autowired(required = false) private final List loggerParsers = new ArrayList<>(); @@ -58,9 +58,11 @@ public ReactiveAopAccessLoggerSupport() { AccessLoggerInfo info = createLogger(methodInterceptorHolder); Object response = methodInvocation.proceed(); if (response instanceof Mono) { - return wrapMonoResponse(((Mono) response), info); + return wrapMonoResponse(((Mono) response), info) + .subscriberContext(Context.of(AccessLoggerInfo.class, info)); } else if (response instanceof Flux) { - return wrapFluxResponse(((Flux) response), info); + return wrapFluxResponse(((Flux) response), info) + .subscriberContext(Context.of(AccessLoggerInfo.class, info)); } return response; }); @@ -183,7 +185,7 @@ protected AccessLoggerInfo createLogger(MethodInterceptorHolder holder) { @Override public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; + return Ordered.HIGHEST_PRECEDENCE; } @Override @@ -217,10 +219,12 @@ private RequestInfo createAccessInfo(ServerWebExchange exchange) { return info; } + @AllArgsConstructor @EqualsAndHashCode - private static class CacheKey{ + private static class CacheKey { private Class type; private Method method; } + } From ffb0e24acc29d05a2108d5caa5acdf1b230969c1 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 10:32:42 +0800 Subject: [PATCH 097/416] =?UTF-8?q?=E5=A2=9E=E5=8A=A0OAuth2GrantedEvent?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/oauth2/server/AccessTokenManager.java | 1 + .../server/OAuth2ServerAutoConfiguration.java | 9 +++-- .../code/DefaultAuthorizationCodeGranter.java | 34 ++++++++++++++----- .../DefaultClientCredentialGranter.java | 20 ++++++++++- .../server/event/OAuth2GrantedEvent.java | 32 +++++++++++++++++ .../server/impl/RedisAccessTokenManager.java | 10 ++++++ .../server/web/OAuth2AuthorizeController.java | 2 ++ .../DefaultAuthorizationCodeGranterTest.java | 3 +- 8 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/event/OAuth2GrantedEvent.java diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java index e90793c6c..37b484e85 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java @@ -40,4 +40,5 @@ Mono createAccessToken(String clientId, */ Mono refreshAccessToken(String clientId, String refreshToken); + Mono removeToken(String clientId,String token); } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java index 842e21125..42f1a575c 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/OAuth2ServerAutoConfiguration.java @@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; @@ -64,15 +65,17 @@ public AccessTokenManager accessTokenManager(ReactiveRedisOperations redis; @SuppressWarnings("all") - public DefaultAuthorizationCodeGranter(AccessTokenManager accessTokenManager, ReactiveRedisConnectionFactory connectionFactory) { - this(accessTokenManager, new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext + public DefaultAuthorizationCodeGranter(AccessTokenManager accessTokenManager, + ApplicationEventPublisher eventPublisher, + ReactiveRedisConnectionFactory connectionFactory) { + this(accessTokenManager, eventPublisher, new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext .newSerializationContext() .key((RedisSerializer) RedisSerializer.string()) .value(RedisSerializer.java()) @@ -75,16 +82,27 @@ public Mono requestToken(AuthorizationCodeTokenRequest request) { .map(this::getRedisKey) .flatMap(redis.opsForValue()::get) .switchIfEmpty(Mono.error(() -> new OAuth2Exception(ErrorType.ILLEGAL_CODE))) - .flatMap(cache -> redis - .opsForValue() - .delete(getRedisKey(cache.getCode())) - .thenReturn(cache)) + //移除code + .flatMap(cache -> redis.opsForValue().delete(getRedisKey(cache.getCode())).thenReturn(cache)) .flatMap(cache -> { if (!request.getClient().getClientId().equals(cache.getClientId())) { return Mono.error(new OAuth2Exception(ErrorType.ILLEGAL_CLIENT_ID)); } - return accessTokenManager.createAccessToken(cache.getClientId(), cache.getAuthentication(), false); - }); + return accessTokenManager + .createAccessToken(cache.getClientId(), cache.getAuthentication(), false) + .flatMap(token -> new OAuth2GrantedEvent(request.getClient(), + token, + cache.getAuthentication(), + cache.getScope(), + GrantType.authorization_code, + request.getParameters()) + .publish(eventPublisher) + .onErrorResume(err -> accessTokenManager + .removeToken(cache.getClientId(), token.getAccessToken()) + .then(Mono.error(err))) + .thenReturn(token)); + }) + ; } } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/credential/DefaultClientCredentialGranter.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/credential/DefaultClientCredentialGranter.java index 74155bc44..08a78cf29 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/credential/DefaultClientCredentialGranter.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/credential/DefaultClientCredentialGranter.java @@ -2,9 +2,12 @@ import lombok.AllArgsConstructor; import org.hswebframework.web.authorization.ReactiveAuthenticationManager; +import org.hswebframework.web.oauth2.GrantType; import org.hswebframework.web.oauth2.server.AccessToken; import org.hswebframework.web.oauth2.server.AccessTokenManager; import org.hswebframework.web.oauth2.server.OAuth2Client; +import org.hswebframework.web.oauth2.server.event.OAuth2GrantedEvent; +import org.springframework.context.ApplicationEventPublisher; import reactor.core.publisher.Mono; @AllArgsConstructor @@ -14,6 +17,8 @@ public class DefaultClientCredentialGranter implements ClientCredentialGranter { private final AccessTokenManager accessTokenManager; + private final ApplicationEventPublisher eventPublisher; + @Override public Mono requestToken(ClientCredentialRequest request) { @@ -21,6 +26,19 @@ public Mono requestToken(ClientCredentialRequest request) { return authenticationManager .getByUserId(client.getUserId()) - .flatMap(auth -> accessTokenManager.createAccessToken(client.getClientId(), auth, true)); + .flatMap(auth -> accessTokenManager + .createAccessToken(client.getClientId(), auth, true) + .flatMap(token -> new OAuth2GrantedEvent(client, + token, + auth, + "*", + GrantType.client_credentials, + request.getParameters()) + .publish(eventPublisher) + .onErrorResume(err -> accessTokenManager + .removeToken(client.getClientId(), token.getAccessToken()) + .then(Mono.error(err))) + .thenReturn(token)) + ); } } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/event/OAuth2GrantedEvent.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/event/OAuth2GrantedEvent.java new file mode 100644 index 000000000..38b341dcb --- /dev/null +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/event/OAuth2GrantedEvent.java @@ -0,0 +1,32 @@ +package org.hswebframework.web.oauth2.server.event; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.hswebframework.web.authorization.Authentication; +import org.hswebframework.web.event.DefaultAsyncEvent; +import org.hswebframework.web.oauth2.server.AccessToken; +import org.hswebframework.web.oauth2.server.OAuth2Client; + +import java.util.Map; + +/** + * OAuth2授权成功事件 + * + * @author zhouhao + * @since 4.0.15 + */ +@Getter +@AllArgsConstructor +public class OAuth2GrantedEvent extends DefaultAsyncEvent { + private final OAuth2Client client; + + private final AccessToken accessToken; + + private final Authentication authentication; + + private final String scope; + + private final String grantType; + + private final Map parameters; +} diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java index fe1e9b39b..1de7183fa 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java @@ -178,4 +178,14 @@ public Mono refreshAccessToken(String clientId, String refreshToken }); } + + @Override + public Mono removeToken(String clientId, String token) { + + return Flux + .merge(userTokenManager.signOutByToken(token), + tokenRedis.delete(createSingletonTokenRedisKey(clientId)), + tokenRedis.delete(createTokenRedisKey(token))) + .then(); + } } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/web/OAuth2AuthorizeController.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/web/OAuth2AuthorizeController.java index b71ee6468..123ab20f9 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/web/OAuth2AuthorizeController.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/web/OAuth2AuthorizeController.java @@ -19,7 +19,9 @@ import org.hswebframework.web.oauth2.server.code.AuthorizationCodeRequest; import org.hswebframework.web.oauth2.server.code.AuthorizationCodeTokenRequest; import org.hswebframework.web.oauth2.server.credential.ClientCredentialRequest; +import org.hswebframework.web.oauth2.server.event.OAuth2GrantedEvent; import org.hswebframework.web.oauth2.server.refresh.RefreshTokenRequest; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/test/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranterTest.java b/hsweb-authorization/hsweb-authorization-oauth2/src/test/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranterTest.java index 4f9fdaacc..6e0545441 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/test/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranterTest.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/test/java/org/hswebframework/web/oauth2/server/code/DefaultAuthorizationCodeGranterTest.java @@ -7,6 +7,7 @@ import org.hswebframework.web.oauth2.server.RedisHelper; import org.hswebframework.web.oauth2.server.impl.RedisAccessTokenManager; import org.junit.Test; +import org.springframework.context.support.StaticApplicationContext; import reactor.test.StepVerifier; import java.util.Collections; @@ -20,7 +21,7 @@ public class DefaultAuthorizationCodeGranterTest { public void testRequestToken() { DefaultAuthorizationCodeGranter codeGranter = new DefaultAuthorizationCodeGranter( - new RedisAccessTokenManager(RedisHelper.factory), RedisHelper.factory + new RedisAccessTokenManager(RedisHelper.factory), new StaticApplicationContext(), RedisHelper.factory ); OAuth2Client client = new OAuth2Client(); From f2c45b037467ecf7a9e434c3e992169fbf9e5d7f Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 13:54:01 +0800 Subject: [PATCH 098/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/authorization/simple/SimpleAuthentication.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java index e318c6c19..96b36a096 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java @@ -105,4 +105,8 @@ public void setUser(User user) { this.user = user; dimensions.add(user); } + + public void setDimensions(List dimensions) { + this.dimensions.addAll(dimensions); + } } From 6aede9dafb99eb623b4f4a4be674611584e5ee09 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 14:04:31 +0800 Subject: [PATCH 099/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../simple/SimpleAuthentication.java | 4 ++++ ...ltReactiveAuthenticationInitializeService.java | 15 ++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java index 96b36a096..f4aac6b40 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/SimpleAuthentication.java @@ -109,4 +109,8 @@ public void setUser(User user) { public void setDimensions(List dimensions) { this.dimensions.addAll(dimensions); } + + public void addDimension(Dimension dimension) { + this.dimensions.add(dimension); + } } diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java index 2cce5809b..e96e69d7a 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultReactiveAuthenticationInitializeService.java @@ -103,20 +103,17 @@ protected Mono initPermission(SimpleAuthentication authenticatio return Flux.fromIterable(dimensionProviders) .flatMap(provider -> provider.getDimensionByUserId(authentication.getUser().getId())) .cast(Dimension.class) + .doOnNext(authentication::addDimension) .collectList() - .doOnNext(authentication::setDimensions) - .flatMap(allDimension -> - Mono.zip( - getAllPermission() - , getSettings(allDimension) - .collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)) - , (_p, _s) -> handlePermission(authentication, allDimension, _p, _s) - )); + .then(Mono.defer(() -> Mono + .zip(getAllPermission(), + getSettings(authentication.getDimensions()).collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)), + (_p, _s) -> handlePermission(authentication, _p, _s) + ))); } protected SimpleAuthentication handlePermission(SimpleAuthentication authentication, - List dimensionList, Map permissions, Map> settings) { Map permissionMap = new HashMap<>(); From 48068826e1cb6d5a27e57e0865e3f652e69fff10 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 17:00:06 +0800 Subject: [PATCH 100/416] =?UTF-8?q?=E4=BC=98=E5=8C=96token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/oauth2/server/AccessTokenManager.java | 18 ++++- .../server/impl/RedisAccessTokenManager.java | 69 ++++++++++++++++--- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java index 37b484e85..7762b4e4c 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/AccessTokenManager.java @@ -40,5 +40,21 @@ Mono createAccessToken(String clientId, */ Mono refreshAccessToken(String clientId, String refreshToken); - Mono removeToken(String clientId,String token); + /** + * 移除token + * + * @param clientId clientId + * @param token token + * @return void + */ + Mono removeToken(String clientId, String token); + + /** + * 取消对用户的授权 + * + * @param clientId clientId + * @param userId 用户ID + * @return void + */ + Mono cancelGrant(String clientId, String userId); } diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java index 1de7183fa..c42540124 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java @@ -64,12 +64,21 @@ public Mono getAuthenticationByToken(String accessToken) { .map(t -> ((AuthenticationUserToken) t).getAuthentication()); } - private String createTokenRedisKey(String token) { - return "oauth2-token:" + token; + private String createTokenRedisKey(String clientId, String token) { + return "oauth2-token:" + clientId + ":" + token; } - private String createRefreshTokenRedisKey(String token) { - return "oauth2-refresh-token:" + token; + private String createUserTokenRedisKey(RedisAccessToken token) { + return createUserTokenRedisKey(token.getClientId(), token.getAuthentication().getUser().getId()); + } + + private String createUserTokenRedisKey(String clientId, String userId) { + return "oauth2-user-tokens:" + clientId + ":" + userId; + } + + + private String createRefreshTokenRedisKey(String clientId, String token) { + return "oauth2-refresh-token:" + clientId + ":" + token; } private String createSingletonTokenRedisKey(String clientId) { @@ -88,14 +97,14 @@ private Mono storeAuthToken(RedisAccessToken token) { if (token.isSingleton()) { return userTokenManager .signIn(token.getAccessToken(), - "oauth2", + createTokenType(token.getClientId()), token.getAuthentication().getUser().getId(), tokenExpireIn * 1000L) .then(); } else { return userTokenManager .signIn(token.getAccessToken(), - "oauth2", + createTokenType(token.getClientId()), token.getAuthentication().getUser().getId(), tokenExpireIn * 1000L, token.getAuthentication()) @@ -109,10 +118,15 @@ private Mono storeToken(RedisAccessToken token) { .merge(storeAuthToken(token), tokenRedis .opsForValue() - .set(createTokenRedisKey(token.getAccessToken()), token, Duration.ofSeconds(tokenExpireIn)), + .set(createUserTokenRedisKey(token), token, Duration.ofSeconds(tokenExpireIn)), tokenRedis .opsForValue() - .set(createRefreshTokenRedisKey(token.getRefreshToken()), token, Duration.ofSeconds(refreshExpireIn))) + .set(createTokenRedisKey(token.getClientId(), + token.getAccessToken()), token, Duration.ofSeconds(tokenExpireIn)), + tokenRedis + .opsForValue() + .set(createRefreshTokenRedisKey(token.getClientId(), + token.getRefreshToken()), token, Duration.ofSeconds(refreshExpireIn))) .then(); } @@ -144,7 +158,7 @@ public Mono createAccessToken(String clientId, @Override public Mono refreshAccessToken(String clientId, String refreshToken) { - String redisKey = createRefreshTokenRedisKey(refreshToken); + String redisKey = createRefreshTokenRedisKey(clientId, refreshToken); return tokenRedis .opsForValue() @@ -185,7 +199,42 @@ public Mono removeToken(String clientId, String token) { return Flux .merge(userTokenManager.signOutByToken(token), tokenRedis.delete(createSingletonTokenRedisKey(clientId)), - tokenRedis.delete(createTokenRedisKey(token))) + tokenRedis.delete(createTokenRedisKey(clientId, token))) .then(); } + + @Override + public Mono cancelGrant(String clientId, String userId) { + //删除refresh_token + Mono removeRefreshToken = tokenRedis + .opsForValue() + .get(createUserTokenRedisKey(clientId, userId)) + .flatMap(t -> tokenRedis + .opsForValue() + .delete(createRefreshTokenRedisKey(t.getClientId(), t.getRefreshToken()))) + .then(); + + //删除access_token + Mono removeAccessToken = userTokenManager + .getByUserId(userId) + .flatMap(token -> { + //其他类型的token 忽略 + if (!(createTokenType(clientId)).equals(token.getType())) { + return Mono.empty(); + } + //移除token + return tokenRedis + .delete(createTokenRedisKey(clientId, token.getToken())) + .then(userTokenManager.signOutByToken(token.getToken())); + }) + .then(); + + return Flux + .merge(removeRefreshToken, removeAccessToken) + .then(); + } + + private String createTokenType(String clientId) { + return "oauth2-" + clientId; + } } From 7160e859bc488baeb38564e5e7005c1bfa18af57 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 19 Aug 2022 17:13:22 +0800 Subject: [PATCH 101/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/impl/RedisAccessTokenManager.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java index c42540124..412cb00b8 100644 --- a/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-oauth2/src/main/java/org/hswebframework/web/oauth2/server/impl/RedisAccessTokenManager.java @@ -20,6 +20,8 @@ import reactor.core.publisher.Mono; import java.time.Duration; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; public class RedisAccessTokenManager implements AccessTokenManager { @@ -205,7 +207,7 @@ public Mono removeToken(String clientId, String token) { @Override public Mono cancelGrant(String clientId, String userId) { - //删除refresh_token + //删除最新的refresh_token Mono removeRefreshToken = tokenRedis .opsForValue() .get(createUserTokenRedisKey(clientId, userId)) @@ -222,9 +224,18 @@ public Mono cancelGrant(String clientId, String userId) { if (!(createTokenType(clientId)).equals(token.getType())) { return Mono.empty(); } - //移除token return tokenRedis - .delete(createTokenRedisKey(clientId, token.getToken())) + .opsForValue() + .get(createTokenRedisKey(clientId, token.getToken())) + .flatMap(t -> { + //移除token + return tokenRedis + .delete(createTokenRedisKey(t.getClientId(), t.getAccessToken())) + //移除token对应的refresh_token + .then(tokenRedis + .opsForValue() + .delete(createRefreshTokenRedisKey(t.getClientId(), t.getRefreshToken()))); + }) .then(userTokenManager.signOutByToken(token.getToken())); }) .then(); From 9a48d78abe5335a8d79f38f90d906afc1fea3b3e Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 9 Sep 2022 14:18:45 +0800 Subject: [PATCH 102/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../token/redis/RedisUserTokenManager.java | 10 +++++--- .../web/bean/FastBeanCopier.java | 25 ++++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java index a33b5fa3f..f8b80b9e6 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java @@ -53,9 +53,13 @@ public RedisUserTokenManager(ReactiveRedisOperations operations) .buffer(Flux.interval(Duration.ofSeconds(10)), HashSet::new) .flatMap(list -> Flux .fromIterable(list) - .flatMap(token -> operations - .expire(getTokenRedisKey(token.getToken()), Duration.ofMillis(token.getMaxInactiveInterval())) - .then()) + .flatMap(token -> { + String key = getTokenRedisKey(token.getToken()); + return Mono + .zip(userTokenStore.put(key, "lastRequestTime", token.getLastRequestTime()), + operations.expire(key, Duration.ofMillis(token.getMaxInactiveInterval()))) + .then(); + }) .onErrorResume(err -> Mono.empty())) .subscribe(); diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java index de0eea385..b8ad202e9 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java @@ -21,6 +21,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -513,6 +514,8 @@ public Collection newCollection(Class targetClass) { if (targetClass == List.class) { return new ArrayList<>(); + } else if (targetClass == ConcurrentHashMap.KeySetView.class) { + return ConcurrentHashMap.newKeySet(); } else if (targetClass == Set.class) { return new HashSet<>(); } else if (targetClass == Queue.class) { @@ -568,7 +571,7 @@ public T convert(Object source, Class targetClass, Class[] genericType) { return (T) new Date(((Date) source).getTime()); } } - if (Collection.class.isAssignableFrom(targetClass)) { + if (target.isCollectionType()) { Collection collection = newCollection(targetClass); Collection sourceCollection; if (source instanceof Collection) { @@ -619,7 +622,7 @@ public T convert(Object source, Class targetClass, Class[] genericType) { Enum t = ((Enum) e); if ((t.name().equalsIgnoreCase(strSource) || Objects.equals(String.valueOf(t.ordinal()), strSource))) { - return (T)e; + return (T) e; } } @@ -642,7 +645,7 @@ public T convert(Object source, Class targetClass, Class[] genericType) { //快速复制map if (targetClass == Map.class) { if (source instanceof Map) { - return (T) new HashMap(((Map) source)); + return (T) copyMap(((Map) source)); } ClassDescription sourType = ClassDescriptions.getDescription(source.getClass()); return (T) copy(source, Maps.newHashMapWithExpectedSize(sourType.getFieldSize())); @@ -656,6 +659,22 @@ public T convert(Object source, Class targetClass, Class[] genericType) { // return null; } + private Map copyMap(Map map) { + if (map instanceof TreeMap) { + return new TreeMap<>(map); + } + + if (map instanceof LinkedHashMap) { + return new LinkedHashMap<>(map); + } + + if (map instanceof ConcurrentHashMap) { + return new ConcurrentHashMap<>(map); + } + + return new HashMap<>(map); + } + private Object converterByApache(Class targetClass, Object source) { org.apache.commons.beanutils.Converter converter = convertUtils.lookup(targetClass); if (null != converter) { From 24d8550bf6126d5e2bf307c0ead4de986be70f3c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 9 Sep 2022 14:19:30 +0800 Subject: [PATCH 103/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/authorization/token/redis/RedisUserTokenManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java index f8b80b9e6..3ff4c2b26 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/redis/RedisUserTokenManager.java @@ -56,8 +56,8 @@ public RedisUserTokenManager(ReactiveRedisOperations operations) .flatMap(token -> { String key = getTokenRedisKey(token.getToken()); return Mono - .zip(userTokenStore.put(key, "lastRequestTime", token.getLastRequestTime()), - operations.expire(key, Duration.ofMillis(token.getMaxInactiveInterval()))) + .zip(this.userTokenStore.put(key, "lastRequestTime", token.getLastRequestTime()), + this.operations.expire(key, Duration.ofMillis(token.getMaxInactiveInterval()))) .then(); }) .onErrorResume(err -> Mono.empty())) From c654222054c3a0ffed7b9693ba10755f2841826a Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 21 Sep 2022 11:06:05 +0800 Subject: [PATCH 104/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8DUpdateEvent=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=8E=B7=E5=8F=96=E4=BF=AE=E6=94=B9=E5=90=8E=E7=9A=84?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/events/EntityEventListener.java | 56 +++++++++---------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index 94e82b682..aa4ae38b2 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -133,39 +133,37 @@ protected void handleQueryBefore(EntityColumnMapping mapping, EventContext conte protected List createAfterData(List olds, EventContext context) { List newValues = new ArrayList<>(olds.size()); + EntityColumnMapping mapping = context .get(MappingContextKeys.columnMapping) .orElseThrow(UnsupportedOperationException::new); - TableOrViewMetadata table = context.get(ContextKeys.table).orElseThrow(UnsupportedOperationException::new); - RDBColumnMetadata idColumn = table - .getColumns() - .stream() - .filter(RDBColumnMetadata::isPrimaryKey) - .findFirst() - .orElse(null); - if (idColumn == null) { - return Collections.emptyList(); - } + + Map columns = context + .get(MappingContextKeys.updateColumnInstance) + .orElse(Collections.emptyMap()); + for (Object old : olds) { - Object newValue = context - .get(MappingContextKeys.updateColumnInstance) - .map(map -> { - Object data = FastBeanCopier.copy(map, FastBeanCopier.copy(old, mapping.newInstance())); - for (Map.Entry entry : map.entrySet()) { - //set null - if (entry.getValue() == null - || entry.getValue() instanceof NullValue) { - GlobalConfig - .getPropertyOperator() - .setProperty(data, entry.getKey(), null); - } - } - return data; - }) - .orElseThrow(() -> { - return new IllegalArgumentException("can not get update instance"); - }); - newValues.add(newValue); + Object data = FastBeanCopier.copy(old, mapping.newInstance()); + for (Map.Entry entry : columns.entrySet()) { + + RDBColumnMetadata column = mapping.getColumnByName(entry.getKey()).orElse(null); + if (column == null) { + continue; + } + + Object value = entry.getValue(); + + //set null + if (value instanceof NullValue) { + value = null; + } + + GlobalConfig + .getPropertyOperator() + .setProperty(data, column.getAlias(), value); + + } + newValues.add(data); } return newValues; } From 3e6bcec8115c5d5fe495cf4eaeb0a0ffe1e44e37 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 21 Sep 2022 11:06:09 +0800 Subject: [PATCH 105/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/factory/MapperEntityFactory.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java index c61c6f805..d1a201c41 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java @@ -27,8 +27,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; /** @@ -37,9 +39,11 @@ */ @SuppressWarnings("unchecked") public class MapperEntityFactory implements EntityFactory, BeanFactory { - private Map realTypeMapper = new HashMap<>(); - private Logger logger = LoggerFactory.getLogger(this.getClass()); - private Map copierCache = new HashMap<>(); + @SuppressWarnings("all") + private final Map, Mapper> realTypeMapper = new ConcurrentHashMap<>(); + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + @SuppressWarnings("all") + private final Map copierCache = new ConcurrentHashMap<>(); private static final DefaultMapperFactory DEFAULT_MAPPER_FACTORY = clazz -> { String simpleClassName = clazz.getPackage().getName().concat(".Simple").concat(clazz.getSimpleName()); @@ -68,6 +72,16 @@ public MapperEntityFactory(Map, Mapper> realTypeMapper) { this.realTypeMapper.putAll(realTypeMapper); } + public MapperEntityFactory addMapping(Class target, Supplier mapper) { + realTypeMapper.put(target, new Mapper(target, mapper)); + return this; + } + + public MapperEntityFactory addMappingIfAbsent(Class target, Supplier mapper) { + realTypeMapper.putIfAbsent(target, new Mapper(target, mapper)); + return this; + } + public MapperEntityFactory addMapping(Class target, Mapper mapper) { realTypeMapper.put(target, mapper); return this; @@ -216,8 +230,8 @@ public void setDefaultPropertyCopier(DefaultPropertyCopier defaultPropertyCopier } public static class Mapper { - Class target; - Supplier instanceGetter; + final Class target; + final Supplier instanceGetter; public Mapper(Class target, Supplier instanceGetter) { this.target = target; @@ -242,16 +256,17 @@ public static Supplier defaultInstanceGetter(Class clazz) { } static class DefaultInstanceGetter implements Supplier { - Class type; + final Constructor constructor; + @SneakyThrows public DefaultInstanceGetter(Class type) { - this.type = type; + this.constructor = type.getConstructor(); } @Override @SneakyThrows public T get() { - return type.newInstance(); + return constructor.newInstance(); } } } From 87b921528f794d5e7994ed8fdcf8331cbbc7c8bf Mon Sep 17 00:00:00 2001 From: zhouhao Date: Wed, 28 Sep 2022 18:47:24 +0800 Subject: [PATCH 106/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A1=A8=E5=90=8D?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../defaults/service/terms/DimensionTerm.java | 20 +++++++++---------- .../service/terms/UserDimensionTerm.java | 2 +- pom.xml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/DimensionTerm.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/DimensionTerm.java index 9760376d2..11b447e7d 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/DimensionTerm.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/DimensionTerm.java @@ -28,19 +28,19 @@ public DimensionTerm() { } public static > T inject(T query, - String column, - String dimensionType, - List userId) { + String column, + String dimensionType, + List userId) { return inject(query, column, dimensionType, false, false, userId); } public static > T inject(T query, - String column, - String dimensionType, - boolean not, - boolean any, - List userId) { - return (T)query.accept(column, createTermType(dimensionType, not, any), userId); + String column, + String dimensionType, + boolean not, + boolean any, + List userId) { + return (T) query.accept(column, createTermType(dimensionType, not, any), userId); } public static String createTermType(String dimensionType, boolean not, boolean any) { @@ -73,7 +73,7 @@ public SqlFragments createFragments(String columnFullName, RDBColumnMetadata col fragments.addSql("not "); } fragments - .addSql("exists(select 1 from s_dimension_user d where d.dimension_type_id = ? and d.dimension_id =", columnFullName) + .addSql("exists(select 1 from", getTableName("s_dimension_user", column), "d where d.dimension_type_id = ? and d.dimension_id =", columnFullName) .addParameter(options.get(0)); if (!options.contains("any")) { diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/UserDimensionTerm.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/UserDimensionTerm.java index 7078b197d..b63fc2b4f 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/UserDimensionTerm.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/terms/UserDimensionTerm.java @@ -37,7 +37,7 @@ public SqlFragments createFragments(String columnFullName, RDBColumnMetadata col fragments.addSql("not"); } - fragments.addSql("exists(select 1 from s_dimension_user d where d.user_id =", columnFullName); + fragments.addSql("exists(select 1 from ",getTableName("s_dimension_user",column)," d where d.user_id =", columnFullName); if (options.size() > 0) { String typeId = options.get(0); diff --git a/pom.xml b/pom.xml index 8854cd5de..c2ad6774a 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ 3.2.2 1.6.12 - 4.0.14 + 4.1.0-SNAPSHOT 3.0.2 3.0.2 2.7.0 From ffdd084920ed6e17c10e24032d887c67b16602e2 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 14 Oct 2022 20:11:28 +0800 Subject: [PATCH 107/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../configuration/EasyormConfiguration.java | 18 +++-- .../crud/events/CompositeEventListener.java | 3 + .../web/crud/events/CreatorEventListener.java | 71 +++++++++++++------ .../web/crud/events/EntityEventListener.java | 11 +++ 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java index 9042b6c9d..393ca3cb8 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormConfiguration.java @@ -38,6 +38,8 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; @@ -112,22 +114,24 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw }; } + @Bean - public EntityEventListener entityEventListener(ApplicationEventPublisher eventPublisher, - ObjectProvider customizers) { - DefaultEntityEventListenerConfigure configure = new DefaultEntityEventListenerConfigure(); - customizers.forEach(customizer -> customizer.customize(configure)); - return new EntityEventListener(eventPublisher, configure); + public CreatorEventListener creatorEventListener() { + return new CreatorEventListener(); } + @Bean public ValidateEventListener validateEventListener() { return new ValidateEventListener(); } @Bean - public CreatorEventListener creatorEventListener() { - return new CreatorEventListener(); + public EntityEventListener entityEventListener(ApplicationEventPublisher eventPublisher, + ObjectProvider customizers) { + DefaultEntityEventListenerConfigure configure = new DefaultEntityEventListenerConfigure(); + customizers.forEach(customizer -> customizer.customize(configure)); + return new EntityEventListener(eventPublisher, configure); } @Bean diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CompositeEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CompositeEventListener.java index 638850b9f..f07ece5db 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CompositeEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CompositeEventListener.java @@ -5,7 +5,9 @@ import org.hswebframework.ezorm.rdb.events.EventContext; import org.hswebframework.ezorm.rdb.events.EventListener; import org.hswebframework.ezorm.rdb.events.EventType; +import org.springframework.core.Ordered; +import java.util.Comparator; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -24,5 +26,6 @@ public void onEvent(EventType type, EventContext context) { public void addListener(EventListener eventListener) { eventListeners.add(eventListener); + eventListeners.sort(Comparator.comparingLong(e -> e instanceof Ordered ? ((Ordered) e).getOrder() : Ordered.LOWEST_PRECEDENCE)); } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java index 9662899d3..722f18a11 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java @@ -12,19 +12,21 @@ import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.validator.CreateGroup; import org.hswebframework.web.validator.UpdateGroup; +import org.springframework.core.Ordered; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import reactor.core.publisher.Mono; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; /** * 自动填充创建人和修改人信息 */ -public class CreatorEventListener implements EventListener { +public class CreatorEventListener implements EventListener, Ordered { @Override public String getId() { @@ -60,27 +62,45 @@ public void onEvent(EventType type, EventContext context) { } protected void doApplyCreator(EventType type, EventContext context, Authentication auth) { - context.get(MappingContextKeys.instance) - .ifPresent(obj -> { - if (obj instanceof Collection) { - applyCreator(auth, ((Collection) obj), type != MappingEventTypes.update_before); - } else { - applyCreator(auth, obj, type != MappingEventTypes.update_before); - } - }); + Object instance = context.get(MappingContextKeys.instance).orElse(null); + if (instance != null) { + if (instance instanceof Collection) { + applyCreator(auth, context, ((Collection) instance), type != MappingEventTypes.update_before); + } else { + applyCreator(auth, context, instance, type != MappingEventTypes.update_before); + } + } else { + context.get(MappingContextKeys.updateColumnInstance) + .ifPresent(map -> { + applyCreator(auth, context, map, type != MappingEventTypes.update_before); + }); + } + + } - public void applyCreator(Authentication auth, Object entity, boolean updateCreator) { - if (updateCreator && entity instanceof RecordCreationEntity) { - RecordCreationEntity e = (RecordCreationEntity) entity; - if (ObjectUtils.isEmpty(e.getCreatorId())) { - e.setCreatorId(auth.getUser().getId()); - e.setCreatorName(auth.getUser().getName()); - } - if (e.getCreateTime() == null) { - e.setCreateTimeNow(); + public void applyCreator(Authentication auth, + EventContext context, + Object entity, + boolean updateCreator) { + if (updateCreator) { + if (entity instanceof RecordCreationEntity) { + RecordCreationEntity e = (RecordCreationEntity) entity; + if (ObjectUtils.isEmpty(e.getCreatorId())) { + e.setCreatorId(auth.getUser().getId()); + e.setCreatorName(auth.getUser().getName()); + } + if (e.getCreateTime() == null) { + e.setCreateTimeNow(); + } + } else if (entity instanceof Map) { + Map map = ((Map) entity); + map.putIfAbsent("creatorId", auth.getUser().getId()); + map.putIfAbsent("creatorName", auth.getUser().getName()); + map.putIfAbsent("createTime", auth.getUser().getId()); } + } if (entity instanceof RecordModifierEntity) { RecordModifierEntity e = (RecordModifierEntity) entity; @@ -91,13 +111,24 @@ public void applyCreator(Authentication auth, Object entity, boolean updateCreat if (e.getModifyTime() == null) { e.setModifyTimeNow(); } + } else if (entity instanceof Map) { + Map map = ((Map) entity); + map.putIfAbsent("modifierId", auth.getUser().getId()); + map.putIfAbsent("modifierName", auth.getUser().getName()); + map.putIfAbsent("modifyTime", auth.getUser().getId()); + } } - public void applyCreator(Authentication auth, Collection entities, boolean updateCreator) { + public void applyCreator(Authentication auth, EventContext context, Collection entities, boolean updateCreator) { for (Object entity : entities) { - applyCreator(auth, entity, updateCreator); + applyCreator(auth, context, entity, updateCreator); } } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index aa4ae38b2..b88ea7ecf 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -142,6 +142,17 @@ protected List createAfterData(List olds, .get(MappingContextKeys.updateColumnInstance) .orElse(Collections.emptyMap()); + List newerInstance = context + .get(MappingContextKeys.instance) + .map(instance -> { + if (instance instanceof List) { + return ((List) instance); + } + return Collections.singletonList(instance); + }) + .orElse(null); + + for (Object old : olds) { Object data = FastBeanCopier.copy(old, mapping.newInstance()); for (Map.Entry entry : columns.entrySet()) { From bff95506b158037c5208abef6bb3c64862319598 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 14 Oct 2022 20:12:36 +0800 Subject: [PATCH 108/416] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E6=B8=85=E9=99=A4=E7=94=A8=E6=88=B7=E6=9D=83?= =?UTF-8?q?=E9=99=90=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../defaults/service/DefaultDimensionUserService.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java index af9489925..538d345a7 100644 --- a/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java +++ b/hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/src/main/java/org/hswebframework/web/system/authorization/defaults/service/DefaultDimensionUserService.java @@ -56,9 +56,6 @@ public void handleUserDeleteEntity(UserDeletedEvent event) { public void dispatchDimensionBind(EntitySavedEvent event) { event.async( this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionBindEvent::new) - .then( - this.clearUserCache(event.getEntity()) - ) ); } @@ -67,9 +64,6 @@ public void dispatchDimensionBind(EntitySavedEvent event) { public void dispatchDimensionBind(EntityCreatedEvent event) { event.async( this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionBindEvent::new) - .then( - this.clearUserCache(event.getEntity()) - ) ); } @@ -78,9 +72,6 @@ public void dispatchDimensionBind(EntityCreatedEvent event) public void dispatchDimensionUnbind(EntityDeletedEvent event) { event.async( this.publishEvent(Flux.fromIterable(event.getEntity()), DimensionUnbindEvent::new) - .then( - this.clearUserCache(event.getEntity()) - ) ); } From df145478164f82467d86173899ad3c8842232899 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 17 Oct 2022 11:32:32 +0800 Subject: [PATCH 109/416] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/events/CreatorEventListener.java | 17 ++++++++-------- .../web/crud/events/EntityEventListener.java | 20 ++++++++----------- .../crud/events/ValidateEventListener.java | 8 +++++++- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java index 722f18a11..54f1f14af 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/CreatorEventListener.java @@ -69,13 +69,11 @@ protected void doApplyCreator(EventType type, EventContext context, Authenticati } else { applyCreator(auth, context, instance, type != MappingEventTypes.update_before); } - } else { - context.get(MappingContextKeys.updateColumnInstance) - .ifPresent(map -> { - applyCreator(auth, context, map, type != MappingEventTypes.update_before); - }); } + context + .get(MappingContextKeys.updateColumnInstance) + .ifPresent(map -> applyCreator(auth, context, map, type != MappingEventTypes.update_before)); } @@ -83,6 +81,7 @@ public void applyCreator(Authentication auth, EventContext context, Object entity, boolean updateCreator) { + long now = System.currentTimeMillis(); if (updateCreator) { if (entity instanceof RecordCreationEntity) { RecordCreationEntity e = (RecordCreationEntity) entity; @@ -91,13 +90,13 @@ public void applyCreator(Authentication auth, e.setCreatorName(auth.getUser().getName()); } if (e.getCreateTime() == null) { - e.setCreateTimeNow(); + e.setCreateTime(now); } } else if (entity instanceof Map) { Map map = ((Map) entity); map.putIfAbsent("creatorId", auth.getUser().getId()); map.putIfAbsent("creatorName", auth.getUser().getName()); - map.putIfAbsent("createTime", auth.getUser().getId()); + map.putIfAbsent("createTime", now); } @@ -109,13 +108,13 @@ public void applyCreator(Authentication auth, e.setModifierName(auth.getUser().getName()); } if (e.getModifyTime() == null) { - e.setModifyTimeNow(); + e.setModifyTime(now); } } else if (entity instanceof Map) { Map map = ((Map) entity); map.putIfAbsent("modifierId", auth.getUser().getId()); map.putIfAbsent("modifierName", auth.getUser().getName()); - map.putIfAbsent("modifyTime", auth.getUser().getId()); + map.putIfAbsent("modifyTime", now); } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index b88ea7ecf..033719238 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -22,6 +22,7 @@ import org.hswebframework.web.event.AsyncEvent; import org.hswebframework.web.event.GenericsPayloadApplicationEvent; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.core.Ordered; import reactor.core.publisher.Mono; import reactor.function.Function3; import reactor.util.function.Tuple2; @@ -36,7 +37,7 @@ @SuppressWarnings("all") @AllArgsConstructor -public class EntityEventListener implements EventListener { +public class EntityEventListener implements EventListener, Ordered { private final ApplicationEventPublisher eventPublisher; @@ -142,17 +143,6 @@ protected List createAfterData(List olds, .get(MappingContextKeys.updateColumnInstance) .orElse(Collections.emptyMap()); - List newerInstance = context - .get(MappingContextKeys.instance) - .map(instance -> { - if (instance instanceof List) { - return ((List) instance); - } - return Collections.singletonList(instance); - }) - .orElse(null); - - for (Object old : olds) { Object data = FastBeanCopier.copy(old, mapping.newInstance()); for (Map.Entry entry : columns.entrySet()) { @@ -239,6 +229,7 @@ protected void handleUpdateBefore(DSLUpdate update, EventContext context) holder.invoke(this.doAsyncEvent(() -> { Tuple2, List> _tmp = updated.get(); if (_tmp != null) { + return sendUpdateEvent(_tmp.getT1(), _tmp.getT2(), entityType, @@ -477,4 +468,9 @@ protected Mono doAsyncEvent(Supplier> eventSupplier) { return eventSupplier.get(); }); } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java index 342dc9e92..75f70d816 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java @@ -10,11 +10,12 @@ import org.hswebframework.web.i18n.LocaleUtils; import org.hswebframework.web.validator.CreateGroup; import org.hswebframework.web.validator.UpdateGroup; +import org.springframework.core.Ordered; import java.util.List; import java.util.Optional; -public class ValidateEventListener implements EventListener { +public class ValidateEventListener implements EventListener, Ordered { @Override public String getId() { @@ -73,4 +74,9 @@ public void tryValidate(EventType type, EventContext context) { .ifPresent(entity -> entity.tryValidate(UpdateGroup.class)); } } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 100; + } } From 7529d9201ffa45dca41c46f0b5122b717a362f65 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 21 Oct 2022 19:13:16 +0800 Subject: [PATCH 110/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../simple/CompositeReactiveAuthenticationManager.java | 7 ++++++- .../web/cache/supports/RedisReactiveCache.java | 5 ++--- .../web/cache/supports/UnSupportedReactiveCache.java | 5 +++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java index 7a1d5502e..79c2037c4 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java @@ -1,6 +1,7 @@ package org.hswebframework.web.authorization.simple; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.hswebframework.web.authorization.*; import reactor.core.publisher.Flux; @@ -11,6 +12,7 @@ import java.util.stream.Collectors; @AllArgsConstructor +@Slf4j public class CompositeReactiveAuthenticationManager implements ReactiveAuthenticationManager { private final List providers; @@ -34,7 +36,10 @@ public Mono getByUserId(String userId) { .stream() .map(manager -> manager .getByUserId(userId) - .onErrorResume((err) -> Mono.empty()) + .onErrorResume((err) -> { + log.warn("get user [{}] authentication error", userId, err); + return Mono.empty(); + }) )) .flatMap(Function.identity()) .collectList() diff --git a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/RedisReactiveCache.java b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/RedisReactiveCache.java index df5b53a8c..c8d6f4387 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/RedisReactiveCache.java +++ b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/RedisReactiveCache.java @@ -64,9 +64,8 @@ public Flux getFlux(Object key) { } protected Mono handleError(Throwable error) { - return Mono.fromRunnable(() -> { - log.error(error.getMessage(), error); - }); + log.error(error.getMessage(), error); + return Mono.empty(); } @Override diff --git a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/UnSupportedReactiveCache.java b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/UnSupportedReactiveCache.java index 4200e2de7..68a2b8ed2 100644 --- a/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/UnSupportedReactiveCache.java +++ b/hsweb-concurrent/hsweb-concurrent-cache/src/main/java/org/hswebframework/web/cache/supports/UnSupportedReactiveCache.java @@ -15,10 +15,11 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class UnSupportedReactiveCache implements ReactiveCache { - private static final UnSupportedReactiveCache INSTANCE = new UnSupportedReactiveCache(); + private static final UnSupportedReactiveCache INSTANCE = new UnSupportedReactiveCache<>(); + @SuppressWarnings("all") public static ReactiveCache getInstance() { - return INSTANCE; + return (UnSupportedReactiveCache)INSTANCE; } @Override From ce703c401efd0496c2ca5f85018cf2a60134369b Mon Sep 17 00:00:00 2001 From: zhouhao Date: Fri, 21 Oct 2022 19:14:49 +0800 Subject: [PATCH 111/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../simple/CompositeReactiveAuthenticationManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java index 79c2037c4..c7a6dc643 100644 --- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java +++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/simple/CompositeReactiveAuthenticationManager.java @@ -23,7 +23,10 @@ public Mono authenticate(Mono request) { .stream() .map(manager -> manager .authenticate(request) - .onErrorResume((err) -> Mono.empty())) + .onErrorResume((err) -> { + log.warn("get user authenticate error", err); + return Mono.empty(); + })) .collect(Collectors.toList())) .take(1) .next(); From b3ba02961bc59715e90c370cf1483150a66a3559 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 24 Oct 2022 13:35:48 +0800 Subject: [PATCH 112/416] =?UTF-8?q?=E4=BC=98=E5=8C=96cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hswebframework/web/crud/events/EntityEventListener.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index 033719238..6366b0a68 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -39,6 +39,9 @@ @AllArgsConstructor public class EntityEventListener implements EventListener, Ordered { + public static final ContextKey> readyToDeleteContextKey = ContextKey.of("readyToDelete"); + public static final ContextKey> readyToUpdateContextKey = ContextKey.of("readyToUpdate"); + private final ApplicationEventPublisher eventPublisher; private final EntityEventListenerConfigure listenerConfigure; @@ -214,6 +217,7 @@ protected void handleUpdateBefore(DSLUpdate update, EventContext context) .collectList() .flatMap((list) -> { List after = createAfterData(list, context); + context.set(readyToUpdateContextKey,after); updated.set(Tuples.of(list, after)); return sendUpdateEvent(list, after, @@ -299,6 +303,7 @@ protected void handleDeleteBefore(Class entityType, EventContext context .collectList() .filter(CollectionUtils::isNotEmpty) .flatMap(list -> { + context.set(readyToDeleteContextKey,list); deleted.set(list); return this .sendDeleteEvent(list, (Class) mapping.getEntityType(), EntityBeforeDeleteEvent::new); From fa3b0a67d0b98294f8e72af17faba01b9bf154bb Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 25 Oct 2022 18:42:42 +0800 Subject: [PATCH 113/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/events/EntityEventListener.java | 7 ++++--- .../web/crud/events/ValidateEventListener.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java index 6366b0a68..80e31bf9a 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/EntityEventListener.java @@ -217,7 +217,6 @@ protected void handleUpdateBefore(DSLUpdate update, EventContext context) .collectList() .flatMap((list) -> { List after = createAfterData(list, context); - context.set(readyToUpdateContextKey,after); updated.set(Tuples.of(list, after)); return sendUpdateEvent(list, after, @@ -301,9 +300,11 @@ protected void handleDeleteBefore(Class entityType, EventContext context .setParam(dslUpdate.toQueryParam()) .fetch() .collectList() + .doOnNext(list->{ + context.set(readyToDeleteContextKey, list); + }) .filter(CollectionUtils::isNotEmpty) .flatMap(list -> { - context.set(readyToDeleteContextKey,list); deleted.set(list); return this .sendDeleteEvent(list, (Class) mapping.getEntityType(), EntityBeforeDeleteEvent::new); @@ -476,6 +477,6 @@ protected Mono doAsyncEvent(Supplier> eventSupplier) { @Override public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; + return Ordered.LOWEST_PRECEDENCE - 100; } } diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java index 75f70d816..4d52c1c14 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/events/ValidateEventListener.java @@ -77,6 +77,6 @@ public void tryValidate(EventType type, EventContext context) { @Override public int getOrder() { - return Ordered.LOWEST_PRECEDENCE - 100; + return Ordered.LOWEST_PRECEDENCE - 1000; } } From 8fad92100a6e672a0adaf64f29857f3e70f5b77c Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 27 Oct 2022 17:20:01 +0800 Subject: [PATCH 114/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=86=85=E5=B5=8C?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../embed/EmbedAuthenticationProperties.java | 31 ++++++++++++------- .../EmbedReactiveAuthenticationManager.java | 13 +++++++- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationProperties.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationProperties.java index e4a09e3c0..1b35e4b1a 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationProperties.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedAuthenticationProperties.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; +import org.apache.commons.collections4.MapUtils; import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.authorization.AuthenticationRequest; import org.hswebframework.web.authorization.builder.DataAccessConfigBuilderFactory; @@ -69,7 +70,10 @@ public void afterPropertiesSet() { for (Map.Entry stringObjectEntry : objectMap.entrySet()) { if (stringObjectEntry.getValue() instanceof Map) { Map mapVal = ((Map) stringObjectEntry.getValue()); - boolean maybeIsList = mapVal.keySet().stream().allMatch(org.hswebframework.utils.StringUtils::isInt); + boolean maybeIsList = mapVal + .keySet() + .stream() + .allMatch(org.hswebframework.utils.StringUtils::isInt); if (maybeIsList) { stringObjectEntry.setValue(mapVal.values()); } @@ -82,20 +86,23 @@ public void afterPropertiesSet() { } public Authentication authenticate(AuthenticationRequest request) { - if(request instanceof PlainTextUsernamePasswordAuthenticationRequest){ + if (MapUtils.isEmpty(users)) { + return null; + } + if (request instanceof PlainTextUsernamePasswordAuthenticationRequest) { PlainTextUsernamePasswordAuthenticationRequest pwdReq = ((PlainTextUsernamePasswordAuthenticationRequest) request); - return users.values() - .stream() - .filter(user -> - pwdReq.getUsername().equals(user.getUsername()) - && pwdReq.getPassword().equals(user.getPassword())) - .findFirst() - .map(EmbedAuthenticationInfo::getId) - .map(authentications::get) - .orElseThrow(() -> new ValidationException("用户不存在")); + for (EmbedAuthenticationInfo user : users.values()) { + if (pwdReq.getUsername().equals(user.getUsername())) { + if (pwdReq.getPassword().equals(user.getPassword())) { + return user.toAuthentication(dataAccessConfigBuilderFactory); + } + return null; + } + } + return null; } - throw new UnsupportedOperationException("不支持的授权请求:"+request); + throw new UnsupportedOperationException("不支持的授权请求:" + request); } public Optional getAuthentication(String userId) { diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java index 6aabf28d9..94fbd6739 100644 --- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java +++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/embed/EmbedReactiveAuthenticationManager.java @@ -1,6 +1,8 @@ package org.hswebframework.web.authorization.basic.embed; import lombok.AllArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.hswebframework.web.authorization.Authentication; import org.hswebframework.web.authorization.AuthenticationRequest; import org.hswebframework.web.authorization.ReactiveAuthenticationManager; @@ -22,7 +24,16 @@ public class EmbedReactiveAuthenticationManager implements ReactiveAuthenticatio @Override public Mono authenticate(Mono request) { - return request.map(properties::authenticate); + if (MapUtils.isEmpty(properties.getUsers())) { + return Mono.empty(); + } + return request. + handle((req, sink) -> { + Authentication auth = properties.authenticate(req); + if (auth != null) { + sink.next(auth); + } + }); } From 1bef816dc64956f8af622927d99272b1f0a31359 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 31 Oct 2022 19:03:34 +0800 Subject: [PATCH 115/416] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/crud/web/ResponseMessageWrapperAdvice.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java index b57bcc504..d4f32299c 100644 --- a/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java +++ b/hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/ResponseMessageWrapperAdvice.java @@ -20,6 +20,7 @@ import reactor.core.publisher.Mono; import javax.annotation.Nonnull; +import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; @@ -82,17 +83,21 @@ public Object beforeBodyWrite(Object body, if (body instanceof Mono) { return ((Mono) body) .map(ResponseMessage::ok) - .switchIfEmpty(Mono.just(ResponseMessage.ok())); + .switchIfEmpty(Mono.fromSupplier(ResponseMessage::ok)); } if (body instanceof Flux) { return ((Flux) body) .collectList() .map(ResponseMessage::ok) - .switchIfEmpty(Mono.just(ResponseMessage.ok())); + .switchIfEmpty(Mono.fromSupplier(ResponseMessage::ok)); } - if (body instanceof String) { + + Method method = returnType.getMethod(); + + if (method != null && returnType.getMethod().getReturnType() == String.class) { return JSON.toJSONString(ResponseMessage.ok(body)); } + return ResponseMessage.ok(body); } From 50667b9b21dc4cb748b4952537261e533b8362da Mon Sep 17 00:00:00 2001 From: zhouhao Date: Mon, 28 Nov 2022 11:56:57 +0800 Subject: [PATCH 116/416] =?UTF-8?q?=E4=BC=98=E5=8C=96map=E8=BD=AClist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/bean/FastBeanCopier.java | 15 +++++ .../web/bean/FastBeanCopierTest.java | 61 +++++++++++++++---- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java index b8ad202e9..909c99343 100644 --- a/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java +++ b/hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java @@ -578,6 +578,8 @@ public T convert(Object source, Class targetClass, Class[] genericType) { sourceCollection = (Collection) source; } else if (source instanceof Object[]) { sourceCollection = Arrays.asList((Object[]) source); + } else if (source instanceof Map) { + sourceCollection = ((Map) source).values(); } else { if (source instanceof String) { String stringValue = ((String) source); @@ -647,6 +649,19 @@ public T convert(Object source, Class targetClass, Class[] genericType) { if (source instanceof Map) { return (T) copyMap(((Map) source)); } + if (source instanceof Collection) { + Map map = new LinkedHashMap<>(); + int i = 0; + for (Object o : ((Collection) source)) { + if (genericType.length >= 2) { + map.put(convert(i++, genericType[0], EMPTY_CLASS_ARRAY), convert(o, genericType[1], EMPTY_CLASS_ARRAY)); + } else { + map.put(i++, o); + } + } + return (T) map; + + } ClassDescription sourType = ClassDescriptions.getDescription(source.getClass()); return (T) copy(source, Maps.newHashMapWithExpectedSize(sourType.getFieldSize())); } diff --git a/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java b/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java index fe7e177e4..0c73a2b45 100644 --- a/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java +++ b/hsweb-core/src/test/java/org/hswebframework/web/bean/FastBeanCopierTest.java @@ -1,16 +1,14 @@ package org.hswebframework.web.bean; import com.google.common.collect.ImmutableMap; -import jdk.nashorn.internal.objects.annotations.Getter; +import lombok.Getter; +import lombok.Setter; import org.junit.Assert; import org.junit.Test; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; /** @@ -61,6 +59,43 @@ public void testMapArray() { } + @Test + public void testMapList() { + Map data = new HashMap<>(); + data.put("templates", new HashMap() { + { + put("0", Collections.singletonMap("name", "test")); + put("1", Collections.singletonMap("name", "test")); + } + }); + + Config config = FastBeanCopier.copy(data, new Config()); + + Assert.assertNotNull(config); + Assert.assertNotNull(config.templates); + System.out.println(config.templates); + Assert.assertEquals(2,config.templates.size()); + + + } + + @Getter + @Setter + public static class Config { + private List