使用JSON接收前端参数时, param参数可以获取, 但body中的json数据 则需要从reqeust.getInputStream中获取JSON内容, 但是由于流只能读取一次, 所以会导致后续SpringMVC解析参数异常。
网上找到一种解决方法: 用HttpRequestWrapper重新封装Reqeust, 使打印日志后SpringMVC能正常解析HttpReqeust。这种方法比较麻烦, 这里不去研究。(这个方法我以前试过,实现也可以,但可能会引起一些奇怪的错误,毕竟实质上是用拷贝的流来实现业务,可能跟最初的流有不一样的地方)
这里主要说说Spring提供的较好的解决方案:
可以通过自定义RequestBodyAdvisor、ResponseBodyAdvisor来实现日志输出。
- RequestBodyAdvisor可以获取到解析后的Controller方法参数对象。
- ResponseBodyAdvisor可以获取到Controller方法返回值对象。
然后将他们注册到requestMappingHandlerAdapter:
前提:
①使用springMvc
②controller层方法上使用@RequestBody注解修饰
@Configuration
@Slf4j
public class WebMvcSupportConfig extends WebMvcConfigurationSupport {
@Override
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
adapter.setRequestBodyAdvice(Lists.newArrayList(new CustomerRequestBodyAdvisor()));
return adapter;
}
}
CustomerRequestBodyAdvisor实现样例:
public class CustomerRequestBodyAdvisor extends RequestBodyAdviceAdapter {
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return methodParameter.getParameterAnnotation(RequestBody.class) != null;
}
/**
* 拦截请求的body入参,并打印
* 只支持RequestBody注解修饰的Controller方法
*/
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
Method method = parameter.getMethod();
// 参数对象转JSON字符串
String jsonBody;
if (StringHttpMessageConverter.class.isAssignableFrom(converterType)) {
jsonBody = body.toString();
} else {
jsonBody = JSON.toJSONString(body);
}
// 自定义日志输出
log.info("前端Body入参={}", jsonBody);
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
另外,还可以获取@ResponseBody的数据, 不过我暂时没遇到应用场景, 实现方式可参考: