- 使用場景:通過request能獲取到一次body中的值账嚎,有時候我們需要多次獲取body中的值的需求裸扶,因此需要對流再次封裝再次傳遞
- 例如:在controller中我們通過@RequestBody注解來獲取前端傳過來的json數據左驾,這里已經使用了一次request來獲取body中的值蕉堰。等我們有需求,在完成這一個controller時搁骑,通過aop來記錄一下操作記錄,則可能會需要再次獲取到body中的值
- 獲取request的參數方法
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
a.重寫自定義HttpServletRequestWrapper
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
public String _body;
public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
StringBuffer sBuffer = new StringBuffer();
BufferedReader bufferedReader = request.getReader();
String line;
while ((line = bufferedReader.readLine()) != null) {
sBuffer.append(line);
}
_body = sBuffer.toString();
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
return new ServletInputStream() {
@Override
public int read() {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
b. 自定義過濾器Filter
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new MultiReadHttpServletRequest((HttpServletRequest) request);
}
//獲取請求中的流如何又固,將取出來的字符串仲器,再次轉換成流,然后把它放入到新request對象中仰冠。
// 在chain.doFiler方法中傳遞新的request對象
if(requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
}
}
c.在配置文件進行配置
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean filterRegist() {
FilterRegistrationBean frBean = new FilterRegistrationBean();
frBean.setFilter(new MyFilter());
frBean.addUrlPatterns("/*");
System.out.println("filter");
return frBean;
}
}
提醒一下:如果你進行文件導入時使用了MultiPartFile 這個組件來上傳文件乏冀,還是會報 getInputSteam()has already exists的異常。所以你只需要將上傳文件的那個請求進行過濾就可以了
- 過濾器修改如下:
public class MyFilter implements Filter {
private final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
Arrays.asList("/writeExcelToDir")));
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
HttpServletRequest servletRequest = (HttpServletRequest) request;
String requestURI = servletRequest.getRequestURI();
if (ALLOWED_PATHS.contains(requestURI)){
chain.doFilter(servletRequest,response);
}else {
requestWrapper = new MultiReadHttpServletRequest(servletRequest);
//獲取請求中的流如何洋只,將取出來的字符串辆沦,再次轉換成流昼捍,然后把它放入到新request對象中。
// 在chain.doFiler方法中傳遞新的request對象
chain.doFilter(requestWrapper, response);
}
}
}