Commit 8e21b5200a113c5626b2daa3f822e3d22af11666
1 parent
cb094596
实现 request body 重复读取的功能
Showing
5 changed files
with
45 additions
and
120 deletions
ruoyi-common/src/main/java/com/ruoyi/common/config/FilterConfig.java
| @@ -44,15 +44,4 @@ public class FilterConfig { | @@ -44,15 +44,4 @@ public class FilterConfig { | ||
| 44 | return registration; | 44 | return registration; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | - @SuppressWarnings({"rawtypes", "unchecked"}) | ||
| 48 | - @Bean | ||
| 49 | - public FilterRegistrationBean someFilterRegistration() { | ||
| 50 | - FilterRegistrationBean registration = new FilterRegistrationBean(); | ||
| 51 | - registration.setFilter(new RepeatableFilter()); | ||
| 52 | - registration.addUrlPatterns("/*"); | ||
| 53 | - registration.setName("repeatableFilter"); | ||
| 54 | - registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); | ||
| 55 | - return registration; | ||
| 56 | - } | ||
| 57 | - | ||
| 58 | } | 47 | } |
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java deleted
| 1 | -package com.ruoyi.common.filter; | ||
| 2 | - | ||
| 3 | -import java.io.IOException; | ||
| 4 | -import javax.servlet.Filter; | ||
| 5 | -import javax.servlet.FilterChain; | ||
| 6 | -import javax.servlet.FilterConfig; | ||
| 7 | -import javax.servlet.ServletException; | ||
| 8 | -import javax.servlet.ServletRequest; | ||
| 9 | -import javax.servlet.ServletResponse; | ||
| 10 | -import javax.servlet.http.HttpServletRequest; | ||
| 11 | - | ||
| 12 | -import org.springframework.http.MediaType; | ||
| 13 | -import com.ruoyi.common.utils.StringUtils; | ||
| 14 | - | ||
| 15 | -/** | ||
| 16 | - * Repeatable 过滤器 | ||
| 17 | - * | ||
| 18 | - * @author ruoyi | ||
| 19 | - */ | ||
| 20 | -public class RepeatableFilter implements Filter { | ||
| 21 | - @Override | ||
| 22 | - public void init(FilterConfig filterConfig) throws ServletException { | ||
| 23 | - | ||
| 24 | - } | ||
| 25 | - | ||
| 26 | - @Override | ||
| 27 | - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
| 28 | - throws IOException, ServletException { | ||
| 29 | - ServletRequest requestWrapper = null; | ||
| 30 | - if (request instanceof HttpServletRequest | ||
| 31 | - && StringUtils.equalsAnyIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) { | ||
| 32 | - requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); | ||
| 33 | - } | ||
| 34 | - if (null == requestWrapper) { | ||
| 35 | - chain.doFilter(request, response); | ||
| 36 | - } else { | ||
| 37 | - chain.doFilter(requestWrapper, response); | ||
| 38 | - } | ||
| 39 | - } | ||
| 40 | - | ||
| 41 | - @Override | ||
| 42 | - public void destroy() { | ||
| 43 | - | ||
| 44 | - } | ||
| 45 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java deleted
| 1 | -package com.ruoyi.common.filter; | ||
| 2 | - | ||
| 3 | -import java.io.BufferedReader; | ||
| 4 | -import java.io.ByteArrayInputStream; | ||
| 5 | -import java.io.IOException; | ||
| 6 | -import java.io.InputStreamReader; | ||
| 7 | -import javax.servlet.ReadListener; | ||
| 8 | -import javax.servlet.ServletInputStream; | ||
| 9 | -import javax.servlet.ServletResponse; | ||
| 10 | -import javax.servlet.http.HttpServletRequest; | ||
| 11 | -import javax.servlet.http.HttpServletRequestWrapper; | ||
| 12 | - | ||
| 13 | -import com.ruoyi.common.utils.http.HttpHelper; | ||
| 14 | - | ||
| 15 | -/** | ||
| 16 | - * 构建可重复读取inputStream的request | ||
| 17 | - * | ||
| 18 | - * @author ruoyi | ||
| 19 | - */ | ||
| 20 | -public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { | ||
| 21 | - private final byte[] body; | ||
| 22 | - | ||
| 23 | - public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException { | ||
| 24 | - super(request); | ||
| 25 | - request.setCharacterEncoding("UTF-8"); | ||
| 26 | - response.setCharacterEncoding("UTF-8"); | ||
| 27 | - | ||
| 28 | - body = HttpHelper.getBodyString(request).getBytes("UTF-8"); | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | - @Override | ||
| 32 | - public BufferedReader getReader() throws IOException { | ||
| 33 | - return new BufferedReader(new InputStreamReader(getInputStream())); | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - @Override | ||
| 37 | - public ServletInputStream getInputStream() throws IOException { | ||
| 38 | - | ||
| 39 | - final ByteArrayInputStream bais = new ByteArrayInputStream(body); | ||
| 40 | - | ||
| 41 | - return new ServletInputStream() { | ||
| 42 | - | ||
| 43 | - @Override | ||
| 44 | - public int read() throws IOException { | ||
| 45 | - return bais.read(); | ||
| 46 | - } | ||
| 47 | - | ||
| 48 | - @Override | ||
| 49 | - public boolean isFinished() { | ||
| 50 | - return false; | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - @Override | ||
| 54 | - public boolean isReady() { | ||
| 55 | - return false; | ||
| 56 | - } | ||
| 57 | - | ||
| 58 | - @Override | ||
| 59 | - public void setReadListener(ReadListener readListener) { | ||
| 60 | - | ||
| 61 | - } | ||
| 62 | - }; | ||
| 63 | - } | ||
| 64 | -} |
src/main/java/cn/iocoder/dashboard/framework/web/config/WebConfiguration.java
| 1 | package cn.iocoder.dashboard.framework.web.config; | 1 | package cn.iocoder.dashboard.framework.web.config; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.dashboard.framework.web.core.filter.RequestBodyCacheFilter; | ||
| 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 4 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 4 | import org.springframework.context.annotation.Bean; | 5 | import org.springframework.context.annotation.Bean; |
| 5 | import org.springframework.context.annotation.Configuration; | 6 | import org.springframework.context.annotation.Configuration; |
| @@ -50,4 +51,13 @@ public class WebConfiguration implements WebMvcConfigurer { | @@ -50,4 +51,13 @@ public class WebConfiguration implements WebMvcConfigurer { | ||
| 50 | return new CorsFilter(source); | 51 | return new CorsFilter(source); |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 54 | + /** | ||
| 55 | + * 创建 RequestBodyCacheFilter Bean,可重复读取请求内容 | ||
| 56 | + */ | ||
| 57 | + @Bean | ||
| 58 | + @Order(Integer.MIN_VALUE) | ||
| 59 | + public RequestBodyCacheFilter requestBodyCacheFilter() { | ||
| 60 | + return new RequestBodyCacheFilter(); | ||
| 61 | + } | ||
| 62 | + | ||
| 53 | } | 63 | } |
src/main/java/cn/iocoder/dashboard/framework/web/core/filter/RequestBodyCacheFilter.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.web.core.filter; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import org.springframework.http.MediaType; | ||
| 5 | +import org.springframework.web.filter.OncePerRequestFilter; | ||
| 6 | +import org.springframework.web.util.ContentCachingRequestWrapper; | ||
| 7 | + | ||
| 8 | +import javax.servlet.FilterChain; | ||
| 9 | +import javax.servlet.ServletException; | ||
| 10 | +import javax.servlet.http.HttpServletRequest; | ||
| 11 | +import javax.servlet.http.HttpServletResponse; | ||
| 12 | +import java.io.IOException; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Request Body 缓存 Filter,实现它的可重复读取 | ||
| 16 | + * | ||
| 17 | + * 基于 Spring 提供的 {@link org.springframework.web.util.ContentCachingRequestWrapper} 实现 | ||
| 18 | + * | ||
| 19 | + * @author 芋道源码 | ||
| 20 | + */ | ||
| 21 | +public class RequestBodyCacheFilter extends OncePerRequestFilter { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) | ||
| 25 | + throws IOException, ServletException { | ||
| 26 | + filterChain.doFilter(new ContentCachingRequestWrapper(request), response); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + @Override | ||
| 30 | + protected boolean shouldNotFilter(HttpServletRequest request) { | ||
| 31 | + // 只处理 json 请求内容 | ||
| 32 | + return !StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |