当前位置:   article > 正文

【Spring源码分析】36-Spring MVC参数值的绑定_springmvc#++#resolvers.add(new servletmodelattribu

springmvc#++#resolvers.add(new servletmodelattributemethodprocessor(false));

上一篇《Spring MVC设计原理》中提到了Spring MVC在使用RequestMappingHandlerAdapter处理HTTP请求时会进行参数绑定,参数绑定会在两种方法上发生:

  1. @RequestMapping方法的参数绑定
  2. @ModelAttribute方法的参数绑定

1、参数解析器的初始化

这两种参数绑定分别使用一个HandlerMethodArgumentResolverComposite对象,只不过这个对象内部使用两套HandlerMethodArgumentResolver。HandlerMethodArgumentResolverComposite的初始化是在RequestMappingHandlerAdapter的afterPropertiesSet()方法中。

控制器使用的参数解析器列表,包括通过setCustomArgumentResolvers()提供的内置解析器和自定义解析器。

  1. private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
  2. List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
  3. // Annotation-based argument resolution
  4. resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
  5. resolvers.add(new RequestParamMapMethodArgumentResolver());
  6. resolvers.add(new PathVariableMethodArgumentResolver());
  7. resolvers.add(new PathVariableMapMethodArgumentResolver());
  8. resolvers.add(new MatrixVariableMethodArgumentResolver());
  9. resolvers.add(new MatrixVariableMapMethodArgumentResolver());
  10. resolvers.add(new ServletModelAttributeMethodProcessor(false));
  11. resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
  12. resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
  13. resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
  14. resolvers.add(new RequestHeaderMapMethodArgumentResolver());
  15. resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
  16. resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
  17. resolvers.add(new SessionAttributeMethodArgumentResolver());
  18. resolvers.add(new RequestAttributeMethodArgumentResolver());
  19. // Type-based argument resolution
  20. resolvers.add(new ServletRequestMethodArgumentResolver());
  21. resolvers.add(new ServletResponseMethodArgumentResolver());
  22. resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
  23. resolvers.add(new RedirectAttributesMethodArgumentResolver());
  24. resolvers.add(new ModelMethodProcessor());
  25. resolvers.add(new MapMethodProcessor());
  26. resolvers.add(new ErrorsMethodArgumentResolver());
  27. resolvers.add(new SessionStatusMethodArgumentResolver());
  28. resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
  29. // Custom arguments
  30. if (getCustomArgumentResolvers() != null) {
  31. resolvers.addAll(getCustomArgumentResolvers());
  32. }
  33. // Catch-all
  34. resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
  35. resolvers.add(new ServletModelAttributeMethodProcessor(true));
  36. return resolvers;
  37. }

@InitBinder方法使用的参数解析器列表,包括setCustomArgumentResolvers()内置和自定义解析器。

  1. private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {
  2. List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
  3. // Annotation-based argument resolution
  4. resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
  5. resolvers.add(new RequestParamMapMethodArgumentResolver());
  6. resolvers.add(new PathVariableMethodArgumentResolver());
  7. resolvers.add(new PathVariableMapMethodArgumentResolver());
  8. resolvers.add(new MatrixVariableMethodArgumentResolver());
  9. resolvers.add(new MatrixVariableMapMethodArgumentResolver());
  10. resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
  11. resolvers.add(new SessionAttributeMethodArgumentResolver());
  12. resolvers.add(new RequestAttributeMethodArgumentResolver());
  13. // Type-based argument resolution
  14. resolvers.add(new ServletRequestMethodArgumentResolver());
  15. resolvers.add(new ServletResponseMethodArgumentResolver());
  16. // Custom arguments
  17. if (getCustomArgumentResolvers() != null) {
  18. resolvers.addAll(getCustomArgumentResolvers());
  19. }
  20. // Catch-all
  21. resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
  22. return resolvers;
  23. }

HandlerMethodArgumentResolver用于在给定请求的上下文中将方法参数解析为参数值的策略接口。

  1. public interface HandlerMethodArgumentResolver {
  2. //此解析程序是否支持给定的MethodParameter方法参数
  3. boolean supportsParameter(MethodParameter parameter);
  4. //将方法参数解析为来自给定请求的参数值。
  5.    //ModelAndViewContainer提供对请求模型的访问。
  6. //WebDataBinderFactory提供了一种在需要进行数据绑定和类型转换时创建WebDataBinder实例的方法
  7. @Nullable
  8. Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
  9. NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
  10. }

