最近在寫日志管理,想着使用攔截器加注解的方式,但是遇到了一個問題,就是如果使用@RequestBody注解接收的參數只能讀取一次,造成了我在攔截器中如果接收了參數,在Controller層就接收不到了,為了解決這個問題,在網上查了方法。自定義一個MyRequestWrapper 繼承 HttpServletRequestWrapper不多說,看代碼:
package cn.huimin100.cms.handler;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
* 與HttpServletRequestWrapperFilter配合使用,保證@RequestBody注解的參數可以讀取兩次
* 因為要在攔截器中獲取參數
*/
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(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));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}
需要結合過濾器使用:
package cn.huimin100.cms.handler;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 該過濾器與MyRequestWrapper配合使用,可以讓@RequestBody注解的參數至少可以讀取兩次,
* 從而使得在攔截器中可以獲取@RequestBody注解的參數。
*/
@WebFilter(filterName="HttpServletRequestWrapperFilter",urlPatterns="/*")
public class HttpServletRequestWrapperFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper= null;
if(request instanceof HttpServletRequest){
requestWrapper = new MyRequestWrapper((HttpServletRequest) request);
}
if(null == requestWrapper){
filterChain.doFilter(request,servletResponse);
}else{
filterChain.doFilter(requestWrapper,servletResponse);
}
}
@Override
public void destroy() {
}
}
攔截器中這樣獲取參數
package
cn.huimin100.cms.handler
;
import
cn.huimin100.cms.config.
LogAnnotation
;
import
cn.huimin100.cms.mapper.newcms.ActionLogsMapper
;
import
cn.huimin100.cms.pojo.po.ActionLogs
;
import
cn.huimin100.cms.util.DateUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
org.apache.commons.lang.time.DateFormatUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.
Autowired
;
import
org.springframework.web.method.HandlerMethod
;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.lang.reflect.Method
;
import
java.util.Date
;
import
java.util.Map
;
/**
* 在讀取@RequestBody注解的參數的時候,需要配合MyRequestWrapper使用
* 一遍保證這些參數可以在Controller層再次讀取
*/
public class
LogManageInterceptor
extends
HandlerInterceptorAdapter {
private final
Logger
logger
= LoggerFactory.
getLogger
(LogManageInterceptor.
class
)
;
@Autowired
private
ActionLogsMapper
logMapper
;
public static final
String
USER_NAME
=
"user__name"
;
public static final
String
BRANCH_ID
=
"branch__id"
;
public static final
String
USER_ID
=
"user__id"
;
@Override
public boolean
preHandle
(HttpServletRequest request
,
HttpServletResponse response
,
Object handler)
throws
Exception {
if
(handler
instanceof
HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler
;
Method method = handlerMethod.getMethod()
;
LogAnnotation
annotation = method.getAnnotation(
LogAnnotation
.
class
)
;
if
(annotation !=
null
){
try
{
ActionLogs log =
new
ActionLogs()
;
//操作類型
log.setAction(annotation.action().getCode())
;
//操作目標方法
log.setCategory(annotation.targetMethod().getCode())
;
//操作人姓名
log.setActionTime(DateFormatUtils.
format
(
new
Date()
,
DateUtil.
DATETIME_DEFAULT_FORMAT
))
;
log.setIsmiddlemode(
2
)
;
Map<String
,
String[]> parameterMap = request.getParameterMap()
;
if
(parameterMap ==
null
|| parameterMap.isEmpty()){
MyRequestWrapper myRequestWrapper =
new
MyRequestWrapper((HttpServletRequest) request)
;
String body = myRequestWrapper.getBody()
;
JSONObject jsonObject = JSONObject.
parseObject
(body)
;
log.setOperator(jsonObject.getString(
USER_NAME
))
;
log.setOperatorId(jsonObject.getInteger(
USER_ID
))
;
log.setBranchId(jsonObject.getInteger(
BRANCH_ID
))
;
}
else
{
log.setOperator(request.getParameter(
USER_NAME
))
;
log.setOperatorId(Integer.
valueOf
(request.getParameter(
USER_ID
)))
;
log.setBranchId(Integer.
valueOf
(request.getParameter(
BRANCH_ID
)))
;
}
logMapper
.insertSelective(log)
;
}
catch
(Exception e){
logger
.error(
"記錄操作日志錯誤 e:{}"
,
e)
;
}
}
}
return true;
}
}