拦截器如何获取HttpServletRequest里body数据
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章主要讲解了"拦截器如何获取HttpServletRequest里body数据",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"拦截器如何获取Htt
千家信息网最后更新 2025年12月02日拦截器如何获取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安全错误
数据库的锁怎样保障安全
如何设置服务器安全
达梦数据库获取insert
芯片原厂软件开发
多种数据库类型支持
夏日清新服务器
鸿蒙软件开发商是谁
真正的网络安全大赛视频
如何保证云服务器硬件安全
网络安全培训教育活动记录
我的世界基岩版服务器长啥样
数据库访问权限集中
软件开发工程师助理是什么
兰州理工大学网络技术
服务器如何搭建两个网站
目前较火的软件开发技术
软件开发出来后后期维护
乐而活互联网科技
delphi7数据库备份
达内软件开发待遇
codm服务器内部异常
服务器在国外的网盘
网络安全非常赚钱吗
互联网前沿与科技
网络安全产品研发方案
幼儿园网络安全家长建议
单位 网络安全责任
政治 如何维护网络安全
软件开发哪家收费合理
tod服务器的搭建
mfc上传文件到数据库