Python 官方文档:入门教程 => 点击学习
Filter获取请求体body再次读取 工作需要,要将请求和响应做一些处理,写一个filter拦截请求,拦截request中body内容后,字符流关闭,controller取到的请求
工作需要,要将请求和响应做一些处理,写一个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的场景,这里最大的问题应该就是body中流以但被读取就无法二次读取了。
我们编写一个过滤器,这样就可以重写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
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0