HandlerMethodArgumentResolverComposite也实现了HandlerMethodArgumentResolver接口,通过委托给已注册的HandlerMethodArgumentResolver列表来解析方法参数。先前解析的方法参数被缓存以便更快地查找。

  1. @Override
  2. @Nullable
  3. public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
  4. NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
  5. HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
  6. if (resolver == null) {
  7. throw new IllegalArgumentException(
  8. "Unsupported parameter type [" + parameter.getParameterType().getName() + "]." +
  9. " supportsParameter should be called first.");
  10. }
  11. return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
  12. }
  13. @Nullable
  14. private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
  15. HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
  16. if (result == null) {
  17. for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
  18. if (methodArgumentResolver.supportsParameter(parameter)) {
  19. result = methodArgumentResolver;
  20. this.argumentResolverCache.put(parameter, result);
  21. break;
  22. }
  23. }
  24. }
  25. return result;
  26. }

2、参数绑定触发时机

Spring MVC在处理请求时会流转到到RequestMappingHandlerAdapter的invokeHandlerMethod方法,这个方法中会调用modelFactory.initModel方法和invocableMethod.invokeAndHandle方法会完成参数解析。

这两个地方最终调用InvocableHandlerMethod.invokeForRequest方法使用HandlerMethodArgumentResolver进行参数解析。

下面分析一下这个方法的具体实现过程。

3、源码分析

  1. @Nullable
  2. public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
  3. Object... providedArgs) throws Exception {
  4. Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
  5. if (logger.isTraceEnabled()) {
  6. logger.trace("Arguments: " + Arrays.toString(args));
  7. }
  8. return doInvoke(args);
  9. }

Spring MVC的参数绑定是在InvocableHandlerMethod#getMethodArgumentValues()中触发的。

  1. //获取当前请求的方法参数值,检查提供的参数值并回退到配置的参数解析器。
  2. //生成的数组将传递到doInvoke()。
  3. protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
  4. Object... providedArgs) throws Exception {
  5. if (ObjectUtils.isEmpty(getMethodParameters())) {
  6. return EMPTY_ARGS;
  7. }
  8. MethodParameter[] parameters = getMethodParameters();
  9. Object[] args = new Object[parameters.length];
  10. for (int i = 0; i < parameters.length; i++) {
  11. MethodParameter parameter = parameters[i];
  12. parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
  13. args[i] = findProvidedArgument(parameter, providedArgs);
  14. if (args[i] != null) {
  15. continue;
  16. }
  17. if (!this.resolvers.supportsParameter(parameter)) {
  18. throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
  19. }
  20. try {
  21. //如果在已提供的参数值中没有与方法参数类型匹配的则使用HandlerMethodArgumentResolverComposite
  22. args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
  23. }
  24. catch (Exception ex) {
  25. // Leave stack trace for later, exception may actually be resolved and handled..
  26. if (logger.isDebugEnabled()) {
  27. String error = ex.getMessage();
  28. if (error != null && !error.contains(parameter.getExecutable().toGenericString())) {
  29. logger.debug(formatArgumentError(parameter, error));
  30. }
  31. }
  32. throw ex;
  33. }
  34. }
  35. return args;
  36. }

下面分析几个HandlerMethodArgumentResolver的实现。

3.1、AbstractNamedValueMethodArgumentResolver

AbstractNamedValueMethodArgumentResolver用于从NamedValueInfo解析方法参数的抽象基类。子类定义如何执行以下操作:

  • 获取方法参数的NamedValueInfo
  • 将名称解析为参数值
  • 在需要参数值时处理缺少的参数值
  • 可选择处理已解析的值

NamedValueInfo是对参数名,参数是否必填以及默认值的封装。

  1. protected static class NamedValueInfo {
  2. private final String name;
  3. private final boolean required;
  4. @Nullable
  5. private final String defaultValue;
  6. public NamedValueInfo(String name, boolean required, @Nullable String defaultValue) {
  7. this.name = name;
  8. this.required = required;
  9. this.defaultValue = defaultValue;
  10. }
  11. }

