使用ServletInputStream在拦截器或过滤器中应用后重写

网友投稿 799 2022-11-28

使用ServletInputStream在-或过滤器中应用后重写

使用ServletInputStream在-或过滤器中应用后重写

目录ServletInputStream在-或过滤器应用后重写在-种使用了request.getInputStream()或者getReader()问题描述原因分析如何处理

ServletInputStream在-或过滤器应用后重写

ServletInputStream inputStream = super.getInputStream();

StringBuilder sb = new StringBuilder();

BufferedReader reader = null;

try {

reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));

String line = "";

while ((line = reader.readLine()) != null) {

sb.append(line);

}MxjYC

} catch (IOException e) {

e.printStackTrace();

} finally {

if (servletInputStream != null) {

try {

servletInputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if (reader != null) {

try {

reader.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//使用ServletInputStream中数据代码

byte[] bytes = sb.getBytes("UTF-8");

final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

return new ServletInputStream() {

@Override

public boolean isFinished() {

return false;

}

@Override

public boolean isReady() {

return false;

}

@Override

public void setReadListener(ReadListener readListener) {

}

@Override

public int read() throws IOException {

return bais.read();

}

};

在-种使用了request.getInputStream()或者getRhttp://eader()

导致在controller中无法获取请求参数

问题描述

在-种使用了request.getInputStream()或者getReader(),然后在controller接口种使用了@requestbody ,导致controller中无法获取入参,报错:HttpMessageNotReadableException: Required request body is missing:

原因分析

ServletRequest中getReader()和getInputStream()只能调用一次。而又由于@RequestBody注解获取输出参数的方式也是根据流的方式获取的。所以我们前面使用流获取后,后面的@RequestBody就获取不到对应的输入流了。

为什么取不到输入流了???因为流对应的是数据,数据放在内存中,有的是部分放在内存中。

read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。

所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据。

javaAPI中有一个方法public void reset() 这个方法就是可以重置pos为起始位置,但是不是所有的IO读取流都可以调用该方法!ServletInputStream是不能调用reset方法,这就导致了只能调用一次getInputStream()。

如何处理

重写HttpServletRequestWrapper把request保存下来,然后通过过滤器把保存下来的request再填充进去,这样就可以多次读取request了。

第一步:定义过滤器

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

@WebFilter(urlPatterns = "/*", filterName = "channelFilter")

public class ChannelFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

throws IOException, ServletException {

ServletRequest requestWrapper = null;

if (servletRequest instanceof HttpServletRequest) {

requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);

}

if (requestWrapper == null) {

filterChain.doFilter(servletRequest, servletResponse);

} else {

System.out.println("进入了过滤器。。。。。");

filterChain.doFilter(requestWrapper, servletResponse);

}

}

@Override

public void destroy() {

}

}

第二步:重写RequestWrapper类

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

public class RequestWrapper extends HttpServletRequestWrapper {

private final String body;

public RequestWrapper(HttpServletRequest request) {

super(request);

StringBuilder stringBuilder = new StringBuilder();

BufferedReader bufferedReader = null;

InputStream inputStream = null;

try {

inputStream = request.getInputStream();

if (inputStream != null) {

bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

char[] charBuffer = new char[128];

int bytesRead = -1;

while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {

stringBuilder.append(charBuffer, 0, bytesRead);

}

} else {

stringBuilder.append("");

}

} catch (IOException ex) {

} finally {

if (inputStream != null) {

try {

inputStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if (bufferedReader != null) {

try {

bufferedReader.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

body = stringBuilder.toString();

}

@OverriMxjYCde

public ServletInputStream getInputStream() throws IOException {

final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());

ServletInputStream servletInputStream = new ServletInputStream() {

@Override

public boolean isFinished() {

return false;

}

@Override

public boolean isReady() {

return false;

}

@Override

public void setReadListener(ReadListener readListener) {

}

@Override

public int read() throws IOException {

return byteArrayInputStream.read();

}

};

return servletInputStream;

}

@Override

public BufferedReader getReader() throws IOException {

return new BufferedReader(new InputStreamReader(this.getInputStream()));

}

public String getBody() {

return this.body;

}

}

第三步:在启动类中注册过滤器

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:POJ 2378 Tree Cutting——树形dp
下一篇:HDU - 3586 Information Disturbing——树形dp
相关文章

 发表评论

暂时没有评论,来抢沙发吧~