HandlerMethodArgumentResolver
HandlerMethodArgumentResolver用来为处理器解析参数
主要在InvocableHandlerMethod中使用
由于每个Resolver对应一种类型的参数,所以有很多实现类
HandlerMethodArgumentResolverComposite
其中HandlerMethodArgumentResolverComposite较为特殊,从命名来看这是一个组合模式
它本身并不像其他子类一样可以解析具体参数,而是对多个解析器进行封装
解析参数时,调用封装在其中的解析器进行具体解析
1)HandlerMethodArgumentResolver接口:
public interface HandlerMethodArgumentResolver {
// 是否支持解析传入的参数
boolean supportsParameter(MethodParameter parameter);
// 具体解析逻辑
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
}
2)从继承关系可以发现HandlerMethodArgumentResolver的实现类一般有两种命名方式:
1,XXXMethodArgumentResolver
参数解析器
2,XXXMethodProcessor
不仅可以解析参数,
还可以处理相应类型的返回值(实现了HandlerMethodReturnValueHandler)
3)还有一组Adapter类,用于兼容WebArgumentResolver类型的参数解析器的适配器
各种解析器作用
各种解析器的作用:
常用解析器分析
1,ModelMethodProcessor
Model类型参数解析器
XXXProcessor命名,既可以解析参数,也可以处理返回值
ModelMethodProcessor源码:
public class ModelMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
// 支持解析Model类型的参数
@Override
public boolean supportsParameter(MethodParameter parameter) {
return Model.class.isAssignableFrom(parameter.getParameterType());
}
// 直接返回mavContainer中的Model
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return mavContainer.getModel();
}
// 支持解析Model类型的返回值
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return Model.class.isAssignableFrom(returnType.getParameterType());
}
// 返回值不为null且是Model类型,将返回值加入到Model中,否则抛出异常
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
if (returnValue == null) {
return;
}
else if (returnValue instanceof Model) {
mavContainer.addAllAttributes(((Model) returnValue).asMap());
}
else {
// should not happen
throw new UnsupportedOperationException("Unexpected return type: " +
returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
}
}
}
分别实现了参数和返回值支持类型和具体处理逻辑
支出Model类型的参数解析和返回值处理
参数解析:直接返回mavContainer中的Model
返回值处理:返回值不为null且是Model类型,将返回值加入到Model中,否则抛出异常
2,PathVariableMethodArgumentResolver
PathVariableMethodArgumentResolver
用于解析url路径中的值
继承自AbstractNamedValueMethodArgumentResolver
AbstractNamedValueMethodArgumentResolver
从继承关系可以看到:
多种解析器都继承自AbstractNamedValueMethodArgumentResolver
AbstractNamedValueMethodArgumentResolver是一个模板模式
没有实现supportsParameter方法,只实现了resolveArgument方法
AbstractNamedValueMethodArgumentResolver#resolveArgument参数的具体处理逻辑:
@Override
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// 创建 MethodParameter 对应的 NamedValueInfo
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
// 因为此时的 name 可能还是被 ${} 符号包裹,
// 则通过 BeanExpressionResolver 来进行解析
Object resolvedName = resolveStringValue(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException(
"Specified name must not resolve to null: [" + namedValueInfo.name + "]");
}
// 具体解析参数的方法,模板方法,子类实现
Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
// 如果没有解析到参数
if (arg == null) {
// namedValueInfo是否有默认值
if (namedValueInfo.defaultValue != null) {
// 解析参数
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// 没有默认值且required=true
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
//参数缺失处理,抛出相应类型异常
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
// null值处理
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
}
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
arg = resolveStringValue(namedValueInfo.defaultValue);
}
// 如果binderFactory不为空,则用binderFactory创建binder
// 如果需要转换,则转换解析出来的参数
if (binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
try {
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
}
catch (ConversionNotSupportedException ex) {
throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
catch (TypeMismatchException ex) {
throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
namedValueInfo.name, parameter, ex.getCause());
}
}
// 对解析出来的参数进行后置处理
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
// 具体解析参数的方法,模板方法,子类实现
protected abstract Object resolveName(String name, MethodParameter parameter, NativeWebRequest request)
throws Exception;
首先根据 MethodParameter 创建了 NamedValueInfo
之后将相关参数传入模板方法resolveName由子类进行具体解析
最后对解析返回的结果进行处理
NamedValueInfo是一个内部类
protected static class NamedValueInfo {
private final String name;// 参数名
private final boolean required;// 是否必输
private final String defaultValue;// 默认值
public NamedValueInfo(String name, boolean required, String defaultValue) {
this.name = name;
this.required = required;
this.defaultValue = defaultValue;
}
}
resolveName解析完成后,判断解析结果是否为null或空串
是null或空串,判断NamedValueInfo是否包含默认值
包含,调用resolveStringValue传入
不是null或空串,