zhou-hao пре 5 година
родитељ
комит
2e39ea195e
15 измењених фајлова са 501 додато и 193 уклоњено
  1. 5 2
      hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java
  2. 7 0
      hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java
  3. 29 6
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DimensionDataAccessHandler.java
  4. 4 1
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java
  5. 6 1
      hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java
  6. 112 0
      hsweb-core/src/main/java/org/hswebframework/web/logger/ReactiveLogger.java
  7. 33 0
      hsweb-core/src/test/java/org/hswebframework/web/logger/ReactiveLoggerTest.java
  8. 17 0
      hsweb-logging/hsweb-access-logging-aop/pom.xml
  9. 3 20
      hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupport.java
  10. 14 25
      hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupportAutoConfiguration.java
  11. 170 0
      hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/ReactiveAopAccessLoggerSupport.java
  12. 54 0
      hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/ResourceAccessLoggerParser.java
  13. 13 117
      hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java
  14. 9 21
      hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/LoggerDefine.java
  15. 25 0
      hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/RequestInfo.java

+ 5 - 2
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenReactiveAuthenticationSupplier.java

@@ -6,6 +6,7 @@ import org.hswebframework.web.authorization.ReactiveAuthenticationSupplier;
 import org.hswebframework.web.authorization.exception.UnAuthorizedException;
 import org.hswebframework.web.context.ContextKey;
 import org.hswebframework.web.context.ContextUtils;
+import org.hswebframework.web.logger.ReactiveLogger;
 import org.springframework.beans.factory.annotation.Autowired;
 import reactor.core.publisher.Mono;
 
@@ -73,9 +74,11 @@ public class UserTokenReactiveAuthenticationSupplier implements ReactiveAuthenti
                                         .getByToken(t.getToken())
                                         .filter(UserToken::validate))
                                 .map(tokenMono -> tokenMono
-                                        .doOnNext(token->userTokenManager.touch(token.getToken()))
+                                        .doOnNext(token -> userTokenManager.touch(token.getToken()))
                                         .flatMap(token -> get(thirdPartAuthenticationManager.get(token.getType()), token.getUserId())))
-                                .orElseGet(Mono::empty));
+                                .orElseGet(Mono::empty))
+                .flatMap(auth -> ReactiveLogger.mdc("userId", auth.getUser().getId()).thenReturn(auth))
+                ;
 
     }
 }

+ 7 - 0
hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java

@@ -5,10 +5,12 @@ import org.hswebframework.web.authorization.simple.builder.SimpleAuthenticationB
 import org.hswebframework.web.authorization.simple.builder.SimpleDataAccessConfigBuilderFactory;
 import org.hswebframework.web.authorization.token.*;
 import org.hswebframework.web.context.ContextKey;
+import org.hswebframework.web.logger.ReactiveLogger;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import reactor.core.publisher.Mono;
+import reactor.core.publisher.SignalType;
 import reactor.test.StepVerifier;
 
 import java.util.Collections;
@@ -127,12 +129,17 @@ public class AuthenticationTests {
                 return  token.getType();
             }
         };
+
         //获取当前登录用户
         Authentication
                 .currentReactive()
                 .map(Authentication::getUser)
                 .map(User::getId)
+                .doOnEach(ReactiveLogger.on(SignalType.ON_NEXT,(ctx,signal)->{
+                    System.out.println(ctx);
+                }))
                 .subscriberContext(acceptContext(ctx -> ctx.put(ContextKey.of(ParsedToken.class), parsedToken)))
+               // .subscriberContext(ReactiveLogger.start("rid","1"))
                 .as(StepVerifier::create)
                 .expectNext("admin")
                 .verifyComplete();

+ 29 - 6
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/handler/access/DimensionDataAccessHandler.java

