解决request.getInputStream()或request.getReader()只能取一次问题
程序员文章站
2024-02-02 15:54:34
...
在工作中接到一个需求,用拦截器将进来的请求做一次解密动作。我们接收的请求是post类型的,于是需用到request.getInputStream()或request.getReader()方法去读取HttpServletRequest对象里的数据。但是request.getInputStream()或request.getReader()方法只能被调用一次,我在拦截器里面调用一次之后,controller里面@ResponseBody这个注解会再调用一次,就会报错。于是查找了很多资料,最终确定一个思路,就是我取完数据之后再将数据放回去请求里面,这样@ResponseBody再去读的时候,就不会报错了。
代码参考文档链接:https://blog.csdn.net/qq_24698193/article/details/76725424
代码参考文档链接:https://www.jianshu.com/p/e4d3cca286e4
废话不多说,上代码:
重写HttpServletRequestWrapper类:
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = HttpServletRequestReader.ReadAsChars2(request).getBytes(Charset.forName("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) {
}
};
}
}
post请求数据读取类:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
public class HttpServletRequestReader
{
// 字符串读取
// 方法一
public static String ReadAsChars(ServletRequest request)
{
BufferedReader br = null;
StringBuilder sb = new StringBuilder("");
try
{
br = request.getReader();
String str;
while ((str = br.readLine()) != null)
{
sb.append(str);
}
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (null != br)
{
try
{
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return sb.toString();
}
// 方法二
public static String ReadAsChars2(ServletRequest request)
{
InputStream is = null;
StringBuilder sb = new StringBuilder();
try
{
is = request.getInputStream();
byte[] b = new byte[4096];
for (int n; (n = is.read(b)) != -1;)
{
sb.append(new String(b, 0, n));
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (null != is)
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return sb.toString();
}
// 二进制读取
public static byte[] readAsBytes(HttpServletRequest request)
{
int len = request.getContentLength();
byte[] buffer = new byte[len];
ServletInputStream in = null;
try
{
in = request.getInputStream();
in.read(buffer, 0, len);
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (null != in)
{
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return buffer;
}
}
配置父拦截器:
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@org.springframework.context.annotation.Configuration
public class Configuration extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInteceptor()).addPathPatterns("/input/*");
}
}
配置子拦截器:
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import cn.weidiankeji.appApi.util.aes.AESUtil;
public class HandlerInteceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("请求结束");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("controller完成之后");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse res, Object arg2) throws Exception {
String password = "1234567890111111";
System.out.println("进件请求参数1:》》" + request.toString());
System.out.println("拦截用户");
String url = request.getRequestURI();
url = url.replace("input","test");
System.out.println("uri=" + url);
//此处一定要注意用重写的request请求
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
String reqData = HttpServletRequestReader.ReadAsChars2(requestWrapper);
System.out.println("请求参数:" + reqData);
JSONObject object = JSONObject.parseObject(reqData);
String data = object.getString("data");
byte[] decryptFrom = AESUtil.parseHexStr2Byte(data);
byte[] decryptResult = AESUtil.decrypt(decryptFrom, password);
String decryptData = new String(decryptResult);
System.out.println("解密后:" + decryptData);
JSONObject jsObj = new JSONObject();
jsObj.put("appid", object.getString("appid"));
jsObj.put("sign", object.getString("sign"));
jsObj.put("data", decryptData);
request.setAttribute("request", jsObj.toString());
request.getRequestDispatcher(url).forward(request, res);
return true;
}
}
controller层:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.weidiankeji.appApi.aop.HttpServletRequestReader;
import cn.weidiankeji.appApi.util.ResultObj;
@Controller
@RequestMapping("/test")
public class testController {
@RequestMapping("/jyquery")
@ResponseBody
public ResultObj inputCentreRequest(HttpServletRequest request,HttpServletResponse res) {
String str = (String)request.getAttribute("request");
System.out.println("str:" + str);
return new ResultObj("000","成功");
}
}
上一篇: 创新企业突出重围的当下 社区O2O如何占领“最后一公里”?
下一篇: 求两数之和