本文的实现根据网友的文章-ServletRequest中getReader()和getInputStream()只能调用一次的解决办法
我做的是springmvc项目,项目经理提出需求:每一个请求都要记录放到日志的功能,记录的内容有IP地址、请求的路径、和访问的参数,并定期转移日志。
遇到的问题就是:ServletRequest的getReader()和getInputStream()两个方法只能被调用一次,而且不能两个都调用。
文章请参考网友的文章,很细腻。但是看了之后可能需要思考一些事情才能解决这个问题。
好啦,开始show 代码啦。
1、Filter部分代码
package com.xxx.xxx.WebService.Filter;
import java.io.BufferedReader;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.json.JSONObject;
public class HttpServletRequestReplacedFilter implements Filter{
private static final Log logger = LogFactory.getLog("requestLogInterceptor");
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(request instanceof HttpServletRequest) {
requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
}
if(null == requestWrapper) {
chain.doFilter(request, response);
} else {
BufferedReader br = requestWrapper.getReader();
String str = null,retStr="";
while ((str = br.readLine()) != null) {
retStr += str;
}
String ip = requestWrapper.getRemoteAddr();
StringBuffer url = ((HttpServletRequest) request).getRequestURL();
JSONObject jo = new JSONObject();
jo.put("ip", ip);
jo.put("url", url.toString());
jo.put("content", retStr);
logger.info(jo);
chain.doFilter(requestWrapper, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
2、BodyReaderHttpServletRequestWrapper部分代码
package com.xxx.xxx.WebService.Filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang.StringUtils;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)
throws IOException {
super(request);
body = readBytes(request.getReader(), "utf-8");
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}
/**
* 通过BufferedReader和字符编码集转换成byte数组
* @param br
* @param encoding
* @return
* @throws IOException
*/
private byte[] readBytes(BufferedReader br,String encoding) throws IOException{
String str = null,retStr="";
while ((str = br.readLine()) != null) {
retStr += str;
}
if (StringUtils.isNotBlank(retStr)) {
return retStr.getBytes(Charset.forName(encoding));
}
return null;
}
}
3、web.xml中的代码
<filter>
<filter-name>springFilter</filter-name>
<filter-class>com.xxx.xxx.WebService.Filter.HttpServletRequestReplacedFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置好了,就可以测试一下啦
日志文件中产生了数据