woody 1 rok pred
rodič
commit
fec3c37027
36 zmenil súbory, kde vykonal 478 pridanie a 500 odobranie
  1. 1 1
      framework-base/src/main/java/com/chelvc/framework/base/config/BeanFullnameGenerator.java
  2. 23 15
      framework-base/src/main/java/com/chelvc/framework/base/config/ContextConfigurer.java
  3. 160 0
      framework-base/src/main/java/com/chelvc/framework/base/context/DefaultSessionFactory.java
  4. 0 1
      framework-base/src/main/java/com/chelvc/framework/base/context/LoggingContextHolder.java
  5. 1 1
      framework-base/src/main/java/com/chelvc/framework/base/context/Result.java
  6. 22 1
      framework-base/src/main/java/com/chelvc/framework/base/context/Session.java
  7. 15 205
      framework-base/src/main/java/com/chelvc/framework/base/context/SessionContextHolder.java
  8. 19 0
      framework-base/src/main/java/com/chelvc/framework/base/context/SessionFactory.java
  9. 0 1
      framework-base/src/main/java/com/chelvc/framework/base/context/ThreadContextHolder.java
  10. 0 1
      framework-base/src/main/java/com/chelvc/framework/base/context/VersionContextHolder.java
  11. 13 3
      framework-base/src/main/java/com/chelvc/framework/base/interceptor/BufferedRequestWrapper.java
  12. 1 1
      framework-base/src/main/java/com/chelvc/framework/base/interceptor/DefaultResponseWrapper.java
  13. 24 20
      framework-base/src/main/java/com/chelvc/framework/base/interceptor/GlobalExceptionInterceptor.java
  14. 1 1
      framework-base/src/main/java/com/chelvc/framework/base/interceptor/ResponseWrapper.java
  15. 5 25
      framework-base/src/main/java/com/chelvc/framework/base/util/HttpUtils.java
  16. 0 20
      framework-common/src/main/java/com/chelvc/framework/common/exception/ParameterInvalidException.java
  17. 77 126
      framework-common/src/main/java/com/chelvc/framework/common/util/FileUtils.java
  18. 3 2
      framework-database/src/main/java/com/chelvc/framework/database/interceptor/DatabaseExceptionInterceptor.java
  19. 2 2
      framework-dubbo/src/main/java/com/chelvc/framework/dubbo/interceptor/DubboConsumerInterceptor.java
  20. 2 2
      framework-dubbo/src/main/java/com/chelvc/framework/dubbo/interceptor/DubboProviderInterceptor.java
  21. 1 1
      framework-feign/src/main/java/com/chelvc/framework/feign/interceptor/FeignExceptionInterceptor.java
  22. 1 1
      framework-feign/src/main/java/com/chelvc/framework/feign/interceptor/FeignHeaderInterceptor.java
  23. 3 3
      framework-kafka/src/main/java/com/chelvc/framework/kafka/context/KafkaContextHolder.java
  24. 12 0
      framework-oauth/src/main/java/com/chelvc/framework/oauth/context/OAuthContextHolder.java
  25. 4 12
      framework-oauth/src/main/java/com/chelvc/framework/oauth/token/RedisTokenValidator.java
  26. 5 5
      framework-redis/src/main/java/com/chelvc/framework/redis/context/RedisContextHolder.java
  27. 1 1
      framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/consumer/MultipleRocketMQListenerContainer.java
  28. 1 1
      framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/consumer/RocketMQListener.java
  29. 4 8
      framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/context/RocketMQContextHolder.java
  30. 22 7
      framework-security/src/main/java/com/chelvc/framework/security/interceptor/ControllerCryptoInterceptor.java
  31. 1 1
      framework-security/src/main/java/com/chelvc/framework/security/interceptor/SecurityExceptionInterceptor.java
  32. 14 12
      framework-security/src/main/java/com/chelvc/framework/security/interceptor/SecurityValidateInterceptor.java
  33. 7 3
      framework-upload/src/main/java/com/chelvc/framework/upload/UploadHandler.java
  34. 23 9
      framework-upload/src/main/java/com/chelvc/framework/upload/support/DelegatingUploadHandler.java
  35. 5 4
      framework-upload/src/main/java/com/chelvc/framework/upload/support/SimpleUploadHandler.java
  36. 5 4
      framework-upload/src/main/java/com/chelvc/framework/upload/support/TencentUploadHandler.java

+ 1 - 1
framework-base/src/main/java/com/chelvc/framework/base/context/BeanFullnameGenerator.java → framework-base/src/main/java/com/chelvc/framework/base/config/BeanFullnameGenerator.java

@@ -1,4 +1,4 @@
-package com.chelvc.framework.base.context;
+package com.chelvc.framework.base.config;
 
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.context.annotation.AnnotationBeanNameGenerator;

+ 23 - 15
framework-base/src/main/java/com/chelvc/framework/base/config/ResponseWrappingConfigurer.java → framework-base/src/main/java/com/chelvc/framework/base/config/ContextConfigurer.java

@@ -4,6 +4,8 @@ import java.util.Collections;
 import java.util.List;
 import javax.annotation.PostConstruct;
 
+import com.chelvc.framework.base.context.DefaultSessionFactory;
+import com.chelvc.framework.base.context.SessionFactory;
 import com.chelvc.framework.base.interceptor.DefaultResponseWrapper;
 import com.chelvc.framework.base.interceptor.ResponseWrapper;
 import com.chelvc.framework.base.interceptor.ResponseWrappingInterceptor;
@@ -26,9 +28,29 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBody
  */
 @Configuration
 @RequiredArgsConstructor(onConstructor = @__(@Autowired))
