requestBody只能读取一次
我们一般使用filter处理body的数据,做验证或者加解密,通过以下之后再次request.getInputStream()后发现没有数据,这是因为是流,position跑到后面去了
new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
我们可以自定义一个httpServletRequest包装类httpServletRequestWrapper,覆盖之前的方法;
示例代码如下:
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
//返回参数字节数组
body = HttpRequestHelper.getBodyString(request).getBytes(StandardCharsets.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();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
}
public class HttpRequestHelper {
public static String getBodyString(HttpServletRequest request) throws IOException {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.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();
}
}
在filter中
requestWrapper = new MyRequestWrapper((HttpServletRequest) servletRequest);
之后使用即可;
public class SingFilter implements Filter {
private final String signature = "signature";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
Boolean throwEx = false;
if (servletRequest instanceof HttpServletRequest) {
requestWrapper = new MyRequestWrapper((HttpServletRequest) servletRequest);
// 获取请求Body
String requestBody = StreamUtils.copyToString(requestWrapper.getInputStream(), StandardCharsets.UTF_8);
JSONObject json = JSON.parseObject(requestBody);
if (json.get(signature) == null) {
throw new MallException("缺少信息:签名");
}
String sign = json.get(signature).toString();
json.remove(signature);
String decryptTxt = RSAUtils.keyDecrypt(sign, RSAUtils.PRIVATE);
String s = JSON.parseObject(decryptTxt).toJSONString();
if (!s.equals(json.toJSONString())) {
throwEx = true;
}
}
// 转发前先重置响应
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.reset();
if (throwEx) {
servletRequest.setAttribute("filterError", new MallException("签名信息错误!"));
servletRequest.getRequestDispatcher("/exception/error/throw").forward(servletRequest, servletResponse);
return;
}
if (requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
使用filter抛出异常捕获问题
如上
throw new MallException("缺少信息:签名");
会发现异常捕获不到,只有500的消息。
使用上面这一部分处理
if (throwEx) {
servletRequest.setAttribute("filterError", new MallException("签名信息错误!"));
servletRequest.getRequestDispatcher("/exception/error/throw").forward(servletRequest, servletResponse);
return;
}
转发到我们的异常controller
@RestController
@RequestMapping("exception/")
public class ExceptionController {
@RequestMapping("error/throw")
public JsonResult handleException(HttpServletRequest request, HttpServletResponse response) throws MallException{
// 获取过滤器中保存的异常信息
MallException ex = (MallException) request.getAttribute("filterError");
if (ex != null) {
throw ex;
}
return new JsonResult();
}
}