从代码里可以直观的看到:有了抽象父类后,子类需要做的事情已经很少了,只需要匹配参数类型、做不同的返回而已。
关于它俩的使用案例,此处不用再展示了,因为各位平时工作中都在使用,再熟悉不过了。但针对他俩的使用,我总结出如下几个小细节,供以参考:
@RequestBody/HttpEntity它的参数(泛型)类型允许是Map
方法上的和类上的@ResponseBody都可以被继承,但@RequestBody不可以
@RequestBody它自带有Bean Validation校验能力(当然需要启用),HttpEntity更加的轻量和方便
HttpEntity/RequestEntity所在包是:org.springframework.http,属于spring-web
@RequestBody位于org.springframework.web.bind.annotation,同样属于spring-web
最后还落了一个ErrorsMethodArgumentResolver,在这里补充一下:
ErrorsMethodArgumentResolver它用于在方法参数可以写Errors类型,来拿到数据校验结果。
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { Class<?> paramType = parameter.getParameterType(); return Errors.class.isAssignableFrom(paramType); } @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { Assert.state(mavContainer != null, "Errors/BindingResult argument only supported on regular handler methods"); ModelMap model = mavContainer.getModel(); String lastKey = CollectionUtils.lastElement(model.keySet()); // 只有@RequestBody/@RequestPart注解的 这里面才会有值 if (lastKey != null && lastKey.startsWith(BindingResult.MODEL_KEY_PREFIX)) { return model.get(lastKey); } // 简单的说:必须有@RequestBody/@RequestPart这注解标注,Errors参数才有意义 throw new IllegalStateException( "An Errors/BindingResult argument is expected to be declared immediately after " + "the model attribute, the @RequestBody or the @RequestPart arguments " + "to which they apply: " + parameter.getMethod()); } } Spring MVC参数处理器的注册与顺序到这里,一个不落的把Spring MVC内置提供的参数处理器ArgumentResolver说了个遍。
前面我有提到过:参数处理对处理器的顺序是敏感的,因此我们需要关注Spring MVC最终的执行顺序,这时候我们的聚合容器HandlerMethodArgumentResolverComposite就出场了:
缺省情况Spring MVC注册的处理器(顺序)如下:
它初始化处的代码如下: RequestMappingHandlerAdapter: @Override public void afterPropertiesSet() { ... // 26个,详见方法getDefaultArgumentResolvers if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } // 12个 详见方法getDefaultInitBinderArgumentResolvers if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } ... }