如何优雅地读写HttpServletRequest和HttpServletResponse的请求体
最近很多交互要同原生的HttpServletRequest
和HttpServletResponse
打交道。从HttpServletRequest
中读取body数据封装成某种数据结构;向HttpServletResponse
写入数据并响应。传统的写法非常不优雅,今天给大家介绍一种比较优雅的方式。
HttpMessageConverter
HttpMessageConverter
是Spring框架提供的一个消息转换器模型,用于在 HTTP 请求和响应之间进行转换的策略接口。它可以对输入消息HttpInputMessage
进行读;也可以对输出消息HttpOutputMessage
进行写。
Spring MVC的消息转换都是通过这个接口的实现来完成的。HttpMessageConverter
有很多实现:
通常Spring MVC中处理Form表单提交、JSON、XML、字符串、甚至Protobuf都由HttpMessageConverter
的实现来完成,前端传递到后端的body参数,后端返回给前端的数据都是由这个接口完成转换的。在Spring IoC中(Spring MVC环境)还存在一个存放HttpMessageConverter
的容器HttpMessageConverters
:
@Bean@ConditionalOnMissingBeanpublic HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {return new HttpMessageConverters((Collection)converters.orderedStream().collect(Collectors.toList()));}
复制代码
我们可以直接拿来使用。那么到底怎么使用呢?那首先要搞清楚HttpInputMessage
和HttpOutputMessage
是干什么用的。
HttpInputMessage
HttpInputMessage
表示一个 HTTP 输入消息,由请求头headers和一个可读的请求体body组成,通常由服务器端的 HTTP 请求句柄或客户端的 HTTP 响应句柄实现。
而HttpServletRequest
是ServletRequest
的扩展接口,提供了HTTP Servlet的请求信息,也包含了请求头和请求体,所以两者是有联系的。我们只要找出两者之间的实际关系就能让HttpMessageConverter
去读取并处理HttpServletRequest
携带的请求信息。
ServletServerHttpRequest
说实话还真找到了:
ServletServerHttpRequest
不仅仅是HttpInputMessage
的实现,它还持有了一个HttpServletRequest
实例属性,ServletServerHttpRequest
的所有操作都是基于HttpServletRequest
进行的。我们可以通过构造为其注入HttpServletRequest
实例,这样HttpMessageConverter
就能间接处理HttpServletRequest
了。
提取请求体实战
这里聚焦的场景是在Servlet过滤器中使用HttpMessageConverter
,在Spring MVC中不太建议去操作HttpServletRequest
。我选择了FormHttpMessageConverter
,它通常用来处理application/x-www-form-urlencoded
请求。我们编写一个过滤器来拦截请求提取body:
/*** 处理 application/x-www-form-urlencoded 请求** @author felord.cn*/@Component
public class FormUrlencodedFilter implements Filter {private final FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();private static final Logger log = LoggerFactory.getLogger(FormUrlencodedFilter.class);@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {String contentType = request.getContentType();MediaType type= StringUtils.hasText(contentType)? MediaType.valueOf(contentType):null;ServletServerHttpRequest serverHttpRequest = new ServletServerHttpRequest((HttpServletRequest) request);if (formHttpMessageConverter.canRead(MultiValueMap.class,type)) {MultiValueMap<String, String> read = formHttpMessageConverter.read(null, serverHttpRequest);log.info("打印读取到的请求体:{}",read);}}
}
复制代码
然后执行一个POST
类型,Content-Type
为application/x-www-form-urlencoded
的请求:
POST /ind HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 20a=b123&c=d123&e=f123
复制代码
控制台会打印:
2021-12-30 6:43:56.409 INFO 12408 --- [nio-8080-exec-1] sfds: 打印读取到的请求体:{a=[b123], c=[d123], e=[f123]}
复制代码
ServletServerHttpResponse
有ServletServerHttpRequest
就有ServletServerHttpResponse
,大致原理差不多。它正好和ServletServerHttpRequest
相反,如果我们需要去处理响应问题,比如想通过HttpServletResponse
写个JSON响应,大概可以这么写:
ServletServerHttpResponse servletServerHttpResponse = new ServletServerHttpResponse(response);
// 使用json converter
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
// authentication 指的是需要写的对象实例
mappingJackson2HttpMessageConverter.write(authentication, MediaType.APPLICATION_JSON,servletServerHttpResponse);
复制代码
总结
HttpMessageConverter
抽象了HTTP消息转换的策略,可以帮助我们优雅地处理一些请求响应的问题。不过有一点需要注意,请求体body只能读取一次,即使它包裹在ServletServerHttpRequest
中,要注意和HttpServletRequestWrapper
的区别。
如何优雅地读写HttpServletRequest和HttpServletResponse的请求体相关推荐
- Maven项目下HttpServletRequest 或 HttpServletResponse需引用的依赖包
转载: http://xyly624.blog.51cto.com/842520/865630/ Maven项目下HttpServletRequest 或 HttpServletResponse需引用 ...
- HttpServletrequest 与HttpServletResponse总结
转载 http://www.cnblogs.com/liuyandeng/p/5336649.html HttpServletrequest 与HttpServletResponse总结 如果说DOM ...
- Struts2之HttpServletRequest、HttpServletResponse,HttpSession,Parameters处理
在正式讲解如何获取上述对象之前,需要先搞清楚一点,类似于Struts2.SpringMVC框架之所以在诸多方面用着比较方便,简化开发人员重复机械性的工作,就是因为它们把底层的Servlet操作封装起来 ...
- 小明滚出---响应对象HttpServletResponse和请求对象HttpServletRequest实例
<Servlet类的Java> @WebServlet("/studentServlet") public class StudentServlet extends H ...
- Maven项目下HttpServletRequest 或 HttpServletResponse显示红色
用Idea软件,Maven项目下HttpServletRequest 或 HttpServletResponse显示红色,需引用的依赖包:servlet-api.jar,官网上对应的是:JavaSer ...
- python用with读文件的好处_python小课堂39 - 用 with 优雅的读写文件
python小课堂39 - 用 with 优雅的读写文件 前言 本篇来介绍一下 Python 中的关键词 with 的小技巧.但是在了解 with 之前,需要先了解一下如何使用 Python 对文件进 ...
- HttpServletRequest对象,请求行、请求头、请求体
HttpServletRequest 公共接口类HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象.对 ...
- Servlet API 详解(HttpServlet、HttpServletRequest、HttpServletResponse)
系列文章目录 Servlet 的运行原理_crazy_xieyi的博客-CSDN博客 如何创建一个Servlet项目(Maven)?_crazy_xieyi的博客-CSDN博客 Tomcat下载.安装 ...
- HttpServletRequest和HttpServletResponse简介
http://blog.csdn.net/tong_xinglong/article/details/12972819
最新文章
- 你是中层管理者?嗯,一个表面看似风光,实际却很 “鸡肋” 的重要岗位
- sublime text3中文文件名显示为框框,怎么解决
- 快速消费品行业前景及进入门槛
- 为容器提供持久存储,这个方法试试看
- C/C++ pthread 线程库的封装
- MySQL怎么给表简明_科学网—mySQL简明入门 - 张金龙的博文
- 服务器项目怎么连接数据库,服务器项目连接数据库配置
- 巴菲特:伯克希尔没有所谓的5G核心能力 子公司会涉足相关行业
- 1.3、TetGen网格化过程之描述
- android 电视安装apk,给一切安卓智能电视安装第三方软件市场
- 与计算机相关的统计表格,统计信息化 Excel与SPSS应用pdf
- android 源码编译apk,在Android源码里编译apk
- 离散数学及其应用第1章笔记总结
- selenium之滑块操作
- html logo写法,教你用CSS3打造HTML5的Logo
- /usr/bin/ld cannot find -lGL
- spring security——学习笔记(day05)-实现自定义 AuthenticationProvider身份认证-手机号码认证登录
- 【Linux】Linux文件锁
- 电子书Epub文件剖析
- DETR3D模型源码导读 MMDetection3D构建流程