默认值字符串可以包含${...}占位符和Spring Expression Language #{...}表达式。 为了这个工作必须提供ConfigurableBeanFactory给类构造函数。创建WebDataBinder以将类型转换应用于已解析的参数值(如果它与方法参数类型不匹配)。

  1. public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {
  2. @Nullable
  3. private final ConfigurableBeanFactory configurableBeanFactory;
  4. @Nullable
  5. private final BeanExpressionContext expressionContext;
  6. private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<>(256);
  7. public AbstractNamedValueMethodArgumentResolver() {
  8. this.configurableBeanFactory = null;
  9. this.expressionContext = null;
  10. }
  11. public AbstractNamedValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory) {
  12. this.configurableBeanFactory = beanFactory;
  13. this.expressionContext =
  14. (beanFactory != null ? new BeanExpressionContext(beanFactory, new RequestScope()) : null);
  15. }
  16. @Override
  17. @Nullable
  18. public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
  19. NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
  20. NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
  21. MethodParameter nestedParameter = parameter.nestedIfOptional();
  22. //参数名支持Spl
  23. Object resolvedName = resolveStringValue(namedValueInfo.name);
  24. if (resolvedName == null) {
  25. throw new IllegalArgumentException(
  26. "Specified name must not resolve to null: [" + namedValueInfo.name + "]");
  27. }
  28. //根据参数名提取参数值
  29. Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
  30. if (arg == null) {
  31. //如不能通过webRequest取得参数值使用默认值(看子类创建namedValueInfo的实现方式)
  32. if (namedValueInfo.defaultValue != null) {
  33. arg = resolveStringValue(namedValueInfo.defaultValue);
  34. }
  35. //如果必填参数值为null通常抛出异常
  36. else if (namedValueInfo.required && !nestedParameter.isOptional()) {
  37. handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
  38. }
  39. //如果arg仍然为null,返回类型是Boolean返回false否则抛异常
  40. arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
  41. }
  42. //空字串使用默认值
  43. else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
  44. arg = resolveStringValue(namedValueInfo.defaultValue);
  45. }
  46. if (binderFactory != null) {
  47. WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
  48. try {
  49. //通常由字符串转换成复杂对象
  50. arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
  51. }
  52. catch (ConversionNotSupportedException ex) {
  53. throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
  54. namedValueInfo.name, parameter, ex.getCause());
  55. }
  56. catch (TypeMismatchException ex) {
  57. throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
  58. namedValueInfo.name, parameter, ex.getCause());
  59. }
  60. }
  61. handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
  62. return arg;
  63. }
  64. //获取给定方法参数的命名值。
  65. private NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
  66. NamedValueInfo namedValueInfo = this.namedValueInfoCache.get(parameter);
  67. if (namedValueInfo == null) {
  68. namedValueInfo = createNamedValueInfo(parameter);
  69. namedValueInfo = updateNamedValueInfo(parameter, namedValueInfo);
  70. this.namedValueInfoCache.put(parameter, namedValueInfo);
  71. }
  72. return namedValueInfo;
  73. }
  74. //为给定的方法参数创建{@link NamedValueInfo}对象。
  75. //实现通常通过MethodParamete.getParameterAnnotation(Class)检索方法注释。
  76. protected abstract NamedValueInfo createNamedValueInfo(MethodParameter parameter);
  77. //基于具有已清理值的给定NamedValueInfo创建新的NamedValueInfo。
  78. private NamedValueInfo updateNamedValueInfo(MethodParameter parameter, NamedValueInfo info) {
  79. String name = info.name;
  80. if (info.name.isEmpty()) {
  81. name = parameter.getParameterName();
  82. if (name == null) {
  83. throw new IllegalArgumentException(
  84. "Name for argument type [" + parameter.getNestedParameterType().getName() +
  85. "] not available, and parameter name information not found in class file either.");
  86. }
  87. }
  88. String defaultValue = (ValueConstants.DEFAULT_NONE.equals(info.defaultValue) ? null : info.defaultValue);
  89. return new NamedValueInfo(name, info.required, defaultValue);
  90. }
  91. //解析给定的注释指定值,可能包含占位符和表达式。
  92. @Nullable
  93. private Object resolveStringValue(String value) {
  94. if (this.configurableBeanFactory == null) {
  95. return value;
  96. }
  97. String placeholdersResolved = this.configurableBeanFactory.resolveEmbeddedValue(value);
  98. BeanExpressionResolver exprResolver = this.configurableBeanFactory.getBeanExpressionResolver();
  99. if (exprResolver == null || this.expressionContext == null) {
  100. return value;
  101. }
  102. return exprResolver.evaluate(placeholdersResolved, this.expressionContext);
  103. }
  104. //将给定的参数类型和值名称解析为参数值。
  105. @Nullable
  106. protected abstract Object resolveName(String name, MethodParameter parameter, NativeWebRequest request)
  107. throws Exception;
  108. //在需要命名值时调用,但resolveName(String,MethodParameter,NativeWebRequest)返回null并且没有默认值。
  109. //在这种情况下,子类通常会抛出异常。
  110. protected void handleMissingValue(String name, MethodParameter parameter, NativeWebRequest request)
  111. throws Exception {
  112. handleMissingValue(name, parameter);
  113. }
  114. //在需要命名值时调用,但resolveName(String,MethodParameter,NativeWebRequest)返回null并且没有默认值。
  115. //在这种情况下,子类通常会抛出异常。
  116. protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
  117. throw new ServletRequestBindingException("Missing argument '" + name +
  118. "' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
  119. }
  120. @Nullable
  121. private Object handleNullValue(String name, @Nullable Object value, Class<?> paramType) {
  122. if (value == null) {
  123. if (Boolean.TYPE.equals(paramType)) {
  124. return Boolean.FALSE;
  125. }
  126. else if (paramType.isPrimitive()) {
  127. throw new IllegalStateException("Optional " + paramType.getSimpleName() + " parameter '" + name +
  128. "' is present but cannot be translated into a null value due to being declared as a " +
  129. "primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
  130. }
  131. }
  132. return value;
  133. }
  134. //在解析值后调用。
  135. protected void handleResolvedValue(@Nullable Object arg, String name, MethodParameter parameter,
  136. @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
  137. }
  138. //表示有关命名值的信息,包括名称,是否需要以及默认值。
  139. protected static class NamedValueInfo {
  140. private final String name;
  141. private final boolean required;
  142. @Nullable
  143. private final String defaultValue;
  144. public NamedValueInfo(String name, boolean required, @Nullable String defaultValue) {
  145. this.name = name;
  146. this.required = required;
  147. this.defaultValue = defaultValue;
  148. }
  149. }
  150. }

