我们只能从 HttpServletRequest 读取一次,因此我们必须在读取请求之前在过滤器中使用HttpServletRequestWrapper并多次使用包装器进行后续调用。
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.dbs.bds.ingestion.util.MultiReadRequestWrapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SessionValidationFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
try {
log.debug("inside filter");
HttpServletRequest httpServletRequest = new MultiReadRequestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (Exception ex) {
log.error("error inside filter:{}", ex.getMessage());
}
}
}
下面是我们在上面过滤器中使用的 Wrapper 的代码。
import org.apache.commons.io.input.BoundedInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class MultiReadRequestWrapper extends HttpServletRequestWrapper {
private static final Logger LOG = LoggerFactory.getLogger(MultiReadRequestWrapper.class);
// We include a max byte size to protect against malicious requests,
//since this all has to be read into memory
public static final Integer MAX_BYTE_SIZE = 1_048_576; // 1 MB
private StringBuilder body;
public MultiReadRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = new StringBuilder("");
try (
InputStream bounded = new BoundedInputStream(request.getInputStream(), MAX_BYTE_SIZE);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bounded));){
String line;
while ((line = bufferedReader.readLine()) != null) {
body.append(line);
}
} catch(Exception e) {
LOG.error(e.getMessage());
}
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.toString().getBytes());
return new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
//do nothing
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
现在将上述过滤器公开为 bean
@Bean(name = "sessionValidationFilter")
public Filter getSessionValidationFilter() {
return new SessionValidationFilter();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean sessionValidationFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getSessionValidationFilter());
registration.addUrlPatterns("/v1/create/record");
registration.setName("sessionValidationFilter");
return registration;
}