原理:自定义过滤器类,继承 javax.servlet.Filter,在 doFilter 接口中实现对HTTP请求和回复的过滤
1. LogFilter:实现过滤功能
package com.test.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.InetAddress;
import java.util.Calendar;
@WebFilter(urlPatterns = "/*")
public class LogFilter implements Filter {
@Override
public void init(FilterConfig fConfig) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if((servletRequest instanceof HttpServletRequest) == false) {
System.out.println();
filterChain.doFilter(servletRequest, servletResponse);
}
else
{
int y, m, d, h, min, s;
Calendar cal=Calendar.getInstance();
y=cal.get(Calendar.YEAR);
m=cal.get(Calendar.MONTH);
d=cal.get(Calendar.DATE);
h=cal.get(Calendar.HOUR_OF_DAY);
min=cal.get(Calendar.MINUTE);
s=cal.get(Calendar.SECOND);
java.lang.String outputStr = String.format(
"\n[%04d-02%d-%02d %02d:%02d:%02d] LogFilter Front\n", y, m, d, h, min, s);
System.out.println(outputStr);
FilterHttpServletRequest filterReq =
new FilterHttpServletRequest((HttpServletRequest)servletRequest);
System.out.println(filterReq.getRemoteHost());
System.out.println(filterReq.getContextPath());
System.out.println(filterReq.getRequestURL());
System.out.println(filterReq.getRequestURI());
System.out.println(filterReq.getQueryString());
BufferedReader br;
try {
br = filterReq.getReader();
String str, wholeParams = "";
while((str = br.readLine()) != null){
wholeParams += str;
}
System.out.println(wholeParams);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println();
FilterHttpServletResponse filterResp =
new FilterHttpServletResponse((HttpServletResponse)servletResponse);
filterChain.doFilter(filterReq, filterResp);
cal=Calendar.getInstance();
y=cal.get(Calendar.YEAR);
m=cal.get(Calendar.MONTH);
d=cal.get(Calendar.DATE);
h=cal.get(Calendar.HOUR_OF_DAY);
min=cal.get(Calendar.MINUTE);
s=cal.get(Calendar.SECOND);
outputStr = String.format(
"\n[%04d-02%d-%02d %02d:%02d:%02d] LogFilter Post\n", y, m, d, h, min, s);
System.out.println(outputStr);
System.out.println(filterResp.getResponseBody());
System.out.println();
}
}
}
2. FilterHttpServletRequest:包装HTTP请求
package com.test.filter;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class FilterHttpServletRequest extends HttpServletRequestWrapper {
private byte[] cachedBody;
public FilterHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream is = request.getInputStream();
this.cachedBody = StreamUtils.copyToByteArray(is);
}
@Override
public BufferedReader getReader() throws IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new FilterServletInputStream(this.cachedBody);
}
}
package com.test.filter;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
class FilterServletInputStream extends ServletInputStream {
private InputStream inputStream;
public FilterServletInputStream(byte[] cachedBody) {
this.inputStream = new ByteArrayInputStream(cachedBody);
}
@Override
public boolean isFinished() {
try {
return inputStream.available() == 0;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
@Override
public int read() throws IOException {
return inputStream.read();
}
}
3. FilterHttpServletResponse:包装HTTP回复
package com.test.filter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
class FilterHttpServletResponse extends HttpServletResponseWrapper {
private volatile FilterServletOutputStream outStream;
private PrintWriter printWriter;
public FilterHttpServletResponse(HttpServletResponse response) {
super(response);
}
@Override
public PrintWriter getWriter() throws IOException {
synchronized (this) {
if (printWriter == null) {
outStream = new FilterServletOutputStream(super.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(outStream,getResponse().getCharacterEncoding());
printWriter = new PrintWriter(osw);
}
}
return printWriter;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
synchronized (this) {
if (outStream == null) {
outStream = new FilterServletOutputStream(super.getOutputStream());
}
}
return outStream;
}
// 获取服务器回复内容
public String getResponseBody() {
return (outStream == null) ? null : new String(outStream.getWroteInfo());
}
}
package com.test.filter;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
class FilterServletOutputStream extends ServletOutputStream {
private ServletOutputStream output;
private ByteArrayOutputStream copy=new ByteArrayOutputStream();
public FilterServletOutputStream(ServletOutputStream output) {
super();
this.output = output;
}
@Override
public boolean isReady() {
return output.isReady();
}
@Override
public void setWriteListener(WriteListener arg0) {
output.setWriteListener(arg0);
}
@Override
public void write(int b) throws IOException {
output.write(b);
copy.write(b);
}
@Override
public void write(byte[] b) throws IOException {
output.write(b);
copy.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
output.write(b,off,len);
copy.write(b,off,len);
}
public byte[] getWroteInfo() {
return copy.toByteArray();
}
@Override
public void flush() throws IOException {
output.flush();
copy.close();
}
@Override
public void close() throws IOException {
output.close();
copy.close();
}
}
参考:
使HttpServletRequest中getReader()和getInputStream()可重复使用 - 道常 - 博客园
HttpServletRequestWrapper,HttpServletResponseWrapper在过滤器Filter中的使用_苦咖啡-coffe的博客-CSDN博客