瀏覽代碼

优化Http请求缓存逻辑

Woody 1 月之前
父節點
當前提交
64d46b71e6

+ 50 - 2
framework-base/src/main/java/com/chelvc/framework/base/interceptor/RequestCachingInterceptor.java

@@ -6,6 +6,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Enumeration;
 import java.util.Map;
 import javax.servlet.FilterChain;
@@ -18,6 +19,7 @@ import javax.servlet.http.HttpServletResponse;
 
 import com.chelvc.framework.base.util.HttpUtils;
 import com.chelvc.framework.common.util.CodecUtils;
+import com.chelvc.framework.common.util.DateUtils;
 import com.chelvc.framework.common.util.FileUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
 import com.chelvc.framework.common.util.StringUtils;
@@ -146,6 +148,7 @@ public class RequestCachingInterceptor extends OncePerRequestFilter {
     public static class CachingRequestWrapper extends HttpServletRequestWrapper {
         private String body;
         private final byte[] bytes;
+        private final Map<String, String[]> headers;
         private final Map<String, String[]> parameters;
 
         private CachingRequestWrapper(HttpServletRequest request) throws IOException {
@@ -153,11 +156,15 @@ public class RequestCachingInterceptor extends OncePerRequestFilter {
             if (request instanceof CachingRequestWrapper) {
                 this.body = ((CachingRequestWrapper) request).body;
                 this.bytes = ((CachingRequestWrapper) request).bytes;
+                this.headers = ((CachingRequestWrapper) request).headers;
                 this.parameters = ((CachingRequestWrapper) request).parameters;
             } else {
+                // 缓存请求头
+                this.headers = HttpUtils.getHeaders(request);
+
                 // Servlet 规范规定如果调用了getInputStream()或getReader()方法,则getParameter*()方法的行为是未定义的
                 // Tomcat、Jetty、Undertow容器均支持在调用getParameter*()方法后能正常调用getInputStream()方法
-                this.parameters = request.getParameterMap();
+                this.parameters = HttpUtils.getParameters(request);
                 if (HttpUtils.isBodyType(request)) {
                     try (InputStream input = request.getInputStream()) {
                         if (input instanceof CachingInputStream) {
@@ -188,6 +195,47 @@ public class RequestCachingInterceptor extends OncePerRequestFilter {
             return this.body;
         }
 
+        /**
+         * 获取请求头
+         *
+         * @return 请求头键/值映射表
+         */
+        public Map<String, String[]> getHeaders() {
+            return this.headers;
+        }
+
+        @Override
+        public String getHeader(String name) {
+            String[] values = this.headers.get(name);
+            return ObjectUtils.isEmpty(values) ? null : values[0];
+        }
+
+        @Override
+        public int getIntHeader(String name) {
+            String value = this.getHeader(name);
+            return StringUtils.isEmpty(value) ? -1 : Integer.parseInt(value);
+        }
+
+        @Override
+        public long getDateHeader(String name) {
+            String value = this.getHeader(name);
+            Date date = DateUtils.parse(value);
+            return date == null ? -1 : date.getTime();
+        }
+
+        @Override
+        public Enumeration<String> getHeaders(String name) {
+            return ObjectUtils.enumeration(this.headers.get(name));
+        }
+
+        @Override
+        public Enumeration<String> getHeaderNames() {
+            if (ObjectUtils.isEmpty(this.headers)) {
+                return Collections.emptyEnumeration();
+            }
+            return Collections.enumeration(this.headers.keySet());
+        }
+
         @Override
         public String getParameter(String name) {
             String[] values = this.parameters.get(name);
@@ -196,7 +244,7 @@ public class RequestCachingInterceptor extends OncePerRequestFilter {
 
         @Override
         public Map<String, String[]> getParameterMap() {
-            return Collections.unmodifiableMap(this.parameters);
+            return this.parameters;
         }
 
         @Override

+ 43 - 0
framework-base/src/main/java/com/chelvc/framework/base/util/HttpUtils.java

@@ -13,6 +13,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -28,6 +29,7 @@ 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;
+import com.google.common.collect.Maps;
 import lombok.NonNull;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.usermodel.Workbook;
@@ -290,6 +292,47 @@ public final class HttpUtils {
                 || type.startsWith("application/grpc") || type.startsWith("application/octet-stream"));
     }
 
+    /**
+     * 获取表单请求参数
+     *
+     * @param request 请求对象
+     * @return 参数键/值映射表
+     */
+    public static Map<String, String[]> getParameters(@NonNull ServletRequest request) {
+        // 从请求包装器中直接获取请求参数
+        if (request instanceof RequestCachingInterceptor.CachingRequestWrapper) {
+            return request.getParameterMap();
+        }
+
+        // 获取原始请求参数
+        return Collections.unmodifiableMap(request.getParameterMap());
+    }
+
+    /**
+     * 获取请求头
+     *
+     * @param request 请求对象
+     * @return 请求头键/值映射表
+     */
+    public static Map<String, String[]> getHeaders(@NonNull HttpServletRequest request) {
+        // 从请求包装器中直接获取请求头
+        if (request instanceof RequestCachingInterceptor.CachingRequestWrapper) {
+            return ((RequestCachingInterceptor.CachingRequestWrapper) request).getHeaders();
+        }
+
+        // 获取原始请求头
+        Enumeration<String> names = request.getHeaderNames();
+        if (names == null) {
+            return Collections.emptyMap();
+        }
+        Map<String, String[]> headers = Maps.newHashMap();
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+            headers.put(name, ObjectUtils.array(String.class, request.getHeaders(name)));
+        }
+        return headers.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(headers);
+    }
+
     /**
      * 初始化文件下载相应头
      *

+ 70 - 0
framework-common/src/main/java/com/chelvc/framework/common/util/ObjectUtils.java

@@ -1701,6 +1701,17 @@ public final class ObjectUtils {
                 ((List<T>) collection).get(0) : collection.iterator().next();
     }
 
+    /**
+     * 获取集合第一个元素
+     *
+     * @param enumeration 对象m枚举
+     * @param <T>         元素类型
+     * @return 对象实例
+     */
+    public static <T> T first(Enumeration<T> enumeration) {
+        return enumeration == null || !enumeration.hasMoreElements() ? null : enumeration.nextElement();
+    }
+
     /**
      * 将枚举对象转换成对象列表
      *
@@ -1719,4 +1730,63 @@ public final class ObjectUtils {
         }
         return list.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(list);
     }
+
+    /**
+     * 创建对象数组
+     *
+     * @param type   对象类型
+     * @param length 数组长度
+     * @param <T>    数据类型
+     * @return 数组实例
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T[] array(@NonNull Class<T> type, int length) {
+        return (T[]) Array.newInstance(type, length);
+    }
+
+    /**
+     * 将枚举对象转换成对象数组
+     *
+     * @param enumeration 枚举对象
+     * @param <T>         元素类型
+     * @return 对象数组
+     */
+    public static <T> T[] array(@NonNull Class<T> type, Enumeration<T> enumeration) {
+        List<T> objects = list(enumeration);
+        T[] array = array(type, objects.size());
+
+        int i = 0;
+        for (T object : objects) {
+            array[i++] = object;
+        }
+
+        return array;
+    }
+
+    /**
+     * 将对象对象数组转换成枚举对象
+     *
+     * @param objects 对象数组
+     * @param <T>     对象类型
+     * @return 对象枚举实例
+     */
+    public static <T> Enumeration<T> enumeration(T... objects) {
+        if (isEmpty(objects)) {
+            return Collections.emptyEnumeration();
+        }
+        return new Enumeration<T>() {
+            private int index = 0;
+            private final T[] array = objects;
+
+            @Override
+            public boolean hasMoreElements() {
+                return this.index < this.array.length;
+            }
+
+            @Override
+            public T nextElement() {
+                return this.array[this.index++];
+            }
+        };
+    }
 }