@@ -114,6 +114,13 @@ public class DimensionDataAccessHandler implements DataAccessHandler {
                                 DataAccessHandlerContext context,
                                 MappingInfo mappingInfo,
                                 Object id) {
+
+        if (id instanceof Param || id instanceof Entity) {
+
+            applyQueryParam(config, context, id);
+            return id;
+        }
+
         List<Dimension> dimensions = context.getDimensions();
 
         Set<Object> scope = CollectionUtils.isNotEmpty(config.getScope()) ?
@@ -138,11 +145,25 @@ public class DimensionDataAccessHandler implements DataAccessHandler {
         if (id instanceof Publisher) {
             if (id instanceof Mono) {
                 return ((Mono) id)
-                        .flatMap(r -> reactiveCheck.apply(r instanceof Collection ? ((Collection) r) : Collections.singleton(r)))
+                        .flatMap(r -> {
+                            if (r instanceof Param) {
+                                applyQueryParam(config, context, r);
+                                return Mono.just(r);
+                            }
+                            return reactiveCheck.apply(r instanceof Collection ? ((Collection) r) : Collections.singleton(r));
+
+                        })
                         .then((Mono) id);
             }
             if (id instanceof Flux) {
                 return ((Flux) id)
+                        .filter(v -> {
+                            if (v instanceof Param) {
+                                applyQueryParam(config, context, v);
+                                return false;
+                            }
+                            return true;
+                        })
                         .collectList()
                         .flatMap(reactiveCheck)
                         .thenMany((Flux) id);
@@ -272,7 +293,7 @@ public class DimensionDataAccessHandler implements DataAccessHandler {
         MappingInfo mappingInfo = getMappingInfo(context).get(cfg.getScopeType());
 
         //根据结果控制
-        if (context.getDefinition().getPhased() == Phased.after) {
+        if (context.getDefinition().getResources().getPhased() == Phased.after) {
             Object result = context.getParamContext().getInvokeResult();
             Set<Object> scope = CollectionUtils.isNotEmpty(cfg.getScope()) ?
                     cfg.getScope() :
@@ -283,12 +304,14 @@ public class DimensionDataAccessHandler implements DataAccessHandler {
             String property = mappingInfo.getProperty();
 
             if (result instanceof Mono) {
-                context.getParamContext().setInvokeResult(((Mono) result).
-                        filter(data -> hasAccessByProperty(scope, property, data)));
+                context.getParamContext()
+                        .setInvokeResult(((Mono) result).
+                                filter(data -> hasAccessByProperty(scope, property, data)));
                 return true;
             } else if (result instanceof Flux) {
-                context.getParamContext().setInvokeResult(((Flux) result).
-                        filter(data -> hasAccessByProperty(scope, property, data)));
+                context.getParamContext()
+                        .setInvokeResult(((Flux) result).
+                                filter(data -> hasAccessByProperty(scope, property, data)));
                 return true;
             }
             return hasAccessByProperty(scope, property, result);

+ 4 - 1
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/web/UserTokenWebFilter.java

@@ -5,6 +5,7 @@ import org.hswebframework.web.authorization.events.AuthorizationSuccessEvent;
 import org.hswebframework.web.authorization.token.ParsedToken;
 import org.hswebframework.web.authorization.token.UserTokenManager;
 import org.hswebframework.web.context.ContextUtils;
+import org.hswebframework.web.logger.ReactiveLogger;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanPostProcessor;
@@ -42,7 +43,9 @@ public class UserTokenWebFilter implements WebFilter, BeanPostProcessor {
                 .subscriberContext(ContextUtils.acceptContext(ctx ->
                         Flux.fromIterable(parsers)
                                 .flatMap(parser -> parser.parseToken(exchange))
-                                .subscribe(token -> ctx.put(ParsedToken.class, token))));
+                                .subscribe(token -> ctx.put(ParsedToken.class, token))))
+                .subscriberContext(ReactiveLogger.start("requestId", exchange.getRequest().getId()))
+                ;
     }
 
     @EventListener

+ 6 - 1
hsweb-core/src/main/java/org/hswebframework/web/aop/MethodInterceptorHolder.java

@@ -52,14 +52,17 @@ public class MethodInterceptorHolder {
         String[] argNames = nameDiscoverer.getParameterNames(invocation.getMethod());
         Object[] args = invocation.getArguments();
         Map<String, Object> argMap = new LinkedHashMap<>();
+        String[] names = new String[args.length];
         for (int i = 0, len = args.length; i < len; i++) {
-            argMap.put((argNames == null || argNames[i] == null) ? "arg" + i : argNames[i], args[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);
     }
 
@@ -71,6 +74,8 @@ public class MethodInterceptorHolder {
 
     private Object[] arguments;
 
+    private String[] argumentsNames;
+
     private Map<String, Object> namedArguments;
 
 

+ 112 - 0
hsweb-core/src/main/java/org/hswebframework/web/logger/ReactiveLogger.java

@@ -0,0 +1,112 @@
+package org.hswebframework.web.logger;
+
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.MDC;
+import reactor.core.publisher.Mono;
+import reactor.core.publisher.Signal;
+import reactor.core.publisher.SignalType;
+import reactor.util.context.Context;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+@Slf4j
+public class ReactiveLogger {
+
+    private static String CONTEXT_KEY = ReactiveLogger.class.getName();
+
+    public static Function<Context, Context> start(String key, String value) {
+        return start(Collections.singletonMap(key, value));
+    }
+
+    public static Mono<Void> mdc(String key, String value) {
+        return Mono.<Void>empty()
+                .subscriberContext(start(key, value));
+    }
+
+    public static Function<Context, Context> start(Map<String, String> context) {
+        return ctx -> {
+            Optional<Map<String, String>> maybeContextMap = ctx.getOrEmpty(CONTEXT_KEY);
+            if (maybeContextMap.isPresent()) {
+                maybeContextMap.get().putAll(context);
+                return ctx;
+            } else {
+                return ctx.put(CONTEXT_KEY, new LinkedHashMap<>(context));
+            }
+        };
+    }
+
+
+    public static <T> void log(Context context, Consumer<Map<String, String>> logger) {
+        Optional<Map<String, String>> maybeContextMap = context.getOrEmpty(CONTEXT_KEY);
+        if (!maybeContextMap.isPresent()) {
+            logger.accept(new HashMap<>());
+        } else {
+            Map<String, String> ctx = maybeContextMap.get();
+            MDC.setContextMap(ctx);
+            try {
+                logger.accept(ctx);
+            } finally {
+                MDC.clear();
+            }
+        }
+    }
+
+    public static <T> Consumer<Signal<T>> on(SignalType type, BiConsumer<Map<String, String>, Signal<T>> logger) {
+        return signal -> {
+            if (signal.getType() != type) {
+                return;
+            }
+            Optional<Map<String, String>> maybeContextMap
+                    = signal.getContext().getOrEmpty(CONTEXT_KEY);
+            if (!maybeContextMap.isPresent()) {
+                logger.accept(new HashMap<>(), signal);
+            } else {
+                Map<String, String> ctx = maybeContextMap.get();
+                MDC.setContextMap(ctx);
+                try {
+                    logger.accept(ctx, signal);
+                } finally {
+                    MDC.clear();
+                }
+            }
+        };
+    }
+
+    public static Mono<Void> mdc(Consumer<Map<String, String>> consumer) {
+        return Mono.subscriberContext()
+                .doOnNext(ctx -> {
+                    Optional<Map<String, String>> maybeContextMap = ctx.getOrEmpty(CONTEXT_KEY);
+                    if (maybeContextMap.isPresent()) {
+                        consumer.accept(maybeContextMap.get());
+                    } else {
+                        consumer.accept(Collections.emptyMap());
+                        log.warn("logger context is empty,please call publisher.subscriberContext(ReactiveLogger.mdc()) first!");
+                    }
+                })
+                .then();
+    }
+
+    public static <T> Consumer<Signal<T>> onNext(Consumer<T> logger) {
+        return on(SignalType.ON_NEXT, (ctx, signal) -> {
+            logger.accept(signal.get());
+        });
+
+    }
+
+    public static <T> Consumer<Signal<T>> onComplete(Runnable logger) {
+        return on(SignalType.ON_COMPLETE, (ctx, signal) -> {
+            logger.run();
+        });
+    }
+
+    public static <T> Consumer<Signal<T>> onError(Consumer<Throwable> logger) {
+        return on(SignalType.ON_ERROR, (ctx, signal) -> {
+            logger.accept(signal.getThrowable());
+        });
+    }
+
+
+}

+ 33 - 0
hsweb-core/src/test/java/org/hswebframework/web/logger/ReactiveLoggerTest.java

@@ -0,0 +1,33 @@
+package org.hswebframework.web.logger;
+
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import reactor.core.publisher.Flux;
+import reactor.test.StepVerifier;
+
+import java.time.Duration;
+
+import static org.junit.Assert.*;
+
+@Slf4j
+public class ReactiveLoggerTest {
+
+
+    @Test
+    public void test() {
+
+        Flux.range(0, 5)
+                .delayElements(Duration.ofSeconds(2))
+                .flatMap(i -> ReactiveLogger.mdc("requestId", "test").thenReturn(i))
+                .doOnEach(ReactiveLogger.onNext(v -> {
+                    log.info("test:{}", v);
+                }))
+                .subscriberContext(ReactiveLogger.start("r","1"))
+                .as(StepVerifier::create)
+                .expectNextCount(5)
+                .verifyComplete();
+
+
+    }
+
+}

+ 17 - 0
hsweb-logging/hsweb-access-logging-aop/pom.xml

@@ -34,15 +34,32 @@
             <groupId>io.swagger</groupId>
             <artifactId>swagger-annotations</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webflux</artifactId>
+            <optional>true</optional>
         </dependency>
+
         <dependency>
             <groupId>org.hswebframework.web</groupId>
             <artifactId>hsweb-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-authorization-api</artifactId>
+            <version>${project.version}</version>
+            <optional>true</optional>
+        </dependency>
+
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>

+ 3 - 20
hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupport.java

@@ -9,11 +9,13 @@ 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.WebUtils;
+import org.reactivestreams.Publisher;
 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.core.Ordered;
 import org.springframework.util.ClassUtils;
+import reactor.core.publisher.Mono;
 
 import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Method;
@@ -28,9 +30,6 @@ import java.util.List;
  */
 public class AopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor {
 
-    @Autowired(required = false)
-    private final List<AccessLoggerListener> listeners = new ArrayList<>();
-
     @Autowired(required = false)
     private final List<AccessLoggerParser> loggerParsers = new ArrayList<>();
 
@@ -38,28 +37,13 @@ public class AopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor {
     private ApplicationEventPublisher eventPublisher;
 
 
-    public AopAccessLoggerSupport addListener(AccessLoggerListener loggerListener) {
-        if (!listeners.contains(loggerListener)) {
-            listeners.add(loggerListener);
-        }
-        return this;
-    }
-
-    public AopAccessLoggerSupport addParser(AccessLoggerParser parser) {
-        if (!loggerParsers.contains(parser)) {
-            loggerParsers.add(parser);
-        }
-        return this;
-    }
-
     public AopAccessLoggerSupport() {
         setAdvice((MethodInterceptor) methodInvocation -> {
             MethodInterceptorHolder methodInterceptorHolder = MethodInterceptorHolder.create(methodInvocation);
             AccessLoggerInfo info = createLogger(methodInterceptorHolder);
-            Object response;
+            Object response = null;
             try {
                 eventPublisher.publishEvent(new AccessLoggerBeforeEvent(info));
-                listeners.forEach(listener -> listener.onLogBefore(info));
                 response = methodInvocation.proceed();
                 info.setResponse(response);
             } catch (Throwable e) {
@@ -69,7 +53,6 @@ public class AopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor {
                 info.setResponseTime(System.currentTimeMillis());
                 //触发监听
                 eventPublisher.publishEvent(new AccessLoggerAfterEvent(info));
-                listeners.forEach(listener -> listener.onLogger(info));
             }
             return response;
         });

+ 14 - 25
hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/AopAccessLoggerSupportAutoConfiguration.java

@@ -6,6 +6,7 @@ import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
@@ -21,10 +22,17 @@ import org.springframework.context.annotation.Configuration;
 public class AopAccessLoggerSupportAutoConfiguration {
 
     @Bean
+    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
     public AopAccessLoggerSupport aopAccessLoggerSupport() {
         return new AopAccessLoggerSupport();
     }
 
+    @Bean
+    @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
+    public ReactiveAopAccessLoggerSupport reactiveAopAccessLoggerSupport() {
+        return new ReactiveAopAccessLoggerSupport();
+    }
+
     @Bean
     public DefaultAccessLoggerParser defaultAccessLoggerParser(){
         return new DefaultAccessLoggerParser();
@@ -36,29 +44,10 @@ public class AopAccessLoggerSupportAutoConfiguration {
         return new SwaggerAccessLoggerParser();
     }
 
-//    @Bean
-//    public ListenerProcessor listenerProcessor() {
-//        return new ListenerProcessor();
-//    }
-//
-//    public static class ListenerProcessor implements BeanPostProcessor {
-//
-//        @Autowired
-//        private AopAccessLoggerSupport aopAccessLoggerSupport;
-//
-//        @Override
-//        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-//            return bean;
-//        }
-//
-//        @Override
-//        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-//            if (bean instanceof AccessLoggerListener) {
-//                aopAccessLoggerSupport.addListener(((AccessLoggerListener) bean));
-//            }  if (bean instanceof AccessLoggerParser) {
-//                aopAccessLoggerSupport.addParser(((AccessLoggerParser) bean));
-//            }
-//            return bean;
-//        }
-//    }
+
+    @Bean
+    @ConditionalOnClass(name = "org.hswebframework.web.authorization.annotation.Resource")
+    public ResourceAccessLoggerParser resourceAccessLoggerParser(){
+        return new ResourceAccessLoggerParser();
+    }
 }

+ 170 - 0
hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/ReactiveAopAccessLoggerSupport.java

@@ -0,0 +1,170 @@
+package org.hswebframework.web.loggin.aop;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.hswebframework.web.aop.MethodInterceptorHolder;
+import org.hswebframework.web.id.IDGenerator;
+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.events.AccessLoggerAfterEvent;
+import org.hswebframework.web.logging.events.AccessLoggerBeforeEvent;
+import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.util.ClassUtils;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.util.context.Context;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 使用AOP记录访问日志,并触发{@link AccessLoggerListener#onLogger(AccessLoggerInfo)}
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public class ReactiveAopAccessLoggerSupport extends StaticMethodMatcherPointcutAdvisor implements WebFilter {
+
+    @Autowired(required = false)
+    private final List<AccessLoggerParser> loggerParsers = new ArrayList<>();
+
+    @Autowired
+    private ApplicationEventPublisher eventPublisher;
+
+    public ReactiveAopAccessLoggerSupport() {
+        setAdvice((MethodInterceptor) methodInvocation -> {
+            MethodInterceptorHolder methodInterceptorHolder = MethodInterceptorHolder.create(methodInvocation);
+            AccessLoggerInfo info = createLogger(methodInterceptorHolder);
+            Object response = methodInvocation.proceed();
+            if (response instanceof Mono) {
+                return wrapMonoResponse(((Mono) response), info);
+            } else if (response instanceof Flux) {
+                return wrapFluxResponse(((Flux) response), info);
+            }
+            return response;
+        });
+    }
+
+    protected Flux<?> wrapFluxResponse(Flux<?> flux, AccessLoggerInfo loggerInfo) {
+        return Mono.subscriberContext()
+                .<RequestInfo>flatMap(ctx -> Mono.justOrEmpty(ctx.getOrEmpty(RequestInfo.class)))
+                .doOnNext(loggerInfo::putAccessInfo)
+                .thenMany(flux)
+                .doOnError(loggerInfo::setException)
+                .doFinally(f -> {
+                    loggerInfo.setResponseTime(System.currentTimeMillis());
+                    eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo));
+                });
+    }
+
+    protected Mono<?> wrapMonoResponse(Mono<?> mono, AccessLoggerInfo loggerInfo) {
+        return Mono.subscriberContext()
+                .<RequestInfo>flatMap(ctx -> Mono.justOrEmpty(ctx.getOrEmpty(RequestInfo.class)))
+                .doOnNext(loggerInfo::putAccessInfo)
+                .then(mono)
+                .doOnError(loggerInfo::setException)
+                .doOnSuccess(loggerInfo::setResponse)
+                .doFinally(f -> {
+                    loggerInfo.setResponseTime(System.currentTimeMillis());
+                    eventPublisher.publishEvent(new AccessLoggerAfterEvent(loggerInfo));
+                });
+    }
+
+    @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);
+
+        if (define != null) {
+            info.setAction(define.getAction());
+            info.setDescribe(define.getDescribe());
+        }
+
+        Map<String, Object> value = new ConcurrentHashMap<>();
+
+        String[] names = holder.getArgumentsNames();
+
+        Object[] args = holder.getArguments();
+
+        for (int i = 0; i < args.length; i++) {
+            String name = names[i];
+            Object val = args[i];
+            if (val == null) {
+                value.put(name, "null");
+                continue;
+            }
+            if (val instanceof Mono) {
+                args[i] = ((Mono) val)
+                        .doOnNext(param -> {
+                            value.put(name, param);
+                        });
+            } else if (val instanceof Flux) {
+                List<Object> arr = new ArrayList<>();
+                value.put(name, arr);
+                args[i] = ((Flux) val)
+                        .doOnNext(param -> {
+                            arr.add(param);
+                        });
+            } else {
+                value.put(name, val);
+            }
+        }
+
+        info.setParameters(value);
+        info.setTarget(holder.getTarget().getClass());
+        info.setMethod(holder.getMethod());
+        return info;
+
+    }
+
+    @Override
+    public int getOrder() {
+        return Ordered.HIGHEST_PRECEDENCE;
+    }
+
+    @Override
+    public boolean matches(Method method, Class<?> aClass) {
+        return loggerParsers.stream().anyMatch(parser -> parser.support(aClass, method));
+    }
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
+        return chain
+                .filter(exchange)
+                .subscriberContext(Context.of(RequestInfo.class, createAccessInfo(exchange)));
+    }
+
+    private RequestInfo createAccessInfo(ServerWebExchange exchange) {
+        RequestInfo info = new RequestInfo();
+        ServerHttpRequest request = exchange.getRequest();
+        info.setRequestId(request.getId());
+        info.setPath(request.getPath().value());
+        info.setRequestMethod(request.getMethodValue());
+        info.setHeaders(request.getHeaders().toSingleValueMap());
+
+        Optional.ofNullable(request.getRemoteAddress())
+                .map(InetSocketAddress::getAddress)
+                .map(InetAddress::getHostAddress)
+                .ifPresent(info::setIpAddr);
+
+        return info;
+    }
+}

+ 54 - 0
hsweb-logging/hsweb-access-logging-aop/src/main/java/org/hswebframework/web/loggin/aop/ResourceAccessLoggerParser.java

@@ -0,0 +1,54 @@
+package org.hswebframework.web.loggin.aop;
+
+
+import org.hswebframework.web.aop.MethodInterceptorHolder;
+import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.authorization.annotation.ResourceAction;
+import org.hswebframework.web.logging.LoggerDefine;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.util.ClassUtils;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
+public class ResourceAccessLoggerParser implements AccessLoggerParser {
+
+    Set<Class<? extends Annotation>> annotations = new HashSet<>(Arrays.asList(
+            Resource.class, ResourceAction.class
+    ));
+
+    @Override
+    public boolean support(Class clazz, Method method) {
+        Set<Annotation> a1 = AnnotatedElementUtils.findAllMergedAnnotations(method, annotations);
+        Set<Annotation> a2 = AnnotatedElementUtils.findAllMergedAnnotations(clazz, annotations);
+
+
+        return !a1.isEmpty() || !a2.isEmpty();
+    }
+
+    @Override
+    public LoggerDefine parse(MethodInterceptorHolder holder) {
+
+        Set<Annotation> a1 = AnnotatedElementUtils.findAllMergedAnnotations(holder.getMethod(), annotations);
+        Set<Annotation> a2 = AnnotatedElementUtils.findAllMergedAnnotations(ClassUtils.getUserClass(holder.getTarget()), annotations);
+
+        LoggerDefine define = new LoggerDefine();
+
+        Stream.concat(a1.stream(), a2.stream())
+                .forEach(ann -> {
+                    if (ann instanceof ResourceAction) {
+                        define.setAction(((ResourceAction) ann).name());
+                    }
+                    if (ann instanceof Resource) {
+                        define.setDescribe(((Resource) ann).name());
+                    }
+                });
+
+        return define;
+    }
+}

+ 13 - 117
hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/AccessLoggerInfo.java

@@ -1,5 +1,8 @@
 package org.hswebframework.web.logging;
 
+import lombok.Getter;
+import lombok.Setter;
+
 import java.io.PrintWriter;
 import java.io.Serializable;
 import java.io.StringWriter;
@@ -16,6 +19,8 @@ import java.util.function.Function;
  * @author zhouhao
  * @since 3.0
  */
+@Getter
+@Setter
 public class AccessLoggerInfo {
 
     /**
@@ -45,7 +50,7 @@ public class AccessLoggerInfo {
     /**
      * 访问对应的java类
      */
-    private Class target;
+    private Class<?> target;
 
     /**
      * 请求的参数,参数为java方法的参数而不是http参数,key为参数名,value为参数值.
@@ -96,122 +101,13 @@ public class AccessLoggerInfo {
      */
     private Throwable exception;
 
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public String getDescribe() {
-        return describe;
-    }
-
-    public void setDescribe(String describe) {
-        this.describe = describe;
-    }
-
-    public Method getMethod() {
-        return method;
-    }
-
-    public void setMethod(Method method) {
-        this.method = method;
-    }
-
-    public Class getTarget() {
-        return target;
-    }
-
-    public void setTarget(Class target) {
-        this.target = target;
-    }
-
-    public Map<String, Object> getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(Map<String, Object> parameters) {
-        this.parameters = parameters;
-    }
-
-    public String getIp() {
-        return ip;
-    }
-
-    public void setIp(String ip) {
-        this.ip = ip;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public Map<String, String> getHttpHeaders() {
-        return httpHeaders;
-    }
-
-    public void setHttpHeaders(Map<String, String> httpHeaders) {
-        this.httpHeaders = httpHeaders;
-    }
-
-    public String getHttpMethod() {
-        return httpMethod;
-    }
-
-    public void setHttpMethod(String httpMethod) {
-        this.httpMethod = httpMethod;
-    }
-
-    public Object getResponse() {
-        return response;
-    }
-
-    public void setResponse(Object response) {
-        this.response = response;
-    }
-
-    public long getRequestTime() {
-        return requestTime;
-    }
-
-    public void setRequestTime(long requestTime) {
-        this.requestTime = requestTime;
-    }
-
-    public long getResponseTime() {
-        return responseTime;
-    }
-
-    public void setResponseTime(long responseTime) {
-        this.responseTime = responseTime;
-    }
-
-    public Throwable getException() {
-        return exception;
-    }
-
-    public void setException(Throwable exception) {
-        this.exception = exception;
-    }
-
-    public Map<String, Object> toSimpleMap(Function<Object, Serializable> noSerialExchange) {
-        return toSimpleMap(noSerialExchange, new LinkedHashMap<>());
-    }
-
     public Map<String, Object> toSimpleMap(Function<Object, Serializable> objectFilter, Map<String, Object> map) {
         map.put("action", action);
         map.put("describe", describe);
         if (method != null) {
             StringJoiner methodAppender = new StringJoiner(",", method.getName().concat("("), ")");
-            String[] parameterNames = parameters.keySet().toArray(new String[parameters.size()]);
-            Class[] parameterTypes = method.getParameterTypes();
+            String[] parameterNames = parameters.keySet().toArray(new String[0]);
+            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)));
@@ -244,11 +140,11 @@ public class AccessLoggerInfo {
         return map;
     }
 
-    public String getId() {
-        return id;
-    }
 
-    public void setId(String id) {
-        this.id = id;
+    public void putAccessInfo(RequestInfo info){
+        setIp(info.getIpAddr());
+        setHttpMethod(info.getRequestMethod());
+        setHttpHeaders(info.getHeaders());
+        setUrl(info.getPath());
     }
 }

+ 9 - 21
hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/LoggerDefine.java

@@ -1,30 +1,18 @@
 package org.hswebframework.web.logging;
 
 
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
 public class LoggerDefine {
     private String action;
 
     private String describe;
-
-    public LoggerDefine(String action,String describe){
-        this.action=action;
-        this.describe=describe;
-    }
-
-    public String getDescribe() {
-        return describe;
-    }
-
-    public void setAction(String action) {
-        this.action = action;
-    }
-
-    public String getAction() {
-        return action;
-    }
-
-    public void setDescribe(String describe) {
-        this.describe = describe;
-    }
 }
 

+ 25 - 0
hsweb-logging/hsweb-access-logging-api/src/main/java/org/hswebframework/web/logging/RequestInfo.java

@@ -0,0 +1,25 @@
+package org.hswebframework.web.logging;
+
+import lombok.*;
+
+import java.util.Map;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RequestInfo {
+
+    private String requestId;
+
+    private String ipAddr;
+
+    private String path;
+
+    private String requestMethod;
+
+    private Map<String,String> headers;
+
+
+}