拦截器被用来获取用户的请求日志,好处多多。一般来说,请求参数通过GET和POST的方式传递,GET请求参数通过request.getParameterMap()方法获取,POST请求参数通过request.getInputStream()方法获取。
但是,当在项目中使用拦截器获取到请求参数后,发现controller中@RequestBody注解获取不到参数了。多番查阅发现,Spring中的request.getInputStream()和request.getReader()只能被获取到一次,而@RequestBody的底层也是通过流来请求数据。于是,有必要将拦截器中的流数据保存下来,以便controller获取到数据。
继承 HttpServletRequestWrapper类,封装HttpServletRequest请求
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
/**
* @author wangyan
* @description 获取请求参数并处理
* @date 2019/7/18 18:38
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
String sessionStream = getBodyString(request);
body = sessionStream.getBytes(Charset.forName("UTF-8"));
}
public String getBodyString(){
return new String(body,Charset.forName("UTF-8"));
}
/**
* 获取请求Body
*
* @param request
* @return
*/
public String getBodyString(final ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = cloneInputStream(request.getInputStream());
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* Description: 复制输入流
*
* @param inputStream
* @return
*/
public InputStream cloneInputStream(ServletInputStream inputStream) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
}
catch (IOException e) {
e.printStackTrace();
}
InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return byteArrayInputStream;
}
@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();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
将自定义请求 RequestWrapper 子类传递下去
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author wangyan
* @description 自定义过滤器
* @date 2019/7/19 18:26
*/
@Component
@WebFilter(urlPatterns = "/*",filterName = "channelFilter")
public class ChannelFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(ChannelFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
logger.info("================进入过滤器======================");
// 防止流读取一次后就没有了, 所以需要将流继续写出去
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
ServletRequest requestWrapper = new RequestWrapper(httpServletRequest);
filterChain.doFilter(requestWrapper, servletResponse);
}
@Override
public void destroy() {
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author wangyan
* @description 自定义拦截器
* @date 2019/7/12 10:13
*/
@Component
public class BaseInterceptor extends HandlerInterceptorAdapter {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
info("***************************【RequestBeginning】***************************");
info("----------------StartProcessingRequest----------------");
try {
Long currentTime = System.currentTimeMillis();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date(currentTime);
info("CurrentTime:{}",formatter.format(date));
info("ResponseTime:{}",(System.currentTimeMillis() - currentTime) + "ms");
String requestURL = request.getRequestURI();
info("RequestURL: {} ", requestURL);
info("GetMethod: {}", handler);
//获取请求参数
RequestWrapper requestWrapper = new RequestWrapper(request);
info("RequestBody: {}",requestWrapper.getBodyString());//这里getBodyString()方法无参数
} catch (Exception e) {
error("MVC业务处理-拦截器异常:", e);
}
info("-------------------------End-------------------------");
return true;
}
/**
* This implementation is empty.
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
logger.info("after");
}
/**
* This implementation is empty.
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
logger.info("Completion");
}
/**
* This implementation is empty.
*/
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
logger.info("Concurrent");
}
protected final void error(String msg, Object... objects) {
logger.error(msg, objects);
}
protected final void info(String msg, Object... objects) {
logger.info(msg, objects);
}
}
至此结束!!!