@RequestBody注解参数的接口以 application/json 作为请求头Content-Type的类型,以输入流的方式读取json类型参数,因为是输入流,所以只能读取一次,在一些项目中,我们可能需要在controller之前使用到请求参数,比如拦截器、过滤器、Aspect,为了满足这些多次获取输入流中参数需求,利用拦截器对request进行改造;
创建一个类ContentCachingRequestWrapper 继承 HttpServletRequestWrapper
包括一个内部类RequestCachingInputStream 继承 ServletInputStream
构造参数为HttpServletRequest 的构造方法
将输入流中数据缓存到ByteArrayInputStream中,可以重复读取
import org.apache.commons.io.IOUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper{
private byte[] body;
private BufferedReader reader;
private ServletInputStream inputStream;
public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException{
super(request);
loadBody(request);
}
private void loadBody(HttpServletRequest request) throws IOException{
body = IOUtils.toByteArray(request.getInputStream());
inputStream = new RequestCachingInputStream(body);
}
public byte[] getBody() {
return body;
}
public void setBody(byte[] body){
this.body=body;
inputStream = new RequestCachingInputStream(body);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (inputStream != null) {
ServletInputStream tmp = this.inputStream;
this.inputStream = new RequestCachingInputStream(body);
return tmp;
return inputStream;
}
return super.getInputStream();
}
@Override
public BufferedReader getReader() throws IOException {
if (reader == null) {
reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding()));
}
return reader;
}
private static class RequestCachingInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public RequestCachingInputStream(byte[] bytes) {
inputStream = new ByteArrayInputStream(bytes);
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public boolean isFinished() {
return inputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readlistener) {
}
}
}
创建过滤器配置类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CharacterEncodingFilter;
import sjy.notion.notion.app.filter.ValidateFilter;
import javax.servlet.DispatcherType;
/**
* @author zhang
* @date 2019/3/29 上午12:01
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean validateFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new ValidateFilter());
registration.addUrlPatterns("/*");
registration.setName("validateFilter");
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}
创建过滤器过滤request
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class ValidateFilter implements Filter {
private static Logger log = LoggerFactory.getLogger(ValidateFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
chain.doFilter(requestWrapper, response);
}
}
request.getInputStream() 就可以重复获取数据
网友评论