返回顶部
首页 > 资讯 > 后端开发 > Python >关于Filter中获取请求体body后再次读取的问题
  • 887
分享到

关于Filter中获取请求体body后再次读取的问题

2024-04-02 19:04:59 887人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

Filter获取请求体body再次读取 工作需要,要将请求和响应做一些处理,写一个filter拦截请求,拦截request中body内容后,字符流关闭,controller取到的请求

Filter获取请求体body再次读取

工作需要,要将请求和响应做一些处理,写一个filter拦截请求,拦截request中body内容后,字符流关闭,controller取到的请求体内容为空。

从Request中获取输入流,InputStream只能被读取一次。

解决方案

给request添加一个包装类BodyWrapper,继承httpservletRequestWrapper,

先从request中取输入流,读取流中的数据,然后重写getInputStream()和getReader()方法。

chain.doFilter(requestWrapper, response);
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.NIO.charset.Charset;
import java.util.Enumeration;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.Http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.xera.fsafesso.HttpHelper;
public class BodyWrapper extends HttpServletRequestWrapper {undefined
    private final byte[] body;
    public BodyWrapper(HttpServletRequest request) throws IOException {undefined
        super(request);
        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
    }
    @Override
    public BufferedReader getReader() throws IOException {undefined
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
    @Override
    public ServletInputStream getInputStream() throws IOException {undefined
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream(){undefined
            @Override
            public int read() throws IOException {undefined
                return bais.read();
            }
            @Override
            public boolean isFinished() {undefined
                return false;
            }
            @Override
            public boolean isReady() {undefined
                return false;
            }
            @Override
            public void setReadListener(ReadListener arg0) {undefined
            }
        };
    }
    @Override
    public String getHeader(String name) {undefined
        return super.getHeader(name);
    }
    @Override
    public Enumeration<String> getHeaderNames() {undefined
        return super.getHeaderNames();
    }
    @Override
    public Enumeration<String> getHeaders(String name) {undefined
        return super.getHeaders(name);
    }
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ServletRequest;
public class HttpHelper {undefined
     
    public static String getBodyString(ServletRequest request) {undefined
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {undefined
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {undefined
                sb.append(line);
            }
        } catch (IOException e) {undefined
            e.printStackTrace();
        } finally {undefined
            if (inputStream != null) {undefined
                try {undefined
                    inputStream.close();
                } catch (IOException e) {undefined
                    e.printStackTrace();
                }
            }
            if (reader != null) {undefined
                try {undefined
                    reader.close();
                } catch (IOException e) {undefined
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

Filter中写法如下:

HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            Map<String, String> requestMap = this.getTypesafeRequestMap(httpServletRequest);
            requestWrapper = new BodyWrapper(httpServletRequest);
            String body = HttpHelper.getBodyString(requestWrapper);
            log.info("loggingFilter---请求路径 {},请求参数 {},请求体内容 {}",httpServletRequest.getRequestURL(),requestMap,body);
      chain.doFilter(requestWrapper, response);

在使用注解的方式(即@WEBFilter)声明过滤器时,

需要再main函数类上添加@ServletComponentScan(basePackages = "此处写明类地址,格式为包名+类名(如com.*) 

Http请求解决body流一旦被读取了就无法二次读取情况

相信大家在工作当中,经常会遇到需要处理http请求及响应body的场景,这里最大的问题应该就是body中流以但被读取就无法二次读取了。

解决request请求流只能读取一次的问题

我们编写一个过滤器,这样就可以重写body了

package com.interceptor; 
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
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 javax.servlet.http.HttpServletResponse;
 
public class MyFilter implements Filter {
    private static String privateKey ;    
    public String getPrivateKey() { 
		return privateKey;
	}
	public void setPrivateKey(String key) {
		privateKey = key;
	}
 
	
    List<String> ignore = Arrays.asList("/xxxx");
    
    
    List<String> ignorePrefix = Arrays.asList( "/CSS/", "/pop/", "/js/", "/static/", "/images/", "/favicon.ico");
    
    
    List<String> ignoreSuffix = Arrays.asList("/test");
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    	//过滤器初始化
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 防止流读取一次后就没有了, 所以需要将流继续写出去
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String uri = request.getServletPath();
        response.setContentType("application/JSON;charset=UTF-8");
        ServletRequest requestWrapper = null;
        if(canIgnore(uri)) {
        	requestWrapper = new MyFilterBodyReaderHttpServletRequestWrapper(request);
        	filterChain.doFilter(requestWrapper, response);
        	return;
        }
    	try {
    		requestWrapper = new MyFilterBodyReaderHttpServletRequestWrapper(request, response, privateKey);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
    	filterChain.doFilter(requestWrapper, servletResponse);
    }
 
    @Override
    public void destroy() {
    	//过滤器销毁
    }
    
    private boolean canIgnore(String uri) {  
    	
    	logger.info("过滤器  request  uri : {} ",uri);
        boolean isExcludedPage = false;
        for (String page : ignore) {
            if (uri.equals(page)) {
            	logger.info("请求路径不需要拦截,忽略该uri : {} ",uri);
                isExcludedPage = true;
                break;
            }
        }
        
        for (String prefix : ignorePrefix) {
            if (uri.startsWith(prefix)) {
            	logger.info("请求路径前缀[{}],不拦截该uri : {} ", prefix, uri);
                isExcludedPage = true;
                break;
            }
        }
        
        for (String prefix : ignoreSuffix) {
        	if (uri.endsWith(prefix)) {
        		logger.info("请求路径后缀[{}],不拦截该uri : {} ", prefix, uri);
        		isExcludedPage = true;
        		break;
        	}
        }
        return isExcludedPage;
    }
} 
 
  
package com.interceptor; 
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Map;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
 

public class MyFilterBodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;
    
    public MyFilterBodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    	super(request);
    	String sessionStream = getBodyString(request);
    	body = sessionStream.getBytes(Charset.forName("UTF-8"));
    }
 
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public MyFilterBodyReaderHttpServletRequestWrapper(HttpServletRequest request,HttpServletResponse response, String clienTKEy, Boolean ignoreCheckSign) throws Exception {
        super(request);
        String sessionStream = getBodyString(request);
        Map paramMap = (Map) JSON.parse(sessionStream);
      
        body = json.getBytes(Charset.forName("UTF-8"));
    }
    
    
    public String getBodyString(final ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = cloneInputStream(request.getInputStream());
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
    
    
    public String getBodyString() {
    	if (body == null) {
            return null;
        }
        String str = new String(body);
        return str;
    }
 
    
    public InputStream cloneInputStream(ServletInputStream inputStream) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        try {
            while ((len = inputStream.read(buffer)) > -1) {
                byteArrayOutputStream.write(buffer, 0, len);
            }
            byteArrayOutputStream.flush();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        return byteArrayInputStream;
    }
    @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) {
            }
        };
    }
} 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: 关于Filter中获取请求体body后再次读取的问题

本文链接: https://lsjlt.com/news/142523.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作