-public class ResponseWrappingConfigurer {
+public class ContextConfigurer {
     private final RequestMappingHandlerAdapter handlerAdapter;
 
+    @PostConstruct
+    public void initialize() {
+        ResponseWrappingInterceptor interceptor = this.responseWrappingInterceptor();
+        List<HandlerMethodReturnValueHandler> handlers = this.handlerAdapter.getReturnValueHandlers();
+        if (CollectionUtils.isEmpty(handlers)) {
+            this.handlerAdapter.setReturnValueHandlers(Collections.singletonList(interceptor));
+            return;
+        }
+        List<HandlerMethodReturnValueHandler> replaces = Lists.newArrayListWithCapacity(handlers.size() + 1);
+        replaces.add(interceptor);
+        replaces.addAll(handlers);
+        this.handlerAdapter.setReturnValueHandlers(replaces);
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(SessionFactory.class)
+    public SessionFactory sessionFactory() {
+        return new DefaultSessionFactory();
+    }
+
     @Bean
     @ConditionalOnMissingBean(ResponseWrapper.class)
     public ResponseWrapper responseWrapper() {
@@ -43,18 +65,4 @@ public class ResponseWrappingConfigurer {
                         .map(handler -> (RequestResponseBodyMethodProcessor) handler).findAny().orElse(null);
         return new ResponseWrappingInterceptor(this.responseWrapper(), processor);
     }
-
-    @PostConstruct
-    public void initialize() {
-        ResponseWrappingInterceptor interceptor = this.responseWrappingInterceptor();
-        List<HandlerMethodReturnValueHandler> handlers = this.handlerAdapter.getReturnValueHandlers();
-        if (CollectionUtils.isEmpty(handlers)) {
-            this.handlerAdapter.setReturnValueHandlers(Collections.singletonList(interceptor));
-            return;
-        }
-        List<HandlerMethodReturnValueHandler> replaces = Lists.newArrayListWithCapacity(handlers.size() + 1);
-        replaces.add(interceptor);
-        replaces.addAll(handlers);
-        this.handlerAdapter.setReturnValueHandlers(replaces);
-    }
 }

+ 160 - 0
framework-base/src/main/java/com/chelvc/framework/base/context/DefaultSessionFactory.java

@@ -0,0 +1,160 @@
+package com.chelvc.framework.base.context;
+
+import java.util.Objects;
+import javax.servlet.http.HttpServletRequest;
+
+import com.chelvc.framework.base.util.HttpUtils;
+import com.chelvc.framework.common.model.Platform;
+import com.chelvc.framework.common.model.Terminal;
+import com.chelvc.framework.common.util.StringUtils;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Session对象工厂默认实现
+ *
+ * @author Woody
+ * @date 2024/4/18
+ */
+@Slf4j
+public class DefaultSessionFactory implements SessionFactory {
+    /**
+     * 获取客户端身份标识
+     *
+     * @param request Http请求对象
+     * @return 身份标识
+     */
+    protected Long getId(@NonNull HttpServletRequest request) {
+        try {
+            return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_ID), Long::parseLong);
+        } catch (Exception e) {
+            log.warn("Id convert failed: {}", e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 获取客户端主机地址
+     *
+     * @param request Http请求对象
+     * @return 主机地址
+     */
+    protected String getHost(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(HttpUtils.getHost(request), (String) null);
+    }
+
+    /**
+     * 获取应用范围
+     *
+     * @param request Http请求对象
+     * @return 应用范围
+     */
+    protected String getScope(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_SCOPE), (String) null);
+    }
+
+    /**
+     * 获取客户端设备标识
+     *
+     * @param request Http请求对象
+     * @return 设备标识
+     */
+    protected String getDevice(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_DEVICE), (String) null);
+    }
+
+    /**
+     * 获取客户端渠道来源
+     *
+     * @param request Http请求对象
+     * @return 渠道来源
+     */
+    protected String getChannel(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_CHANNEL), (String) null);
+    }
+
+    /**
+     * 获取客户端平台标识
+     *
+     * @param request Http请求对象
+     * @return 平台标识
+     */
+    protected Platform getPlatform(@NonNull HttpServletRequest request) {
+        try {
+            return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_PLATFORM), Platform::valueOf);
+        } catch (Exception e) {
+            log.warn("Platform convert failed: {}", e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 获取客户端终端
+     *
+     * @param request Http请求对象
+     * @return 终端标识
+     */
+    protected Terminal getTerminal(@NonNull HttpServletRequest request) {
+        try {
+            return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_TERMINAL), Terminal::valueOf);
+        } catch (Exception e) {
+            log.warn("Terminal convert failed: {}", e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 获取客户端版本号
+     *
+     * @param request Http请求对象
+     * @return 版本号
+     */
+    protected String getVersion(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_VERSION), (String) null);
+    }
+
+    /**
+     * 是否是匿名用户
+     *
+     * @param request Http请求对象
+     * @return true/false
+     */
+    protected boolean isAnonymous(@NonNull HttpServletRequest request) {
+        String anonymous = request.getHeader(SessionContextHolder.HEADER_ANONYMOUS);
+        return StringUtils.isEmpty(anonymous) || Objects.equals(anonymous, StringUtils.TRUE);
+    }
+
+    /**
+     * 获取请求时间戳
+     *
+     * @param request Http请求对象
+     * @return 时间戳
+     */
+    protected Long getTimestamp(@NonNull HttpServletRequest request) {
+        try {
+            return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_TIMESTAMP), Long::parseLong);
+        } catch (Exception e) {
+            log.warn("Timestamp convert failed: {}", e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 获取设备指纹
+     *
+     * @param request Http请求对象
+     * @return 设备指纹
+     */
+    protected String getFingerprint(@NonNull HttpServletRequest request) {
+        return StringUtils.ifEmpty(request.getHeader(SessionContextHolder.HEADER_FINGERPRINT), (String) null);
+    }
+
+    @Override
+    public Session build(@NonNull HttpServletRequest request) {
+        return Session.builder().id(this.getId(request)).host(this.getHost(request)).scope(this.getScope(request))
+                .device(this.getDevice(request)).channel(this.getChannel(request)).platform(this.getPlatform(request))
+                .terminal(this.getTerminal(request)).version(this.getVersion(request))
+                .fingerprint(this.getFingerprint(request)).anonymous(this.isAnonymous(request))
+                .timestamp(this.getTimestamp(request)).build();
+    }
+}

+ 0 - 1
framework-base/src/main/java/com/chelvc/framework/base/context/LoggingContextHolder.java

@@ -3,7 +3,6 @@ package com.chelvc.framework.base.context;
 import javax.servlet.http.HttpServletRequest;
 
 import com.chelvc.framework.common.model.Platform;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.model.Terminal;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;

+ 1 - 1
framework-common/src/main/java/com/chelvc/framework/common/model/Result.java → framework-base/src/main/java/com/chelvc/framework/base/context/Result.java

@@ -1,4 +1,4 @@
-package com.chelvc.framework.common.model;
+package com.chelvc.framework.base.context;
 
 import java.io.Serializable;
 import java.util.Objects;

+ 22 - 1
framework-common/src/main/java/com/chelvc/framework/common/model/Session.java → framework-base/src/main/java/com/chelvc/framework/base/context/Session.java

@@ -1,11 +1,14 @@
-package com.chelvc.framework.common.model;
+package com.chelvc.framework.base.context;
 
 import java.io.Serializable;
 
+import com.chelvc.framework.common.model.Platform;
+import com.chelvc.framework.common.model.Terminal;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
+import lombok.NonNull;
 
 /**
  * 会话信息
@@ -18,6 +21,11 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @AllArgsConstructor
 public class Session implements Serializable {
+    /**
+     * 会话信息命名
+     */
+    public static final String NAMING = "session";
+
     /**
      * 主体标识
      */
@@ -72,4 +80,17 @@ public class Session implements Serializable {
      * 请求时间戳
      */
     private Long timestamp;
+
+    /**
+     * 初始化会话主体信息
+     *
+     * @param id        主体标识
+     * @param scope     应用范围
+     * @param anonymous 是否匿名
+     */
+    void initializePrincipal(@NonNull Long id, @NonNull String scope, boolean anonymous) {
+        this.id = id;
+        this.scope = scope;
+        this.anonymous = anonymous;
+    }
 }

+ 15 - 205
framework-base/src/main/java/com/chelvc/framework/base/context/SessionContextHolder.java

@@ -4,24 +4,22 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayDeque;
 import java.util.Deque;
-import java.util.Objects;
 import java.util.function.Function;
 import javax.servlet.ServletRequestEvent;
 import javax.servlet.ServletRequestListener;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import com.chelvc.framework.base.util.HttpUtils;
 import com.chelvc.framework.common.model.Platform;
-import com.chelvc.framework.common.model.Result;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.model.Terminal;
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
 import com.fasterxml.jackson.core.JsonEncoding;
 import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.stereotype.Component;
@@ -36,12 +34,8 @@ import org.springframework.web.context.request.ServletRequestAttributes;
  */
 @Slf4j
 @Component
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
 public class SessionContextHolder implements ServletRequestListener {
-    /**
-     * 会话上下文名称
-     */
-    public static final String NAME = "session";
-
     /**
      * 身份标识请求头
      */
@@ -87,21 +81,11 @@ public class SessionContextHolder implements ServletRequestListener {
      */
     public static final String HEADER_TIMESTAMP = "timestamp";
 
-    /**
-     * 签名信息请求头
-     */
-    public static final String HEADER_SIGNATURE = "signature";
-
     /**
      * 设备指纹请求头
      */
     public static final String HEADER_FINGERPRINT = "fingerprint";
 
-    /**
-     * 认证信息请求头
-     */
-    public static final String HEADER_AUTHORIZATION = "authorization";
-
     /**
      * 空会话对象实例
      */
@@ -112,6 +96,8 @@ public class SessionContextHolder implements ServletRequestListener {
      */
     private static final ThreadLocal<Deque<Session>> SESSION_CONTEXT = ThreadLocal.withInitial(ArrayDeque::new);
 
+    private final SessionFactory sessionFactory;
+
     /**
      * 获取会话信息
      *
@@ -148,26 +134,26 @@ public class SessionContextHolder implements ServletRequestListener {
     }
 
     /**
-     * 初始化会话信息
+     * 设置会话信息,如果当前已存在会话则更新会话主体信息
      *
      * @param id        主体标识
      * @param scope     应用范围
      * @param anonymous 是否匿名
      * @return 会话信息
      */
-    public static Session initializeSession(@NonNull Long id, @NonNull String scope, boolean anonymous) {
+    public static Session setSession(@NonNull Long id, @NonNull String scope, boolean anonymous) {
         Deque<Session> deque = SESSION_CONTEXT.get();
-        Session session, original = deque.poll();
-        if (original == null || original == EMPTY_SESSION) {
+        Session session = deque.peek();
+        if (session == null || session == EMPTY_SESSION) {
+            if (session != null) {
+                deque.poll();
+            }
             session = Session.builder().id(id).scope(scope).anonymous(anonymous)
                     .timestamp(System.currentTimeMillis()).build();
+            deque.push(session);
         } else {
-            session = Session.builder().id(id).scope(scope).anonymous(anonymous).host(original.getHost())
-                    .device(original.getDevice()).channel(original.getChannel()).platform(original.getPlatform())
-                    .terminal(original.getTerminal()).version(original.getVersion())
-                    .fingerprint(original.getFingerprint()).timestamp(original.getTimestamp()).build();
+            session.initializePrincipal(id, scope, anonymous);
         }
-        deque.push(session);
         return session;
     }
 
@@ -180,21 +166,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getId);
     }
 
-    /**
-     * 获取客户端身份标识
-     *
-     * @param request Http请求对象
-     * @return 身份标识
-     */
-    public static Long getId(@NonNull HttpServletRequest request) {
-        try {
-            return StringUtils.ifEmpty(request.getHeader(HEADER_ID), Long::parseLong);
-        } catch (Exception e) {
-            log.warn("Id convert failed: {}", e.getMessage());
-        }
-        return null;
-    }
-
     /**
      * 获取当前会话请求地址
      *
@@ -204,16 +175,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getHost);
     }
 
-    /**
-     * 获取客户端主机地址
-     *
-     * @param request Http请求对象
-     * @return 主机地址
-     */
-    public static String getHost(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(HttpUtils.getHost(request), (String) null);
-    }
-
     /**
      * 获取应用范围
      *
@@ -223,16 +184,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getScope);
     }
 
-    /**
-     * 获取应用范围
-     *
-     * @param request Http请求对象
-     * @return 应用范围
-     */
-    public static String getScope(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_SCOPE), (String) null);
-    }
-
     /**
      * 获取当前会话设备标识
      *
@@ -242,16 +193,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getDevice);
     }
 
-    /**
-     * 获取客户端设备标识
-     *
-     * @param request Http请求对象
-     * @return 设备标识
-     */
-    public static String getDevice(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_DEVICE), (String) null);
-    }
-
     /**
      * 获取当前会话渠道来源
      *
@@ -261,16 +202,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getChannel);
     }
 
-    /**
-     * 获取客户端渠道来源
-     *
-     * @param request Http请求对象
-     * @return 渠道来源
-     */
-    public static String getChannel(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_CHANNEL), (String) null);
-    }
-
     /**
      * 获取当前会话平台信息
      *
@@ -280,21 +211,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getPlatform);
     }
 
-    /**
-     * 获取客户端平台标识
-     *
-     * @param request Http请求对象
-     * @return 平台标识
-     */
-    public static Platform getPlatform(@NonNull HttpServletRequest request) {
-        try {
-            return StringUtils.ifEmpty(request.getHeader(HEADER_PLATFORM), Platform::valueOf);
-        } catch (Exception e) {
-            log.warn("Platform convert failed: {}", e.getMessage());
-        }
-        return null;
-    }
-
     /**
      * 获取当前会话终端信息
      *
@@ -304,21 +220,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getTerminal);
     }
 
-    /**
-     * 获取客户端终端
-     *
-     * @param request Http请求对象
-     * @return 终端标识
-     */
-    public static Terminal getTerminal(@NonNull HttpServletRequest request) {
-        try {
-            return StringUtils.ifEmpty(request.getHeader(HEADER_TERMINAL), Terminal::valueOf);
-        } catch (Exception e) {
-            log.warn("Terminal convert failed: {}", e.getMessage());
-        }
-        return null;
-    }
-
     /**
      * 获取当前会话版本信息
      *
@@ -328,16 +229,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getVersion);
     }
 
-    /**
-     * 获取客户端版本号
-     *
-     * @param request Http请求对象
-     * @return 版本号
-     */
-    public static String getVersion(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_VERSION), (String) null);
-    }
-
     /**
      * 是否是匿名用户
      *
@@ -348,17 +239,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return session == null || session.isAnonymous();
     }
 
-    /**
-     * 是否是匿名用户
-     *
-     * @param request Http请求对象
-     * @return true/false
-     */
-    public static boolean isAnonymous(@NonNull HttpServletRequest request) {
-        String anonymous = request.getHeader(HEADER_ANONYMOUS);
-        return StringUtils.isEmpty(anonymous) || Objects.equals(anonymous, StringUtils.TRUE);
-    }
-
     /**
      * 获取请求时间戳
      *
@@ -368,40 +248,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getTimestamp);
     }
 
-    /**
-     * 获取请求时间戳
-     *
-     * @param request Http请求对象
-     * @return 时间戳
-     */
-    public static Long getTimestamp(@NonNull HttpServletRequest request) {
-        try {
-            return StringUtils.ifEmpty(request.getHeader(HEADER_TIMESTAMP), Long::parseLong);
-        } catch (Exception e) {
-            log.warn("Timestamp convert failed: {}", e.getMessage());
-        }
-        return null;
-    }
-
-    /**
-     * 获取签名信息
-     *
-     * @return 签名信息
-     */
-    public static String getSignature() {
-        return ObjectUtils.ifNull(getRequest(), SessionContextHolder::getSignature, () -> null);
-    }
-
-    /**
-     * 获取签名信息
-     *
-     * @param request Http请求对象
-     * @return 签名信息
-     */
-    public static String getSignature(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_SIGNATURE), (String) null);
-    }
-
     /**
      * 获取设备指纹
      *
@@ -411,36 +257,6 @@ public class SessionContextHolder implements ServletRequestListener {
         return ObjectUtils.ifNull(getSession(false), Session::getFingerprint);
     }
 
-    /**
-     * 获取设备指纹
-     *
-     * @param request Http请求对象
-     * @return 设备指纹
-     */
-    public static String getFingerprint(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_FINGERPRINT), (String) null);
-    }
-
-    /**
-     * 获取认证信息
-     *
-     * @return 认证信息
-     */
-    public static String getAuthorization() {
-        HttpServletRequest request = getRequest();
-        return request == null ? null : getAuthorization(request);
-    }
-
-    /**
-     * 获取认证信息
-     *
-     * @param request Http请求对象
-     * @return 认证信息
-     */
-    public static String getAuthorization(@NonNull HttpServletRequest request) {
-        return StringUtils.ifEmpty(request.getHeader(HEADER_AUTHORIZATION), (String) null);
-    }
-
     /**
      * 获取当前请求对象
      *
@@ -576,7 +392,6 @@ public class SessionContextHolder implements ServletRequestListener {
         output.flush();
     }
 
-
     /**
      * 清空上下文信息
      */
