拦截器如何获取HttpServletRequest里body数据
发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,这篇文章主要讲解了"拦截器如何获取HttpServletRequest里body数据",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"拦截器如何获取Htt
千家信息网最后更新 2024年11月18日拦截器如何获取HttpServletRequest里body数据
这篇文章主要讲解了"拦截器如何获取HttpServletRequest里body数据",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"拦截器如何获取HttpServletRequest里body数据"吧!
一、问题
通过在拦截器中获取request中的json数据,我们可以实现对参数进行校验和改写。问题是参数只能在拦截器里获取一次,往后在controller层就无法获取数据,提示body为空。
在网上查找资料后发现,request的输入流只能读取一次,那么这是为什么呢?
那是因为流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据。javaAPI中有一个方法public void reset() 这个方法就是可以重置pos为起始位置,但是不是所有的IO读取流都可以调用该方法!ServletInputStream是不能调用reset方法,这就导致了只能调用一次getInputStream()
二、解决办法
HttpServletRequestWrapper是 httpServletRequest 的包装类
新建一个类继承HttpServletRequestWrapper实现对 httpServletRequest 的装饰,用来获取 body 数据
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; private String bodyStr; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); String bodyString = getBodyString(request); body = bodyString.getBytes(Charset.forName("UTF-8")); bodyStr=bodyString; } public String getBodyStr() { return bodyStr; } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } public 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, Charset.forName("UTF-8"))); char[] bodyCharBuffer = new char[1024]; int len = 0; while ((len = reader.read(bodyCharBuffer)) != -1) { sb.append(new String(bodyCharBuffer, 0, len)); } } 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 实现对传入的 httpServletRequest 的转换
@WebFilter(filterName = "httpServletRequestWrapperFilter", urlPatterns = {"/*"})public class HttpServletRequestWrapperFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ServletRequest requestWrapper = null; if (request instanceof HttpServletRequest) { HttpServletRequest httpRequest = (HttpServletRequest) request; //遇到post方法才对request进行包装 String methodType = httpRequest.getMethod(); if ("POST".equals(methodType)) { requestWrapper = new BodyReaderHttpServletRequestWrapper( (HttpServletRequest) request); } } if (null == requestWrapper) { chain.doFilter(request, response); } else { chain.doFilter(requestWrapper, response); } } @Override public void destroy() { }}
最后在拦截器就可以获取request中body数据
if(request instanceof BodyReaderHttpServletRequestWrapper ){ System.out.println(((BodyReaderHttpServletRequestWrapper) request).getBodyStr()); }
经测试发现并不影响controller层获取body数据
为什么需要在 filter 里进行对 httpServletRequest 的包装转换,直接在拦截器里进行包装不行嘛?
过滤器(Filter)和拦截器(Interceptor)之间的最大区别就是,过滤器可以包装Request和Response,而拦截器并不能用代码描述拦截器和过滤器的流程大概就是这样的:拦截器:void run () { Request request = new Request(); preHandle(request); service(request);}preHandler(Request request) { request = new RequestWrapper(request); //在这里修改Request的引用,不会影响到service方法的request}过滤器void run () { Request request = new Request(); doFilter(request);}doFilter(Request request) { request = new RequestWrapper(request); //在这里修改Request的引用,会影响到service方法的request service(request);}
感谢各位的阅读,以上就是"拦截器如何获取HttpServletRequest里body数据"的内容了,经过本文的学习后,相信大家对拦截器如何获取HttpServletRequest里body数据这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
数据
拦截器
方法
就是
包装
内存
过滤器
位置
问题
学习
影响
内容
参数
标记
UTF-8
不行
最大
有的是
之间
代码
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网征信 科技
access 数据库解密
直播系统软件开发公司
服务器端 识别客户端
服务器软件工程师招聘
对服务器而言最重要的是什么
软件开发招生宣讲
连上wi-fi后无法访问服务器
来分期平台的服务器
魔兽世界单机提取数据库
数据库事物提交与锁的释放
专科生学软件技术涉及软件开发
网络安全设计及集成
软件开发禅道
沧州软件开发招聘信息
嵌入式软件开发集成环境
开放式数据库
单位领导在网络安全讲话
主机和域名服务器连接图
古色古香小说软件开发
佛山市淼业网络技术
r840服务器可以上什么内存
共上一节网络安全课
服务器风扇哪里比较全
怎么组建小型服务器网络
数据库有几种备份的方式
fc交换机和服务器连接
服务器显卡通用吗
无领导小组面试题网络安全
软件开发和技术推广