3.2、RequestParamMethodArgumentResolver

RequestParamMethodArgumentResolver解析使用@RequestParam注释的方法参数、类型为MultipartFile的参数、以及Spring的 MultipartResolver抽象、以及类型为javax.servlet.http.Part的参数、以及Servlet 3.0 multipart请求。此解析程序也可以在默认解析模式下创建,其中未使用@RequestParam注释的简单类型(int,long等)也被视为请求参数,参数名称派生自参数名称。如果方法参数类型为Map,则注释中指定的名称用于解析请求参数String值。然后,假设已经注册了合适的Converter或PropertyEditor,则通过类型转换将该值转换为Map。或者,如果未指定请求参数名称,则使用RequestParamMapMethodArgumentResolver来提供对Map形式的所有请求参数的访问。调用WebDataBinder以将类型转换应用于尚未与方法参数类型匹配的已解析请求标头值。

  1. public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver
  2. implements UriComponentsContributor {
  3. private static final TypeDescriptor STRING_TYPE_DESCRIPTOR = TypeDescriptor.valueOf(String.class);
  4. private final boolean useDefaultResolution;
  5. //useDefaultResolution在默认解析模式下,一个简单类型的方法参数(如BeanUtils.isSimpleProperty}中所定义)被视为请求参数,
  6. //即使它未注释,请求参数名称也是从方法参数名称派生的
  7. public RequestParamMethodArgumentResolver(boolean useDefaultResolution) {
  8. this.useDefaultResolution = useDefaultResolution;
  9. }
  10. public RequestParamMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory,
  11. boolean useDefaultResolution) {
  12. super(beanFactory);
  13. this.useDefaultResolution = useDefaultResolution;
  14. }
  15. //支持以下内容:
  16.    //@RequestParam注释方法参数。 这排除了Map参数,其中注释未指定名称。 有关此类参数,请参阅RequestParamMapMethodArgumentResolver
  17.    //类型为MultipartFile的参数,除非使用@RequestPart进行注释。
  18.    //Part类型的参数,除非使用@RequestPart进行注释。
  19.    //在默认解析模式下,简单类型参数即使不与@RequestParam一起使用。
  20. @Override
  21. public boolean supportsParameter(MethodParameter parameter) {
  22. if (parameter.hasParameterAnnotation(RequestParam.class)) {
  23. if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
  24. RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
  25. return (requestParam != null && StringUtils.hasText(requestParam.name()));
  26. }
  27. else {
  28. return true;
  29. }
  30. }
  31. else {
  32. if (parameter.hasParameterAnnotation(RequestPart.class)) {
  33. return false;
  34. }
  35. parameter = parameter.nestedIfOptional();
  36. if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
  37. return true;
  38. }
  39. else if (this.useDefaultResolution) {
  40. return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
  41. }
  42. else {
  43. return false;
  44. }
  45. }
  46. }
  47. @Override
  48. protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
  49. RequestParam ann = parameter.getParameterAnnotation(RequestParam.class);
  50. return (ann != null ? new RequestParamNamedValueInfo(ann) : new RequestParamNamedValueInfo());
  51. }
  52. @Override
  53. @Nullable
  54. protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
  55. HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
  56. if (servletRequest != null) {
  57. Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
  58. if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
  59. return mpArg;
  60. }
  61. }
  62. Object arg = null;
  63. MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class);
  64. if (multipartRequest != null) {
  65. List<MultipartFile> files = multipartRequest.getFiles(name);
  66. if (!files.isEmpty()) {
  67. arg = (files.size() == 1 ? files.get(0) : files);
  68. }
  69. }
  70. if (arg == null) {
  71. String[] paramValues = request.getParameterValues(name);
  72. if (paramValues != null) {
  73. arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
  74. }
  75. }
  76. return arg;
  77. }
  78. @Override
  79. protected void handleMissingValue(String name, MethodParameter parameter, NativeWebRequest request)
  80. throws Exception {
  81. HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
  82. if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
  83. if (servletRequest == null || !MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
  84. throw new MultipartException("Current request is not a multipart request");
  85. }
  86. else {
  87. throw new MissingServletRequestPartException(name);
  88. }
  89. }
  90. else {
  91. throw new MissingServletRequestParameterException(name,
  92. parameter.getNestedParameterType().getSimpleName());
  93. }
  94. }
  95. @Override
  96. public void contributeMethodArgument(MethodParameter parameter, @Nullable Object value,
  97. UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
  98. Class<?> paramType = parameter.getNestedParameterType();
  99. if (Map.class.isAssignableFrom(paramType) || MultipartFile.class == paramType || Part.class == paramType) {
  100. return;
  101. }
  102. RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
  103. String name = (requestParam == null || StringUtils.isEmpty(requestParam.name()) ?
  104. parameter.getParameterName() : requestParam.name());
  105. Assert.state(name != null, "Unresolvable parameter name");
  106. if (value == null) {
  107. if (requestParam != null &&
  108. (!requestParam.required() || !requestParam.defaultValue().equals(ValueConstants.DEFAULT_NONE))) {
  109. return;
  110. }
  111. builder.queryParam(name);
  112. }
  113. else if (value instanceof Collection) {
  114. for (Object element : (Collection<?>) value) {
  115. element = formatUriValue(conversionService, TypeDescriptor.nested(parameter, 1), element);
  116. builder.queryParam(name, element);
  117. }
  118. }
  119. else {
  120. builder.queryParam(name, formatUriValue(conversionService, new TypeDescriptor(parameter), value));
  121. }
  122. }
  123. @Nullable
  124. protected String formatUriValue(
  125. @Nullable ConversionService cs, @Nullable TypeDescriptor sourceType, @Nullable Object value) {
  126. if (value == null) {
  127. return null;
  128. }
  129. else if (value instanceof String) {
  130. return (String) value;
  131. }
  132. else if (cs != null) {
  133. return (String) cs.convert(value, sourceType, STRING_TYPE_DESCRIPTOR);
  134. }
  135. else {
  136. return value.toString();
  137. }
  138. }
  139. private static class RequestParamNamedValueInfo extends NamedValueInfo {
  140. public RequestParamNamedValueInfo() {
  141. super("", false, ValueConstants.DEFAULT_NONE);
  142. }
  143. public RequestParamNamedValueInfo(RequestParam annotation) {
  144. super(annotation.name(), annotation.required(), annotation.defaultValue());
  145. }
  146. }
  147. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/66295
推荐阅读
相关标签
  

闽ICP备14008679号