Browse Source

实现 request body 重复读取的功能

YunaiV 4 years ago
parent
commit
8e21b5200a

+ 0 - 11
ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java

@@ -44,15 +44,4 @@ public class FilterConfig {
         return registration;
     }
 
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    @Bean
-    public FilterRegistrationBean someFilterRegistration() {
-        FilterRegistrationBean registration = new FilterRegistrationBean();
-        registration.setFilter(new RepeatableFilter());
-        registration.addUrlPatterns("/*");
-        registration.setName("repeatableFilter");
-        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
-        return registration;
-    }
-
 }

+ 0 - 45
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java

@@ -1,45 +0,0 @@
-package com.ruoyi.common.filter;
-
-import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.http.MediaType;
-import com.ruoyi.common.utils.StringUtils;
-
-/**
- * Repeatable 过滤器
- *
- * @author ruoyi
- */
-public class RepeatableFilter implements Filter {
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-
-    }
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-            throws IOException, ServletException {
-        ServletRequest requestWrapper = null;
-        if (request instanceof HttpServletRequest
-                && StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
-            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
-        }
-        if (null == requestWrapper) {
-            chain.doFilter(request, response);
-        } else {
-            chain.doFilter(requestWrapper, response);
-        }
-    }
-
-    @Override
-    public void destroy() {
-
-    }
-}

+ 0 - 64
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java

@@ -1,64 +0,0 @@
-package com.ruoyi.common.filter;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-
-import com.ruoyi.common.utils.http.HttpHelper;
-
-/**
- * 构建可重复读取inputStream的request
- *
- * @author ruoyi
- */
-public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
-    private final byte[] body;
-
-    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
-        super(request);
-        request.setCharacterEncoding("UTF-8");
-        response.setCharacterEncoding("UTF-8");
-
-        body = HttpHelper.getBodyString(request).getBytes("UTF-8");
-    }
-
-    @Override
-    public BufferedReader getReader() throws IOException {
-        return new BufferedReader(new InputStreamReader(getInputStream()));
-    }
-
-    @Override
-    public ServletInputStream getInputStream() throws IOException {
-
-        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
-
-        return new ServletInputStream() {
-
-            @Override
-            public int read() throws IOException {
-                return bais.read();
-            }
-
-            @Override
-            public boolean isFinished() {
-                return false;
-            }
-
-            @Override
-            public boolean isReady() {
-                return false;
-            }
-
-            @Override
-            public void setReadListener(ReadListener readListener) {
-
-            }
-        };
-    }
-}

+ 10 - 0
src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java

@@ -1,5 +1,6 @@
 package cn.iocoder.dashboard.framework.web.config;
 
+import cn.iocoder.dashboard.framework.web.core.filter.RequestBodyCacheFilter;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -50,4 +51,13 @@ public class WebConfiguration implements WebMvcConfigurer {
         return new CorsFilter(source);
     }
 
+    /**
+     * 创建 RequestBodyCacheFilter Bean,可重复读取请求内容
+     */
+    @Bean
+    @Order(Integer.MIN_VALUE)
+    public RequestBodyCacheFilter requestBodyCacheFilter() {
+        return new RequestBodyCacheFilter();
+    }
+
 }

+ 35 - 0
src/main/java/cn/iocoder/dashboard/framework/web/core/filter/RequestBodyCacheFilter.java

@@ -0,0 +1,35 @@
+package cn.iocoder.dashboard.framework.web.core.filter;
+
+import cn.hutool.core.util.StrUtil;
+import org.springframework.http.MediaType;
+import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.util.ContentCachingRequestWrapper;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Request Body 缓存 Filter,实现它的可重复读取
+ *
+ * 基于 Spring 提供的 {@link org.springframework.web.util.ContentCachingRequestWrapper} 实现
+ *
+ * @author 芋道源码
+ */
+public class RequestBodyCacheFilter extends OncePerRequestFilter {
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws IOException, ServletException {
+        filterChain.doFilter(new ContentCachingRequestWrapper(request), response);
+    }
+
+    @Override
+    protected boolean shouldNotFilter(HttpServletRequest request) {
+        // 只处理 json 请求内容
+        return !StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE);
+    }
+
+}