在拦截器中读取request参数,解决在controller中无法二次读取的问题

网友投稿 337 2022-11-28

在拦截器中读取request参数,解决在controller中无法二次读取的问题

目录拦截器中读取request参数,在controller中无法二次读取新建类添加过滤器使用拦截器时,controller中不能再次获取body中的参数解决办法1、获取body信息2、重新写入3、注册过滤器

拦截器中读取request参数,在controller中无法二次读取

新建类

package com.ouyeelbuy.mc.common.base;

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

/**

* @author robin.zhang

* @date $

* @description 解决在request的数据流只能读取一次的问题

*/

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();

}

@Override

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;

}

@Overridhttp://e

public BufferedReader getReader() throws IOException {

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

}

public String getBody() {

return this.body;

}

}

添加过滤器

package com.ouyeelbuy.mc.common.filter;

import com.ouyeelbuy.mc.common.base.RequestWrapper;

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

/**

* @author robin.zhang

* @date $

* @description 解决request数据流只能读取一次的问题

*/

@Component

public class RequestFilter 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 {

filterChain.doFilter(requestWrapper, servletResponse);

}

}

@Override

public void destroy() {

}

}

然后注册这个过滤器到spring容器中,问题解决!

使用拦截器时,controller中不能再次获取body中的参数

报错信息:从报错信息可以看出,io流已经关闭。这是由于拦截器读取了body中的参数信息,导致controller不能再次读取。

I/O error while reading input message; nested exception is java.io.IOException: Stream closed

解决办法

在拦截器读取到body信息后,再次将内容写入

1、获取body信息

import javax.servlet.ReadListener;

import javax.servlet.ServletInputStream;

import javax.servlet.ServletRequest;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletRequestWrapper;

import java.io.*;

import java.nio.charset.Charset;

/**

* 保存流

*/

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

private final byte[] body;

public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {

super(request);

String sessionStream = getBodyString(request);

body = sessionStream.getBytes(Charset.forName("UTF-8"));

}

/**

* 获取请求Body

*

* @param request

* @return

*/

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();

}

/**

* Description: 复制输入流

*

* @param inputStream

* @return

*/

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) {

}

};

}

}

2、重新写入

import org.springframework.core.annotation.Order;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

// 表示执行过滤顺序,值越小,越先执行

@Order(1)

// 配置需要过滤的地址

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

public class BodyReaderFilter implements Filter {

@Override

public void init(FilterConfig filterConfig) throws ServletException {

// System.out.println("--------------过滤器初始化------------");

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

// System.out.println("--------------执行过滤操作------------");

// 防止流读取一次后就没有了, 所以需要将流继续写出去

HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(httpServletRequest);

filterChain.doFilter(requestWrapper, servletResponse);

}

@Override

public void destroy() {

// System.out.println("--------------过滤器销毁------------");

}

}

3、注册过滤器

import org.sprinhttp://gframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.web.servlet.ServletComponentScan;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication

@EnableFeignClients

@EnableDiscoveryClient

// 注册过滤器注解

@ServletComponentScan

public class WebPlatformApplication {

public static void main(String[] args) {

SpringApplication.run(WebPlatformApplication.class);

}

}

添加完成后,运行正常!

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

上一篇:Objective-C语法之内存管理
下一篇:thinkphp 使用标签库的步骤
相关文章

 发表评论

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