@@ -590,12 +405,7 @@ public class SessionContextHolder implements ServletRequestListener {
 
     @Override
     public void requestInitialized(ServletRequestEvent event) {
-        HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
-        Session session = Session.builder().id(getId(request)).host(getHost(request)).scope(getScope(request))
-                .device(getDevice(request)).channel(getChannel(request)).platform(getPlatform(request))
-                .terminal(getTerminal(request)).version(getVersion(request)).fingerprint(getFingerprint(request))
-                .anonymous(isAnonymous(request)).timestamp(getTimestamp(request)).build();
-        setSession(session);
+        setSession(this.sessionFactory.build((HttpServletRequest) event.getServletRequest()));
     }
 
     @Override

+ 19 - 0
framework-base/src/main/java/com/chelvc/framework/base/context/SessionFactory.java

@@ -0,0 +1,19 @@
+package com.chelvc.framework.base.context;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Session对象工厂接口
+ *
+ * @author Woody
+ * @date 2024/4/18
+ */
+public interface SessionFactory {
+    /**
+     * 构建Session对象实例
+     *
+     * @param request Http请求对象
+     * @return Session对象实例
+     */
+    Session build(HttpServletRequest request);
+}

+ 0 - 1
framework-base/src/main/java/com/chelvc/framework/base/context/ThreadContextHolder.java

@@ -8,7 +8,6 @@ import java.util.concurrent.ForkJoinPool;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.ThreadUtils;
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;

+ 0 - 1
framework-base/src/main/java/com/chelvc/framework/base/context/VersionContextHolder.java

@@ -1,6 +1,5 @@
 package com.chelvc.framework.base.context;
 
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.model.Terminal;
 import com.chelvc.framework.common.model.Version;
 import com.chelvc.framework.common.util.ObjectUtils;

+ 13 - 3
framework-base/src/main/java/com/chelvc/framework/base/interceptor/BufferedRequestWrapper.java

@@ -10,8 +10,9 @@ import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 
-import com.chelvc.framework.base.util.HttpUtils;
+import com.chelvc.framework.common.util.FileUtils;
 import lombok.NonNull;
+import org.apache.commons.codec.binary.Base64;
 
 /**
  * 可缓存请求体的请求包装器实现
@@ -43,7 +44,7 @@ public class BufferedRequestWrapper extends HttpServletRequestWrapper {
             if (input instanceof BufferedServletInputStream) {
                 return ((BufferedServletInputStream) input).body;
             }
-            return HttpUtils.getBody(input);
+            return FileUtils.getBytes(input);
         }
     }
 
@@ -74,12 +75,21 @@ public class BufferedRequestWrapper extends HttpServletRequestWrapper {
          *
          * @return 请求体字节数组
          */
-        public byte[] getBody() {
+        public byte[] body() {
             byte[] copy = new byte[this.body.length];
             System.arraycopy(this.body, 0, copy, 0, this.body.length);
             return copy;
         }
 
+        /**
+         * 获取请求体base64解码
+         *
+         * @return 请求体字节数组
+         */
+        public byte[] decodeBase64() {
+            return Base64.decodeBase64(this.body);
+        }
+
         @Override
         public int read() throws IOException {
             return this.delegate.read();

+ 1 - 1
framework-base/src/main/java/com/chelvc/framework/base/interceptor/DefaultResponseWrapper.java

@@ -1,7 +1,7 @@
 package com.chelvc.framework.base.interceptor;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
-import com.chelvc.framework.common.model.Result;
+import com.chelvc.framework.base.context.Result;
 import org.springframework.core.MethodParameter;
 import org.springframework.web.context.request.NativeWebRequest;
 

+ 24 - 20
framework-base/src/main/java/com/chelvc/framework/base/interceptor/GlobalExceptionInterceptor.java

@@ -14,10 +14,10 @@ import javax.validation.ValidationException;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.LoggingContextHolder;
+import com.chelvc.framework.base.context.Result;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.exception.FrameworkException;
 import com.chelvc.framework.common.exception.ParameterInvalidException;
-import com.chelvc.framework.common.model.Result;
 import com.chelvc.framework.common.util.ErrorUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -147,36 +147,40 @@ public class GlobalExceptionInterceptor extends AbstractErrorController {
         if (e instanceof HttpMessageNotReadableException) {
             Throwable cause = e.getCause();
             if (cause instanceof InvalidFormatException) {
-                return ParameterInvalidException.result(this.format((InvalidFormatException) cause));
+                return Result.of(ParameterInvalidException.CODE, this.format((InvalidFormatException) cause),
+                        ApplicationContextHolder.getMessage("Parameter.Invalid"));
             }
             return Result.of(HttpStatus.BAD_REQUEST.name(), null,
                     ApplicationContextHolder.getMessage("Request.Invalid"));
         } else if (e instanceof MissingPathVariableException) {
-            return ParameterInvalidException.result(ImmutableMap.of(
-                    ((MissingPathVariableException) e).getVariableName(), e.getMessage()
-            ));
+            return Result.of(ParameterInvalidException.CODE,
+                    ImmutableMap.of(((MissingPathVariableException) e).getVariableName(), e.getMessage()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof MissingMatrixVariableException) {
-            return ParameterInvalidException.result(ImmutableMap.of(
-                    ((MissingMatrixVariableException) e).getVariableName(), e.getMessage()
-            ));
+            return Result.of(ParameterInvalidException.CODE,
+                    ImmutableMap.of(((MissingMatrixVariableException) e).getVariableName(), e.getMessage()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof MissingServletRequestParameterException) {
-            return ParameterInvalidException.result(ImmutableMap.of(
-                    ((MissingServletRequestParameterException) e).getParameterName(), e.getMessage()
-            ));
+            return Result.of(ParameterInvalidException.CODE,
+                    ImmutableMap.of(((MissingServletRequestParameterException) e).getParameterName(), e.getMessage()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof BindException) {
-            return ParameterInvalidException.result(this.format(((BindException) e).getBindingResult()));
+            return Result.of(ParameterInvalidException.CODE, this.format(((BindException) e).getBindingResult()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof ConstraintViolationException) {
-            return ParameterInvalidException.result(this.format((ConstraintViolationException) e));
+            return Result.of(ParameterInvalidException.CODE, this.format((ConstraintViolationException) e),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof MethodArgumentNotValidException) {
-            return ParameterInvalidException.result(
-                    this.format(((MethodArgumentNotValidException) e).getBindingResult())
-            );
+            return Result.of(ParameterInvalidException.CODE,
+                    this.format(((MethodArgumentNotValidException) e).getBindingResult()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof MethodArgumentTypeMismatchException) {
-            return ParameterInvalidException.result(this.format((MethodArgumentTypeMismatchException) e));
+            return Result.of(ParameterInvalidException.CODE, this.format((MethodArgumentTypeMismatchException) e),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof MissingServletRequestPartException) {
-            return ParameterInvalidException.result(ImmutableMap.of(
-                    ((MissingServletRequestPartException) e).getRequestPartName(), e.getMessage()
-            ));
+            return Result.of(ParameterInvalidException.CODE,
+                    ImmutableMap.of(((MissingServletRequestPartException) e).getRequestPartName(), e.getMessage()),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         } else if (e instanceof ValidationException || e instanceof TypeMismatchException
                 || e instanceof MultipartException || e instanceof HttpMessageConversionException
                 || e instanceof ServletRequestBindingException || e instanceof HttpRequestMethodNotSupportedException

+ 1 - 1
framework-base/src/main/java/com/chelvc/framework/base/interceptor/ResponseWrapper.java

@@ -1,6 +1,6 @@
 package com.chelvc.framework.base.interceptor;
 
-import com.chelvc.framework.common.model.Result;
+import com.chelvc.framework.base.context.Result;
 import org.springframework.core.MethodParameter;
 import org.springframework.web.context.request.NativeWebRequest;
 

+ 5 - 25
framework-base/src/main/java/com/chelvc/framework/base/util/HttpUtils.java

@@ -1,6 +1,5 @@
 package com.chelvc.framework.base.util;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -25,6 +24,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import com.chelvc.framework.base.interceptor.BufferedRequestWrapper;
+import com.chelvc.framework.common.util.FileUtils;
 import com.chelvc.framework.common.util.HostUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -177,31 +177,11 @@ public final class HttpUtils {
      */
     public static byte[] getBody(@NonNull HttpServletRequest request) throws IOException {
         try (InputStream input = request.getInputStream()) {
-            return getBody(input);
-        }
-    }
-
-    /**
-     * 获取Body请求参数
-     *
-     * @param input 输入流
-     * @return 请求体字节数组
-     * @throws IOException I/O异常
-     */
-    public static byte[] getBody(@NonNull InputStream input) throws IOException {
-        // 如果请求体已缓存则直接获取
-        if (input instanceof BufferedRequestWrapper.BufferedServletInputStream) {
-            return ((BufferedRequestWrapper.BufferedServletInputStream) input).getBody();
-        }
-
-        // 从请求输入流中读取请求体
-        int n;
-        byte[] buffer = new byte[1024];
-        ByteArrayOutputStream output = new ByteArrayOutputStream(Math.max(32, input.available()));
-        while ((n = input.read(buffer)) != -1) {
-            output.write(buffer, 0, n);
+            if (input instanceof BufferedRequestWrapper.BufferedServletInputStream) {
+                return ((BufferedRequestWrapper.BufferedServletInputStream) input).body();
+            }
+            return FileUtils.getBytes(input);
         }
-        return output.toByteArray();
     }
 
     /**

+ 0 - 20
framework-common/src/main/java/com/chelvc/framework/common/exception/ParameterInvalidException.java

@@ -2,7 +2,6 @@ package com.chelvc.framework.common.exception;
 
 import java.util.Map;
 
-import com.chelvc.framework.common.model.Result;
 import com.google.common.collect.ImmutableMap;
 import lombok.NonNull;
 
@@ -33,23 +32,4 @@ public class ParameterInvalidException extends FrameworkException {
     public ParameterInvalidException(@NonNull Map<String, String> errors, Throwable cause) {
         super(CODE, errors, String.valueOf(errors), cause);
     }
-
-    /**
-     * 将参数无效异常转换成结果对象
-     *
-     * @return 结果对象实例
-     */
-    public Result<?> result() {
-        return Result.of(CODE, this.getData(), "Invalid parameter");
-    }
-
-    /**
-     * 构建参数无效异常结果
-     *
-     * @param errors 参数异常映射表
-     * @return 结果对象实例
-     */
-    public static Result<?> result(@NonNull Map<String, String> errors) {
-        return Result.of(CODE, errors, "Invalid parameter");
-    }
 }

+ 77 - 126
framework-common/src/main/java/com/chelvc/framework/common/util/FileUtils.java

@@ -4,6 +4,7 @@ import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -118,20 +119,6 @@ public final class FileUtils {
         return separator < 0 ? null : StringUtils.ifEmpty(filename.substring(separator + 1), (String) null);
     }
 
-    /**
-     * 获取输入流内容长度
-     *
-     * @param stream 输入流对象实例
-     * @return 内容长度
-     */
-    public static long getLength(@NonNull InputStream stream) {
-        try {
-            return stream.available();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     /**
      * 图片压缩
      *
@@ -147,70 +134,81 @@ public final class FileUtils {
     }
 
     /**
-     * 读取文件内容
+     * 读取文件
      *
-     * @param file 文件对象
-     * @return 文件内容
+     * @param file     文件对象
+     * @param consumer 文件内容消费者
+     * @throws IOException I/O异常
      */
-    public static String read(@NonNull File file) {
-        try {
-            return read(new FileReader(file));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+    public static void lines(@NonNull File file, @NonNull Consumer<String> consumer) throws IOException {
+        lines(new FileReader(file), consumer);
     }
 
     /**
-     * 读取文件内容
+     * 读取文件行
      *
-     * @param file     文件对象
+     * @param in       文件读取处理器
      * @param consumer 文件内容消费者
+     * @throws IOException I/O异常
      */
-    public static void read(@NonNull File file, @NonNull Consumer<String> consumer) {
-        try {
-            read(new FileReader(file), consumer);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+    public static void lines(@NonNull Reader in, @NonNull Consumer<String> consumer) throws IOException {
+        try (BufferedReader reader = new BufferedReader(in)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                consumer.accept(line);
+            }
         }
     }
 
     /**
-     * 读取文件内容
+     * 读取文件字节数组
      *
-     * @param file 文件路径
-     * @return 文件内容
+     * @param file 文件对象
+     * @return 字节数组
+     * @throws IOException I/O异常
      */
-    public static String read(@NonNull String file) {
-        try {
-            return read(new FileReader(file));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+    public static byte[] getBytes(@NonNull File file) throws IOException {
+        return getBytes(new FileInputStream(file));
     }
 
     /**
-     * 读取文件内容
+     * 读取输入流字节数组
      *
-     * @param file     文件路径
-     * @param consumer 文件内容消费者
+     * @param in 输入流
+     * @return 字节数组
+     * @throws IOException I/O异常
      */
-    public static void read(@NonNull String file, @NonNull Consumer<String> consumer) {
-        try {
-            read(new FileReader(file), consumer);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+    public static byte[] getBytes(@NonNull InputStream in) throws IOException {
+        int n;
+        byte[] buffer = new byte[1024];
+        ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(32, in.available()));
+        while ((n = in.read(buffer)) != -1) {
+            out.write(buffer, 0, n);
         }
+        return out.toByteArray();
     }
 
     /**
-     * 读取文件内容
+     * 读取文件字符串
+     *
+     * @param file 文件对象
+     * @return 文件字符串
+     * @throws IOException I/O异常
+     */
+    public static String getString(@NonNull File file) throws IOException {
+        return getString(new FileReader(file));
+    }
+
+    /**
+     * 读取文件字符串
      *
      * @param in 文件读取器
-     * @return 文件内容
+     * @return 文件字符串
+     * @throws IOException I/O异常
      */
-    public static String read(@NonNull Reader in) {
+    public static String getString(@NonNull Reader in) throws IOException {
         StringBuilder buffer = new StringBuilder();
-        read(in, line -> {
+        lines(in, line -> {
             if (buffer.length() > 0) {
                 buffer.append(StringUtils.ENTER);
             }
@@ -219,49 +217,15 @@ public final class FileUtils {
         return buffer.toString();
     }
 
-    /**
-     * 读取文件内容
-     *
-     * @param in       文件读取处理器
-     * @param consumer 文件内容消费者
-     */
-    public static void read(@NonNull Reader in, @NonNull Consumer<String> consumer) {
-        try (BufferedReader reader = new BufferedReader(in)) {
-            String line;
-            while ((line = reader.readLine()) != null) {
-                consumer.accept(line);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     /**
      * 写文件
      *
      * @param file    目标文件
      * @param content 文件内容
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull File file, @NonNull String content) {
-        try {
-            write(new FileWriter(file), content);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 写文件
-     *
-     * @param file    目标文件路径
-     * @param content 文件内容
-     */
-    public static void write(@NonNull String file, @NonNull String content) {
-        try {
-            write(new FileWriter(file), content);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+    public static void write(@NonNull File file, @NonNull String content) throws IOException {
+        write(new FileWriter(file), content);
     }
 
     /**
@@ -269,12 +233,11 @@ public final class FileUtils {
      *
      * @param out     文件写入处理器
      * @param content 文件内容
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull Writer out, @NonNull String content) {
+    public static void write(@NonNull Writer out, @NonNull String content) throws IOException {
         try (BufferedWriter writer = new BufferedWriter(out)) {
             writer.write(content);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
         }
     }
 
@@ -283,64 +246,52 @@ public final class FileUtils {
      *
      * @param out 输出文件
      * @param in  输入文件
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull File out, @NonNull File in) {
-        try {
-            try (OutputStream output = new FileOutputStream(out)) {
-                write(output, in);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+    public static void write(@NonNull File out, @NonNull File in) throws IOException {
+        try (OutputStream output = new FileOutputStream(out)) {
+            write(output, in);
         }
     }
 
     /**
      * 将输入流写入文件
      *
-     * @param file  文件对象
-     * @param input 输入流
+     * @param file 文件对象
+     * @param in   输入流
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull File file, @NonNull InputStream input) {
-        try {
-            try (OutputStream output = new FileOutputStream(file)) {
-                write(output, input);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+    public static void write(@NonNull File file, @NonNull InputStream in) throws IOException {
+        try (OutputStream output = new FileOutputStream(file)) {
+            write(output, in);
         }
     }
 
     /**
      * 将文件写入输入流
      *
-     * @param output 输出流
-     * @param file   文件对象
+     * @param out  输出流
+     * @param file 文件对象
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull OutputStream output, @NonNull File file) {
-        try {
-            try (InputStream input = new FileInputStream(file)) {
-                write(output, input);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+    public static void write(@NonNull OutputStream out, @NonNull File file) throws IOException {
+        try (InputStream input = new FileInputStream(file)) {
+            write(out, input);
         }
     }
 
     /**
      * 将输入流写入输出流
      *
-     * @param output 输出流
-     * @param input  输入流
+     * @param out 输出流
+     * @param in  输入流
+     * @throws IOException I/O异常
      */
-    public static void write(@NonNull OutputStream output, @NonNull InputStream input) {
-        int len;
+    public static void write(@NonNull OutputStream out, @NonNull InputStream in) throws IOException {
+        int n;
         byte[] buffer = new byte[1024];
-        try {
-            while ((len = input.read(buffer)) > -1) {
-                output.write(buffer, 0, len);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+        while ((n = in.read(buffer)) > -1) {
+            out.write(buffer, 0, n);
         }
     }
 

+ 3 - 2
framework-database/src/main/java/com/chelvc/framework/database/interceptor/DatabaseExceptionInterceptor.java

@@ -4,8 +4,8 @@ import javax.servlet.http.HttpServletRequest;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.LoggingContextHolder;
+import com.chelvc.framework.base.context.Result;
 import com.chelvc.framework.common.exception.ParameterInvalidException;
-import com.chelvc.framework.common.model.Result;
 import com.chelvc.framework.common.util.ErrorUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.mybatis.spring.MyBatisSystemException;
@@ -39,7 +39,8 @@ public class DatabaseExceptionInterceptor {
         ParameterInvalidException parameterInvalidException = ErrorUtils.lookup(e, ParameterInvalidException.class);
         if (parameterInvalidException != null) {
             LoggingContextHolder.warn(log, request, e);
-            return parameterInvalidException.result();
+            return Result.of(ParameterInvalidException.CODE, parameterInvalidException.getData(),
+                    ApplicationContextHolder.getMessage("Parameter.Invalid"));
         }
         LoggingContextHolder.error(log, request, e);
         return Result.failure(ApplicationContextHolder.getMessage("Failure"));

+ 2 - 2
framework-dubbo/src/main/java/com/chelvc/framework/dubbo/interceptor/DubboConsumerInterceptor.java

@@ -1,7 +1,7 @@
 package com.chelvc.framework.dubbo.interceptor;
 
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.dubbo.adapter.DubboObjectAdapterHolder;
 import com.chelvc.framework.dubbo.adapter.DubboObjectAdapterWrapper;
 import org.apache.dubbo.common.constants.CommonConstants;
@@ -76,7 +76,7 @@ public class DubboConsumerInterceptor implements Filter {
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
         Session session = SessionContextHolder.getSession(false);
-        RpcContext.getClientAttachment().setObjectAttachment(SessionContextHolder.NAME, session);
+        RpcContext.getClientAttachment().setObjectAttachment(Session.NAMING, session);
         try {
             return this.processing(invoker, invocation);
         } finally {

+ 2 - 2
framework-dubbo/src/main/java/com/chelvc/framework/dubbo/interceptor/DubboProviderInterceptor.java

@@ -1,8 +1,8 @@
 package com.chelvc.framework.dubbo.interceptor;
 
 import com.chelvc.framework.base.context.LoggingContextHolder;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.dubbo.adapter.DubboObjectAdapterHolder;
 import com.chelvc.framework.dubbo.adapter.DubboObjectAdapterWrapper;
 import lombok.extern.slf4j.Slf4j;
@@ -52,7 +52,7 @@ public class DubboProviderInterceptor implements Filter {
 
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
-        Session session = (Session) RpcContext.getServerAttachment().getObjectAttachment(SessionContextHolder.NAME);
+        Session session = (Session) RpcContext.getServerAttachment().getObjectAttachment(Session.NAMING);
         SessionContextHolder.setSession(session);
         try {
             boolean debug = log.isDebugEnabled();

+ 1 - 1
framework-feign/src/main/java/com/chelvc/framework/feign/interceptor/FeignExceptionInterceptor.java

@@ -3,8 +3,8 @@ package com.chelvc.framework.feign.interceptor;
 import java.io.IOException;
 import java.io.InputStream;
 
+import com.chelvc.framework.base.context.Result;
 import com.chelvc.framework.common.exception.FrameworkException;
-import com.chelvc.framework.common.model.Result;
 import com.chelvc.framework.common.util.JacksonUtils;
 import feign.Response;
 import feign.codec.ErrorDecoder;

+ 1 - 1
framework-feign/src/main/java/com/chelvc/framework/feign/interceptor/FeignHeaderInterceptor.java

@@ -1,8 +1,8 @@
 package com.chelvc.framework.feign.interceptor;
 
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.model.Platform;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.model.Terminal;
 import com.chelvc.framework.common.util.ObjectUtils;
 import feign.RequestInterceptor;

+ 3 - 3
framework-kafka/src/main/java/com/chelvc/framework/kafka/context/KafkaContextHolder.java

@@ -12,8 +12,8 @@ import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.JacksonUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -97,7 +97,7 @@ public final class KafkaContextHolder {
      * @return 会话实例
      */
     public static Session getSession(@NonNull Headers headers) {
-        Iterator<Header> iterator = headers.headers(SessionContextHolder.NAME).iterator();
+        Iterator<Header> iterator = headers.headers(Session.NAMING).iterator();
         if (iterator.hasNext()) {
             return JacksonUtils.deserialize(iterator.next().value(), Session.class);
         }
@@ -112,7 +112,7 @@ public final class KafkaContextHolder {
     public static void initializeSession(@NonNull Headers headers) {
         Session session = SessionContextHolder.getSession(false);
         if (session != null) {
-            headers.add(SessionContextHolder.NAME, JacksonUtils.serialize(session).getBytes(StandardCharsets.UTF_8));
+            headers.add(Session.NAMING, JacksonUtils.serialize(session).getBytes(StandardCharsets.UTF_8));
         }
     }
 

+ 12 - 0
framework-oauth/src/main/java/com/chelvc/framework/oauth/context/OAuthContextHolder.java

@@ -8,6 +8,8 @@ import java.util.Objects;
 import java.util.Set;
 import javax.servlet.http.HttpServletRequest;
 
+import com.chelvc.framework.base.context.Session;
+import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.function.Adapter;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -257,4 +259,14 @@ public final class OAuthContextHolder {
         String[] authorities = getJwtClaim(jwt, claims -> claims.getStringArrayClaim(JWT_CLAIM_AUTHORITIES));
         return ObjectUtils.isEmpty(authorities) ? Collections.emptySet() : Sets.newHashSet(authorities);
     }
+
+    /**
+     * 初始化会话主体信息
+     *
+     * @param jwt JWT对象
+     * @return 会话信息
+     */
+    public static Session initializeSessionPrincipal(@NonNull Jwt jwt) {
+        return SessionContextHolder.setSession(getId(jwt), getScope(jwt), isAnonymous(jwt));
+    }
 }

+ 4 - 12
framework-oauth/src/main/java/com/chelvc/framework/oauth/token/RedisTokenValidator.java

@@ -50,12 +50,8 @@ public class RedisTokenValidator implements OAuth2TokenValidator<Jwt> {
         } catch (Exception e) {
             log.warn("Redis token validate failed: {}", e.getMessage());
 
-            // 初始化会话信息
-            SessionContextHolder.initializeSession(
-                    OAuthContextHolder.getId(jwt),
-                    OAuthContextHolder.getScope(jwt),
-                    OAuthContextHolder.isAnonymous(jwt)
-            );
+            // 初始化会话主体信息
+            OAuthContextHolder.initializeSessionPrincipal(jwt);
             return OAuth2TokenValidatorResult.success();
         }
         String scope = ObjectUtils.size(values) > 0 ? (String) StringUtils.ifEmpty(values.get(0), (String) null) : null;
@@ -77,12 +73,8 @@ public class RedisTokenValidator implements OAuth2TokenValidator<Jwt> {
             throw new OAuth2AuthenticationException(new OAuth2Error("SCOPE_CHANGED", message, null));
         }
 
-        // 初始化会话信息
-        SessionContextHolder.initializeSession(
-                OAuthContextHolder.getId(jwt),
-                OAuthContextHolder.getScope(jwt),
-                OAuthContextHolder.isAnonymous(jwt)
-        );
+        // 初始化会话主体信息
+        OAuthContextHolder.initializeSessionPrincipal(jwt);
         return OAuth2TokenValidatorResult.success();
     }
 }

+ 5 - 5
framework-redis/src/main/java/com/chelvc/framework/redis/context/RedisContextHolder.java

@@ -18,9 +18,9 @@ import java.util.function.Function;
 import java.util.function.Supplier;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.function.Executor;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.IdentityUtils;
 import com.chelvc.framework.common.util.JacksonUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
@@ -1428,7 +1428,7 @@ public final class RedisContextHolder {
         }
         Session session = SessionContextHolder.getSession(false);
         if (session != null) {
-            args.add(SessionContextHolder.NAME);
+            args.add(Session.NAMING);
             args.add(JacksonUtils.serialize(session));
         }
         List<String> keys = Collections.singletonList(isolate(topic));
@@ -1571,9 +1571,9 @@ public final class RedisContextHolder {
         if (StringUtils.notEmpty(payload)) {
             builder.put(PAYLOAD, payload);
         }
-        String session = value.get(SessionContextHolder.NAME);
+        String session = value.get(Session.NAMING);
         if (StringUtils.notEmpty(session)) {
-            builder.put(SessionContextHolder.NAME, session);
+            builder.put(Session.NAMING, session);
         }
         String delaying = value.get(DELAYING);
         if (StringUtils.notEmpty(delaying)) {
@@ -1608,7 +1608,7 @@ public final class RedisContextHolder {
                                    @NonNull Consumer<T> consumer) {
         Map<String, String> value = record.getValue();
         T payload = (T) JacksonUtils.deserialize(value.get(PAYLOAD), type);
-        Session session = JacksonUtils.deserialize(value.get(SessionContextHolder.NAME), Session.class);
+        Session session = JacksonUtils.deserialize(value.get(Session.NAMING), Session.class);
         SessionContextHolder.setSession(session);
         try {
             consumer.accept(payload);

+ 1 - 1
framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/consumer/MultipleRocketMQListenerContainer.java

@@ -7,7 +7,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
-import com.chelvc.framework.common.model.Session;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.ThreadUtils;

+ 1 - 1
framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/consumer/RocketMQListener.java

@@ -2,8 +2,8 @@ package com.chelvc.framework.rocketmq.consumer;
 
 import java.util.List;
 
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.ObjectUtils;
 import org.apache.commons.lang3.tuple.Pair;
 

+ 4 - 8
framework-rocketmq/src/main/java/com/chelvc/framework/rocketmq/context/RocketMQContextHolder.java

@@ -16,9 +16,9 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.common.model.Reference;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.JacksonUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
@@ -214,7 +214,7 @@ public final class RocketMQContextHolder {
         MessageBuilder builder = getMessageBuilder().setTopic(topic.getLeft()).setBody(body)
                 .addProperty(TYPE, payload.getClass().getName());
         if (Objects.nonNull(session)) {
-            builder.addProperty(SessionContextHolder.NAME, session);
+            builder.addProperty(Session.NAMING, session);
         }
         if (StringUtils.notEmpty(topic.getRight())) {
             builder.setTag(topic.getRight());
@@ -277,9 +277,7 @@ public final class RocketMQContextHolder {
     public static void deserialize(@NonNull MessageView message, @NonNull Type type,
                                    @NonNull Consumer<Object> consumer) {
         Object payload = deserialize(message, type);
-        Session session = JacksonUtils.deserialize(
-                message.getProperties().get(SessionContextHolder.NAME), Session.class
-        );
+        Session session = JacksonUtils.deserialize(message.getProperties().get(Session.NAMING), Session.class);
         SessionContextHolder.setSession(session);
         try {
             consumer.accept(payload);
@@ -304,9 +302,7 @@ public final class RocketMQContextHolder {
         }
         return messages.stream().map(message -> {
             Object payload = deserialize(message, type);
-            Session session = JacksonUtils.deserialize(
-                    message.getProperties().get(SessionContextHolder.NAME), Session.class
-            );
+            Session session = JacksonUtils.deserialize(message.getProperties().get(Session.NAMING), Session.class);
             return function.apply(payload, session);
         }).filter(Objects::nonNull).collect(Collectors.toList());
     }

+ 22 - 7
framework-security/src/main/java/com/chelvc/framework/security/interceptor/ControllerCryptoInterceptor.java

@@ -8,12 +8,13 @@ import java.util.Objects;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.JacksonContextHolder;
+import com.chelvc.framework.base.context.Result;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.base.util.HttpUtils;
+import com.chelvc.framework.base.interceptor.BufferedRequestWrapper;
 import com.chelvc.framework.common.exception.FrameworkException;
-import com.chelvc.framework.common.model.Result;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.AESUtils;
+import com.chelvc.framework.common.util.FileUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.security.annotation.Crypto;
 import com.chelvc.framework.security.config.SecurityProperties;
@@ -71,6 +72,21 @@ public class ControllerCryptoInterceptor extends RequestBodyAdviceAdapter implem
         return annotation;
     }
 
+    /**
+     * 获取消息密文
+     *
+     * @param message 消息对象
+     * @return 密文字节数组
+     * @throws IOException I/O异常
+     */
+    private byte[] getCiphertext(HttpInputMessage message) throws IOException {
+        InputStream input = message.getBody();
+        if (input instanceof BufferedRequestWrapper.BufferedServletInputStream) {
+            return ((BufferedRequestWrapper.BufferedServletInputStream) input).decodeBase64();
+        }
+        return Base64.decodeBase64(FileUtils.getBytes(input));
+    }
+
     @Override
     public boolean supports(MethodParameter method, Class<? extends HttpMessageConverter<?>> clazz) {
         Crypto annotation = this.getCryptoAnnotation(method);
@@ -86,15 +102,14 @@ public class ControllerCryptoInterceptor extends RequestBodyAdviceAdapter implem
     @Override
     public HttpInputMessage beforeBodyRead(HttpInputMessage message, MethodParameter method, Type type,
                                            Class<? extends HttpMessageConverter<?>> clazz) throws IOException {
-        byte[] ciphertext = Base64.decodeBase64(HttpUtils.getBody(message.getBody()));
+        byte[] ciphertext = this.getCiphertext(message);
         String secret = Objects.requireNonNull(this.properties.getSecret()), iv = this.iv();
         byte[] body;
         try {
             body = AESUtils.decode(ciphertext, secret, iv);
         } catch (Exception e) {
-            throw new FrameworkException(
-                    HttpStatus.BAD_REQUEST.name(), null, ApplicationContextHolder.getMessage("Ciphertext.Invalid")
-            );
+            throw new FrameworkException(HttpStatus.BAD_REQUEST.name(), null,
+                    ApplicationContextHolder.getMessage("Ciphertext.Invalid"));
         }
         return new HttpInputMessage() {
             @Override

+ 1 - 1
framework-security/src/main/java/com/chelvc/framework/security/interceptor/SecurityExceptionInterceptor.java

@@ -3,8 +3,8 @@ package com.chelvc.framework.security.interceptor;
 import javax.servlet.http.HttpServletRequest;
 
 import com.chelvc.framework.base.context.LoggingContextHolder;
+import com.chelvc.framework.base.context.Result;
 import com.chelvc.framework.base.context.SessionContextHolder;
-import com.chelvc.framework.common.model.Result;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;

+ 14 - 12
framework-security/src/main/java/com/chelvc/framework/security/interceptor/SecurityValidateInterceptor.java

@@ -6,10 +6,10 @@ import javax.servlet.http.HttpServletResponse;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.LoggingContextHolder;
+import com.chelvc.framework.base.context.Session;
 import com.chelvc.framework.base.context.SessionContextHolder;
 import com.chelvc.framework.base.util.HttpUtils;
 import com.chelvc.framework.common.exception.FrameworkException;
-import com.chelvc.framework.common.model.Session;
 import com.chelvc.framework.common.util.CodecUtils;
 import com.chelvc.framework.common.util.StringUtils;
 import com.chelvc.framework.security.annotation.Security;
@@ -35,6 +35,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @Component
 @RequiredArgsConstructor(onConstructor = @__(@Autowired))
 public class SecurityValidateInterceptor implements HandlerInterceptor, WebMvcConfigurer {
+    /**
+     * 签名信息请求头
+     */
+    private static final String HEADER_SIGNATURE = "signature";
+
     private final SecurityProperties properties;
 
     /**
@@ -68,17 +73,15 @@ public class SecurityValidateInterceptor implements HandlerInterceptor, WebMvcCo
             // 非空请求头校验
             if (session.getPlatform() == null || session.getTerminal() == null
                     || StringUtils.isEmpty(session.getVersion()) || session.getTimestamp() == null) {
-                throw new FrameworkException(
-                        HttpStatus.BAD_REQUEST.name(), null, ApplicationContextHolder.getMessage("Header.Missing")
-                );
+                throw new FrameworkException(HttpStatus.BAD_REQUEST.name(), null,
+                        ApplicationContextHolder.getMessage("Header.Missing"));
             }
 
             // 请求时间戳校验
             long duration = this.properties.getDuration();
             if (duration > 0 && Math.abs(System.currentTimeMillis() - session.getTimestamp()) > duration) {
-                throw new FrameworkException(
-                        HttpStatus.BAD_REQUEST.name(), null, ApplicationContextHolder.getMessage("Time.Deviated")
-                );
+                throw new FrameworkException(HttpStatus.BAD_REQUEST.name(), null,
+                        ApplicationContextHolder.getMessage("Time.Deviated"));
             }
         }
 
@@ -89,12 +92,11 @@ public class SecurityValidateInterceptor implements HandlerInterceptor, WebMvcCo
             String plaintext = secret + session.getPlatform() + session.getTerminal() + session.getVersion() +
                     session.getTimestamp() + payload;
             String ciphertext = CodecUtils.md5(plaintext);
-            String signature = request.getHeader(SessionContextHolder.HEADER_SIGNATURE);
-            LoggingContextHolder.debug(log, plaintext, ciphertext, payload);
+            String signature = request.getHeader(HEADER_SIGNATURE);
+            LoggingContextHolder.debug(log, signature, plaintext, ciphertext, payload);
             if (!Objects.equals(ciphertext, signature)) {
-                throw new FrameworkException(
-                        HttpStatus.BAD_REQUEST.name(), null, ApplicationContextHolder.getMessage("Signature.Invalid")
-                );
+                throw new FrameworkException(HttpStatus.BAD_REQUEST.name(), null,
+                        ApplicationContextHolder.getMessage("Signature.Invalid"));
             }
         }
         return true;

+ 7 - 3
framework-upload/src/main/java/com/chelvc/framework/upload/UploadHandler.java

@@ -1,6 +1,7 @@
 package com.chelvc.framework.upload;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 
 /**
@@ -15,8 +16,9 @@ public interface UploadHandler {
      *
      * @param file 文件对象
      * @return 文件访问地址
+     * @throws IOException I/O异常
      */
-    String upload(File file);
+    String upload(File file) throws IOException;
 
     /**
      * 文件上传
@@ -24,8 +26,9 @@ public interface UploadHandler {
      * @param stream 文件流
      * @param suffix 后缀名
      * @return 文件访问地址
+     * @throws IOException I/O异常
      */
-    String upload(InputStream stream, String suffix);
+    String upload(InputStream stream, String suffix) throws IOException;
 
     /**
      * 文件上传
@@ -34,8 +37,9 @@ public interface UploadHandler {
      * @param suffix 后缀名
      * @param length 文件大小
      * @return 文件访问地址
+     * @throws IOException I/O异常
      */
-    String upload(InputStream stream, String suffix, long length);
+    String upload(InputStream stream, String suffix, long length) throws IOException;
 
     /**
      * 销毁处理器

+ 23 - 9
framework-upload/src/main/java/com/chelvc/framework/upload/support/DelegatingUploadHandler.java

@@ -1,9 +1,9 @@
 package com.chelvc.framework.upload.support;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
-import java.util.function.Function;
 
 import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.upload.UploadHandler;
@@ -24,19 +24,33 @@ public class DelegatingUploadHandler implements UploadHandler {
         this.handlers = AssertUtils.nonempty(handlers, () -> "Delegating handlers must not be empty");
     }
 
+    /**
+     * 文件上传执行器接口
+     */
+    private interface Executor {
+        /**
+         * 执行文件上传处理
+         *
+         * @param handler 文件上传处理器
+         * @return 文件路径
+         * @throws IOException I/O异常
+         */
+        String execute(UploadHandler handler) throws IOException;
+    }
+
     /**
      * 遍历所有短信处理器并执行文件上传处理,直到上传成功
      *
-     * @param callback 文件上传处理回调函数
+     * @param executor 文件上传执行器
      */
-    private String execute(Function<UploadHandler, String> callback) {
+    private String execute(Executor executor) throws IOException {
         RuntimeException unsupported = null;
         for (int i = 0, last = this.handlers.size() - 1; i <= last; i++) {
             try {
-                return callback.apply(this.handlers.get(i));
-            } catch (RuntimeException e) {
+                return executor.execute(this.handlers.get(i));
+            } catch (Exception e) {
                 if (e instanceof UnsupportedOperationException) {
-                    unsupported = e;
+                    unsupported = (UnsupportedOperationException) e;
                 } else if (i < last) {
                     log.warn("File upload failed: {}", e.getMessage());
                 } else {
@@ -51,17 +65,17 @@ public class DelegatingUploadHandler implements UploadHandler {
     }
 
     @Override
-    public String upload(@NonNull File file) {
+    public String upload(@NonNull File file) throws IOException {
         return this.execute(handler -> handler.upload(file));
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix) {
+    public String upload(@NonNull InputStream stream, String suffix) throws IOException {
         return this.execute(handler -> handler.upload(stream, suffix));
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix, long length) {
+    public String upload(@NonNull InputStream stream, String suffix, long length) throws IOException {
         return this.execute(handler -> handler.upload(stream, suffix, length));
     }
 }

+ 5 - 4
framework-upload/src/main/java/com/chelvc/framework/upload/support/SimpleUploadHandler.java

@@ -1,6 +1,7 @@
 package com.chelvc.framework.upload.support;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.Objects;
 
@@ -27,7 +28,7 @@ public class SimpleUploadHandler implements UploadHandler {
     }
 
     @Override
-    public String upload(@NonNull File file) {
+    public String upload(@NonNull File file) throws IOException {
         String suffix = FileUtils.getSuffix(file);
         String filename = StringUtils.uuid() + StringUtils.ifEmpty(suffix, name -> "." + name, StringUtils.EMPTY);
         FileUtils.write(new File(this.path, filename), file);
@@ -35,12 +36,12 @@ public class SimpleUploadHandler implements UploadHandler {
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix) {
-        return this.upload(stream, suffix, FileUtils.getLength(stream));
+    public String upload(@NonNull InputStream stream, String suffix) throws IOException {
+        return this.upload(stream, suffix, stream.available());
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix, long length) {
+    public String upload(@NonNull InputStream stream, String suffix, long length) throws IOException {
         String filename = StringUtils.uuid() + StringUtils.ifEmpty(suffix, name -> "." + name, StringUtils.EMPTY);
         FileUtils.write(new File(this.path, filename), stream);
         return HttpUtils.url(this.domain, filename);

+ 5 - 4
framework-upload/src/main/java/com/chelvc/framework/upload/support/TencentUploadHandler.java

@@ -1,6 +1,7 @@
 package com.chelvc.framework.upload.support;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.Objects;
 
@@ -58,7 +59,7 @@ public class TencentUploadHandler implements UploadHandler {
     }
 
     @Override
-    public String upload(@NonNull File file) {
+    public String upload(@NonNull File file) throws IOException {
         String suffix = FileUtils.getSuffix(file);
         String filename = StringUtils.uuid() + StringUtils.ifEmpty(suffix, name -> "." + name, StringUtils.EMPTY);
         this.client.putObject(this.path, filename, file);
@@ -66,12 +67,12 @@ public class TencentUploadHandler implements UploadHandler {
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix) {
-        return this.upload(stream, suffix, FileUtils.getLength(stream));
+    public String upload(@NonNull InputStream stream, String suffix) throws IOException {
+        return this.upload(stream, suffix, stream.available());
     }
 
     @Override
-    public String upload(@NonNull InputStream stream, String suffix, long length) {
+    public String upload(@NonNull InputStream stream, String suffix, long length) throws IOException {
         ObjectMetadata metadata = new ObjectMetadata();
         metadata.setContentLength(length);
         String filename = StringUtils.uuid() + StringUtils.ifEmpty(suffix, name -> "." + name, StringUtils.EMPTY);