主要内容
主要从四个方面来解释springmvc是如何注入的。
- 文件的注入
- body的注入
- param的注入
- path variable的注入
其次,总结在日常开发中的这里可以有哪些规范来提升自己的研发效率。
源码分析
org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
/*** 获取当前方法参数的值* Get the method argument values for the current request, checking the provided* argument values and falling back to the configured argument resolvers.* <p>The resulting array will be passed into {@link #doInvoke}.* @since 5.1.2*/protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {MethodParameter[] parameters = getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;}//遍历解决每个参数(优先级、重复等问题)Object[] args = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {MethodParameter parameter = parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] != null) {continue;}if (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));}try {args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);}catch (Exception ex) {// Leave stack trace for later, exception may actually be resolved and handled...if (logger.isDebugEnabled()) {String exMsg = ex.getMessage();if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, exMsg));}}throw ex;}}return args;}
核心模型:
MethodParameter:方法参数的抽象
HandlerMethodArgumentResolver:核心用来解决参数的转换和注入的问题,同理这里用了HandlerMethodArgumentResolverComposite来解决HandlerMethodArgumentResolver的管理问题,同时提供缓存匹配结果。这里resolver有很多个,可以具体举几个例子来处理。
1. RequestParamMethodArgumentResolver
@Override@Nullableprotected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);if (servletRequest != null) {Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {return mpArg;}}//解决MultipartFile的注入Object arg = null;MultipartRequest multipartRequest = request.getNativeRequest(MultipartRequest.class);if (multipartRequest != null) {List<MultipartFile> files = multipartRequest.getFiles(name);if (!files.isEmpty()) {arg = (files.size() == 1 ? files.get(0) : files);}}if (arg == null) {String[] paramValues = request.getParameterValues(name);if (paramValues != null) {arg = (paramValues.length == 1 ? paramValues[0] : paramValues);}}return arg;}
�在解决mulitpartFile的时候,以下这段代码很重要
//参数名称会跟文件名匹配,才能数据一样;那么这个add的默认文件名是怎么设置的呢?if (MultipartFile.class == parameter.getNestedParameterType()) {if (multipartRequest == null && isMultipart) {multipartRequest = new StandardMultipartHttpServletRequest(request);}return (multipartRequest != null ? multipartRequest.getFile(name) : null);}
参数名称会跟文件名匹配,才能数据一样;那么这个add的默认文件名是怎么设置的呢? 在mock场景下,默认文件名就是自己new MockMultipartFile(fileName)
�
异常场景
- 文件上传的时候,报空指针异常。
编程规范
�
