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.