今天尝试在切面中读取 request 请求,校验请求的参数,解析异常则报错
但是,在 切面读取了一次 request 后,再到 controller 的时候,request 就变成了空的
找了一圈找到这种方法,通过继承 HttpServletRequestWrapper
,来操作 HttpServletRequest
package xxxxx;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.Collections;
/**
* Author: heatdeath
* Date: 2018/5/15
* Desc:
*/
@Aspect
@Component
public class RestServiceValidReqAndHandleExc {
private static final Logger logger = LoggerFactory.getLogger(RestServiceValidReqAndHandleExc.class);
@Pointcut("@annotation(web.aspect.annotation.AnnForValidReqAndHandleExc)")
public void parseRequestPointcut() {
}
@Around("parseRequestPointcut()")
public Object parseHttpRequest(ProceedingJoinPoint joinPoint) {
HttpServletRequest request = (HttpServletRequest) joinPoint.getArgs()[0];
ResettableStreamHttpServletRequest wrappedRequest = new ResettableStreamHttpServletRequest(request);
try {
wrappedRequest.setCharacterEncoding("utf-8");
String bodyStr = HttpServletRequestUtil.readHttpServletRequestBody(wrappedRequest);
if (StringUtils.isEmpty(bodyStr))
return ResultMessageUtil.getErrorResultMessage(new ResultMessage(), ErrorNumConsts.PARAM_ERROR,
"请求数据不能为空!");
} catch (Exception e) {
System.out.println(ExceptionUtils.getExceptionStackTrace(e));
return ResultMessageUtil.getErrorResultMessage(new ResultMessage(), ErrorNumConsts.PARAM_ERROR,
"解析请求数据错误!");
}
try {
wrappedRequest.resetInputStream();
Object[] args = Collections.singletonList(wrappedRequest).toArray();
return joinPoint.proceed(args);
} catch (Throwable t) {
logger.error(ExceptionUtils.getExceptionStackTrace(t));
return ResultMessageUtil.getErrorResultMessage(new ResultMessage(), ErrorNumConsts.OPERATION_ERROR,
"操作失败,请再次尝试!");
}
}
private static class ResettableStreamHttpServletRequest extends
HttpServletRequestWrapper {
private byte[] rawData;
private HttpServletRequest request;
private ResettableServletInputStream servletStream;
ResettableStreamHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
this.servletStream = new ResettableServletInputStream();
}
void resetInputStream() {
servletStream.stream = new ByteArrayInputStream(rawData);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}
@Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return new BufferedReader(new InputStreamReader(servletStream));
}
private class ResettableServletInputStream extends ServletInputStream {
private InputStream stream;
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
}
}
参考资料:
1、request.getInputStream()只能获取一次的问题
https://blog.csdn.net/zly9923218/article/details/52120920
2、解决在Filter中读取Request中的流后, 然后再Control中读取不到的做法
https://my.oschina.net/vernon/blog/363693
3、拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.
https://blog.csdn.net/beflyabot/article/details/78053130