Recently, many interactions have to deal HttpServletRequest
and HttpServletResponse
Read body data from HttpServletRequest
and encapsulate it into a certain data structure; HttpServletResponse
and respond. The traditional way of writing is very inelegant. Today I will introduce you to a more elegant way.
HttpMessageConverter
HttpMessageConverter
is a message converter model provided by the Spring framework, which is a strategy interface for converting between HTTP requests and responses. It can read the input message HttpInputMessage
; it can also write HttpOutputMessage
Spring MVC is done through the realization of this interface. There are many implementations of HttpMessageConverter
Typically the Spring the MVC processing Form1 form submission, the JSON , the XML , string, even Protobuf by HttpMessageConverter
implemented to complete, is transmitted to the rear end of the front end body parameters, return to the rear end The front-end data is converted by this interface. In the Spring the IoC in ( the Spring the MVC environment) there is a storage HttpMessageConverter
container HttpMessageConverters
:
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters((Collection)converters.orderedStream().collect(Collectors.toList()));
}
We can use it directly. So how do you use it? First, we must figure out HttpInputMessage
and HttpOutputMessage
are used for.
HttpInputMessage
HttpInputMessage
represents a the HTTP input message from the request header headers and a request body readable body composition, typically by a server the HTTP request handle or a client the HTTP response handler implementation.
And HttpServletRequest
is ServletRequest
expansion interface that provides the HTTP the Servlet request information, the request also includes a request header and a body, so the two are linked. As long as we find out the actual relationship between the two, HttpMessageConverter
can read and process the request information carried by HttpServletRequest
ServletServerHttpRequest
To be honest, I found it:
ServletServerHttpRequest
just HttpInputMessage
implementation, it also holds a HttpServletRequest
instance property, ServletServerHttpRequest
all operations are based HttpServletRequest
carried out. We can inject the HttpServletRequest
instance by constructing it, so that HttpMessageConverter
can indirectly process HttpServletRequest
.
The actual combat of extracting the request body
The scene focused here is to use HttpMessageConverter
in the Servlet filter. It is not recommended to operate HttpServletRequest
in Spring MVC. I chose FormHttpMessageConverter
, which is usually used to process application/x-www-form-urlencoded
requests. We write a filter to intercept requests to extract 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);
@Override
public 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);
}
}
}
Then execute a POST
type Content-Type
is application/x-www-form-urlencoded
:
POST /ind HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
a=b123&c=d123&e=f123
The console will print:
2021-12-30 6:43:56.409 INFO 12408 --- [nio-8080-exec-1] sfds: 打印读取到的请求体:{a=[b123], c=[d123], e=[f123]}
ServletServerHttpResponse
There ServletServerHttpRequest
there ServletServerHttpResponse
, roughly the principle is similar. It is just the ServletServerHttpRequest
. If we need to deal with the response problem, for example, if we want to HttpServletResponse
, we can probably write like this:
ServletServerHttpResponse servletServerHttpResponse = new ServletServerHttpResponse(response);
// 使用json converter
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
// authentication 指的是需要写的对象实例
mappingJackson2HttpMessageConverter.write(authentication, MediaType.APPLICATION_JSON,servletServerHttpResponse);
Summarize
HttpMessageConverter
abstracts the HTTP message conversion strategy, which can help us handle some request response issues gracefully. But one thing to note is that the request body body can only be read once, even if it is wrapped in ServletServerHttpRequest
, pay attention to the difference HttpServletRequestWrapper
Follow the public account: Felordcn for more information
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。