当前位置: 首页 > 后端技术 > Java

如何优雅的读写HttpServletRequest和HttpServletResponse的请求体

时间:2023-04-02 01:48:13 Java

最近很多交互都要处理原生的HttpServletRequest和HttpServletResponse。从HttpServletRequest中读取body数据,封装成一定的数据结构;将数据写入HttpServletResponse并响应。传统的写法很不优雅。今天给大家介绍一种比较优雅的方式。HttpMessageConverterHttpMessageConverter是Spring框架提供的消息转换器模型,HTTP请求和响应之间转换的策略接口。它可以读取输入消息HttpInputMessage;它还可以编写输出消息HttpOutputMessage。SpringMVC的消息转换就是通过这个接口的实现来完成的。HttpMessageConverter的实现有很多:通常,SpringMVC中Form表单提交、JSON、XML、字符串,甚至Protobuf的处理都是由HttpMessageConverter的实现来完成的。前端传给后端的body参数,后端返回的数据给前端接口进行转换。在SpringIoC(SpringMVC环境)中,也有一个容器HttpMessageConverters,存放HttpMessageConverterHttpMessageConverters:@Bean@ConditionalOnMissingBeanpublicHttpMessageConvertersmessageConverters(ObjectProvider>converters){returnnewHttpMessageConverters.converters((Collection)edconverters(Collectors.toList()));我们可以直接使用它。那么如何使用呢?首先我们要搞清楚HttpInputMessage和HttpOutputMessage是干什么用的。HttpInputMessageHttpInputMessage表示一个HTTP输入消息,由请求头和可读的请求体组成,通常由服务器端的HTTP请求处理程序或客户端的HTTP响应处理程序实现。HttpServletRequest是ServletRequest的扩展接口,提供HTTPServlet请求信息,还包括请求头和请求体,所以两者是相关的。只要弄清两者的实际关系,就可以让HttpMessageConverter读取并处理HttpServletRequest携带的请求信息。ServletServerHttpRequest老老实实发现:ServletServerHttpRequest不仅仅是HttpInputMessage的实现,它还持有一个HttpServletRequest实例属性,ServletServerHttpRequest的所有操作都是基于HttpServletRequest。我们可以通过构造向其中注入HttpServletRequest实例,让HttpMessageConverter间接处理HttpServletRequest。提取请求体的实战重点是在Servlet过滤器中使用HttpMessageConverter。不建议在SpringMVC中操作HttpServletRequest。我选择了FormHttpMessageConverter,它通常用于处理application/x-www-form-urlencoded请求。我们写一个过滤器拦截请求提取body:/***Processapplication/x-www-form-urlencodedrequest**@authorfelord.cn*/@ComponentpublicclassFormUrlencodedFilterimplementsFilter{privatefinalFormHttpMessageConverterformHttpMessageConverter=newFormHttpMessageConverter();privatestaticfinalLoggerlog=LoggerFactory.getLogger(FormUrlencodedFilter.class);@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException{StringcontentType=request.(内容类型)?MediaType.valueOf(contentType):null;ServletServerHttpRequestserverHttpRequest=newServletServerHttpRequest((HttpServletRequest)请求);如果(formHttpMessageConverter.canRead(MultiValueMap.class,type)){MultiValueMap(null,serverHttpRequest);log.info("打印读取请求体:{}",读);然后使用Content-Typeapplication/x-www-form-urlencoded:POST/indHTTP/1.1Host:localhost:8080Content-Type:application/x-www-form-urlencodedContent-Length:20a=执行POST请求b123&c=d123&e=f123控制台将打印:2021-12-306:43:56.409INFO12408---[nio-8080-exec-1]sfds:printthereadrequestbody:{a=[b123],c=[d123],e=[f123]}ServletServerHttpResponse有ServletServerHttpRequest,有ServletServerHttpResponse。大体原理类似。它与ServletServerHttpRequest正好相反。如果我们需要处理响应问题,比如我们要写一个JSON响应,大致可以这样写:ServletServerHttpResponseservletServerHttpResponse=newServletServerHttpResponse(response);//使用jsonconverterMappingJackson2HttpMessageConvertermappingJackson2HttpMessageConverter;authenticationJackson2HttpMessageConverter;的是需要写的实例mappingJackson2HttpMessageConverter.write(authentication,MediaType.APPLICATION_JSON,servletServerHttpResponse);总结HttpMessageConverter抽象了HTTP消息转换的策略,可以帮助我们优雅的处理一些请求响应问题。但是需要注意一点,请求体只能被读取一次,即使是包裹在ServletServerHttpRequest中,注意和HttpServletRequestWrapper的区别。关注公众号:Felordcn获取更多资讯个人博客:https://felord.cn