Spring Boot 2.0.2-webmvc源码分析(四)

前面章节介绍了webmvc的请求流程,客户端第一次请求servlet时,会调用servlet的init()方法(对应执行DispatcherServlet的initStrategies方法),该方法只会初始化一次,init方法初始完之后,紧接着执行service方法,对应DispatcherServlet的doDispatch方法,该方法会对请求参数进行解析,获取到对应handler,对应@Controller里面具体执行的方法,参数解析完成后,然后通过反射的原理调用Controller里面的@RequestMapping映射的method,方法执行完后,最后通过RequestResponseBodyMethodProcessor的handleReturnValue处理方法返回值,然后响应给客户端。
下面是前面测试的Controller

@RequestMapping("/hello")
public String hello() {
      return "hello spring boot webmvc";
}

可以看到上面hello方法没有参数,所以内部处理逻辑简单很多,我们现在把hello方法添加一个pojo参数,看一下加完参数之后,内部是怎么处理和解析该参数。

@RequestMapping("/hello")
public Student hello(@RequestBody Student student) {
     return student;
}

参数解析主要是通过HandlerMethodArgumentResolverComposite类的resolveArgument方法处理,通过类名,我们可以发现该类是通过组合模式进行实现,该方法的源码如下:

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

        HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); // 获取的是RequestResponseBodyMethodProcessor对象
        if (resolver == null) {
            throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
        }
        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    }

上面方法最终进入RequestResponseBodyMethodProcessor类的resolveArgument方法,该方法源码:

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

        parameter = parameter.nestedIfOptional();
        Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
        String name = Conventions.getVariableNameForParameter(parameter);

        if (binderFactory != null) {
            WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
            if (arg != null) {
                validateIfApplicable(binder, parameter);
                if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                    throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
                }
            }
            if (mavContainer != null) {
                mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
            }
        }

        return adaptArgumentIfNecessary(arg, parameter);
    }

通过上面的方法解析完参数后,继续执行InvocableHandlerMethod的invokeForRequest方法开始进行方法的调用,可以看下该方法源码:

@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
            Object... providedArgs) throws Exception {

        Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); // 这里既是获取解析后的参数,通过上面的resolveArgument方法进行
        Object returnValue = doInvoke(args);// 最终执行Method的invoke方法
        return returnValue; // 即Controller里method的返回值
    }

上面会执行完Controller里对应的method,得到method的返回值后,开始调用HandlerMethodReturnValueHandlerComposite类的handleReturnValue方法,该类和上面参数解析的类类似也是通过组合模式进行实现,该方法源码如下:

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

        HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        }
        handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }

上面方法最终进入RequestResponseBodyMethodProcessor类型handleReturnValue方法,由此可以发现,RequestResponseBodyMethodProcessor这个类既是对请求参数的解析,同时又对方法处理的返回值进行处理,最终响应给客户端。

@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

        mavContainer.setRequestHandled(true);
        ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
        ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

        // Try even with null return value. ResponseBodyAdvice could get involved.
        writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); //将方法处理结果返回给客户端
    }

你可能感兴趣的:(Spring Boot 2.0.2-webmvc源码分析(四))