springMvc参数绑定之list

本文探讨了在SpringMVC中使用List作为控制器方法参数时出现的问题及解决办法。通过对比不同注解的作用,深入分析了@RequestParam对于List类型参数解析的重要性,并通过源码解析揭示了参数解析的具体过程。
public Map<String, Object> method(@NotNull List<String> list){ 
  //your code
}

在开发中, 遇到某些场景需要传入一个集合参数, 当我理所应当的写出上述代码, 并且进行调试的时候, 却出现了和意料中不一样的结果:

HTTP Status 500 - Request processing failed; 
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [java.util.List]: Specified class is an interface

  

 原来如此, 原来List是一个接口, 那么我换成实现就应该好了, 于是将代码修改为:

public Map<String, Object> method(@NotNull ArrayList<String> list){ 
  //your code
}

  

当我使用swagger接口文档进行调试, 输入以下参数

这下应该好了吧, 但是实际上和我想的还是不一样, 接口调用不报错了, 但是:

接口中的参数是一个空集合, 经过胡乱探索发现, 在参数上做一点小改动就可以达到正确传入:

public Map<String, Object> method(@NotNull @RequestParam List<String> list){ 
  //your code 
}

  

效果图:

但是为什么?, 通过跟踪源码发现, 存在一个参数解析的过程, 不同的注解使用不同的解析器来解析, 其中这篇文章对我的启发很大, 推荐大家看看

https://www.2cto.com/kf/201405/301660.html

经过追踪分析源码, 比对存在@RequestParam和不存在的情况, 发现参数解析是一种尝试行为, 如果能解析出来, 那么正确赋值. 下面特出关键源码, 源码类为:

org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver

代码如下:

@Override
	public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

		Class<?> paramType = parameter.getParameterType();
		NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);

          //从request中获取参数 Object arg = resolveName(namedValueInfo.name, parameter, webRequest); if (arg == null) { if (namedValueInfo.defaultValue != null) { arg = resolveDefaultValue(namedValueInfo.defaultValue); } else if (namedValueInfo.required && !parameter.getParameterType().getName().equals("java.util.Optional")) { handleMissingValue(namedValueInfo.name, parameter); } arg = handleNullValue(namedValueInfo.name, arg, paramType); } else if ("".equals(arg) && namedValueInfo.defaultValue != null) { arg = resolveDefaultValue(namedValueInfo.defaultValue); }
         //如果绑定处理工厂不是空, 尝试进行参数解析, 这里将会正确的将list参数解析为list, 本例中如果不加Requestparam那么是不会进入的. if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name); try { arg = binder.convertIfNecessary(arg, paramType, 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; }

  

至此, 知其所以然. mark一下

 

转载于:https://www.cnblogs.com/damoyuan/p/7891752.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值