Scenario
Spring framework provides mechanism for binding controller method parameters to custom model. Here is a very good article on how to implement custom data binding https://www.baeldung.com/spring-mvc-custom-data-binder During data binding there might be a need to access HTTP request body.
Solution
HTTP request body is hidden in the ModelAndViewContainer object that spring provides to the argument resolver. Here is a code example:
public class MyContextArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(@Nullable MethodParameter methodParameter) {
return methodParameter != null &&
methodParameter.getParameterAnnotation(MyContext.class) != null;
}
@Override
public Object resolveArgument(@Nullable MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer,
@Nullable NativeWebRequest nativeWebRequest,
return toContext(modelAndViewContainer);
}
private MyContext toContext(ModelAndViewContainer modelAndViewContainer) {
if (modelAndViewContainer == null) {
return MyContext.builder().build();
}
MyContext.Builder builder = MyContext.builder();
modelAndViewContainer.getModel().forEach((k, v) -> {
if (v instanceof BindingResult) {
BindingResult result = (BindingResult) v;
if (result.getTarget() instanceof Map) {
// plain map
builder
.setPropertyOne(((Map<?, ?>) result.getTarget()).get("propertyOne"))
.setPropertyTwo(((Map<?, ?>) result.getTarget()).get("propertyTwo"));
} else if (result.getTarget() instanceof MyRequest) {
// handle MyRequest request
builder
.setPropertyOne(((MyRequest) result.getTarget()).getpropertyOne())
.setPropertyTwo(((MyRequest) result.getTarget()).getpropertyTwo());
}
}
});
return builder.builder();
}
}All details about setting up method argument resolver are omitted and the focus is on the toContext function that demonstrates how to get request body from ModelAndViewContainer.