HandlerMethodArgumentResolver(三):基于消息转换器的参数处理器【享学Spring MVC】 (3)

顾名思义,它负责处理@RequestBody这个注解的参数

public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(RequestBody.class); } @Override public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { parameter = parameter.nestedIfOptional(); // 所以核心逻辑:读取流、消息换换等都在父类里已经完成。子类直接调用就可以拿到转换后的值arg // arg 一般都是个类对象。比如Person实例 Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType()); // 若是POJO,就是类名首字母小写(并不是形参名) String name = Conventions.getVariableNameForParameter(parameter); // 进行数据校验(之前已经详细分析过,此处一笔带过) if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name); if (arg != null) { validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) { throw new MethodArgumentNotValidException(parameter, binder.getBindingResult()); } } // 把校验结果放进Model里,方便页面里获取 if (mavContainer != null) { mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult()); } } // 适配:支持到Optional类型的参数 return adaptArgumentIfNecessary(arg, parameter); } } HttpEntityMethodProcessor

用于处理HttpEntity和RequestEntity类型的入参的。

public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor { @Override public boolean supportsParameter(MethodParameter parameter) { return (HttpEntity.class == parameter.getParameterType() || RequestEntity.class == parameter.getParameterType()); } @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws IOException, HttpMediaTypeNotSupportedException { ServletServerHttpRequest inputMessage = createInputMessage(webRequest); // 拿到HttpEntity的泛型类型 Type paramType = getHttpEntityType(parameter); if (paramType == null) { // 注意:这个泛型类型是必须指定的,必须的 throw new IllegalArgumentException("HttpEntity parameter '" + parameter.getParameterName() + "' in method " + parameter.getMethod() + " is not parameterized"); } // 调用父类方法拿到body的值(把泛型类型传进去了,所以返回的是个实例) Object body = readWithMessageConverters(webRequest, parameter, paramType); // 注意步操作:new了一个RequestEntity进去,持有实例即可 if (RequestEntity.class == parameter.getParameterType()) { return new RequestEntity<>(body, inputMessage.getHeaders(), inputMessage.getMethod(), inputMessage.getURI()); } else { // 用的父类HttpEntity,那就会丢失掉Method等信息(因此建议入参用RequestEntity类型,更加强大些) return new HttpEntity<>(body, inputMessage.getHeaders()); } } }

注意:这里可没有validate校验了,这也是经常被面试问到的:使用HttpEntity和@RequestBody有什么区别呢?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywsgx.html