上一篇写的是在Spring WebFlux中的WebFilter中实现filter方法,并获取请求body的实现,这篇是Java Servlet API中的,用于在Servlet容器中实现过滤器
@WebFilter("/*")
public static class PointFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try{
// 包装HttpServletRequest,以便多次读取请求体
HttpServletRequest httpRequest = (HttpServletRequest) request;
String url = httpRequest.getRequestURI();
log.info("PointFilter doFilter httpRequest.getRequestURI():{}", url);
String contentType = httpRequest.getContentType();
log.info("PointFilter doFilter httpRequest.getContentType():{}", contentType);
EmbeddedPointInteceptor.EmbeddedContext embeddedContext = new EmbeddedPointInteceptor.EmbeddedContext();
HOLDER.set(embeddedContext);
if (setFilter.contains(url) ||
(StringUtils.isNotEmpty(contentType) && httpRequest.getContentType().contains("multipart/form-data"))){
try {
// 继续处理请求
chain.doFilter(request, response);
} finally {
HOLDER.remove();
}
return;
} else if (StringUtils.isNotEmpty(contentType) && contentType.contains(MediaType.APPLICATION_JSON_VALUE)){
RequestWrapper wrappedRequest = new RequestWrapper(httpRequest);
// 获取请求体内容
String requestBody = getRequestBody(wrappedRequest);
// 打印请求体内容(在实际应用中,你可以将请求体内容存储到日志中或进行其他处理)
log.info("Request Body: {}" + requestBody);
try {
// 继续处理请求
chain.doFilter(wrappedRequest, response);
} finally {
HOLDER.remove();
}
return;
}
}catch (Exception e){
log.error("PointFilter doFilter:{}", e);
}
chain.doFilter(request, response);
}
public static String getRequestBody(HttpServletRequest request) throws IOException {
StringBuilder requestBody = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
requestBody.append(line);
}
}
return requestBody.toString();
}
}
关键类是RequestWrapper
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
private String body;
/**
* Wrapper的构造方法,主要是将body里的内容取出来,然后存储到对象中的body变量中,方便
* 后续复用
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
log.error("IOException 异常:{}", ex);
}
}
}
body = stringBuilder.toString();
}
/**
* 这里才是关键,这里将getInputStream重新,让它能重复获取到body里的内容,这样才不会影响后续的流程
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
// Do nothing because of X and Y.
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
/**
* 重写获取 字符流的方式
* @return
* @throws IOException
*/
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(), Charsets.UTF_8));
}
/**
* 获取body
* @return
*/
public String getBody() {
return this.body;
}
}