SpringMVC02DispatchServlet的执行过程5HandlerAdapter.handle()

编程

HandlerAdapter.handle()此方法内有对请求参数的解析、调用Controller里的具体方法和对响应结果的处理。最终返回ModelAndView对象。

下面将介绍最核心的处理请求的HandlerAdapter.handle()方法,此方法通过调用对应的处理器对请求做出处理,并返回一个ModelAndView对象。HandlerAdapter是一个接口,因此handle()方法需要其子类实现。HandlerAdapter的类图如图所示。

重点分析的AbstractHandlerMethodAdapter类结构图如下:

挑选其中的AbstractHandlerMethodAdapter分析,handle()方法的实现如下:

/**

* This implementation expects the handler to be an {@link HandlerMethod}.

*/

@Override

@Nullable

public final ModelAndView handle(HttpServletRequest request,

HttpServletResponse response, Object handler) throws Exception {

return handleInternal(request, response, (HandlerMethod) handler);

}

AbstractHandlerMethodAdapter中的handle()方法是调用RequestMappingHandlerAdapter类中的handleInternal()方法完成功能的。入参中的handler其实就是Controller中自定义的方法。RequestMappingHandlerAdapter类中handleInternal()方法实现如下:

@Override

protected ModelAndView handleInternal(HttpServletRequest request,

HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ModelAndView mav;

checkRequest(request);

// Execute invokeHandlerMethod in synchronized block if required.

if (this.synchronizeOnSession) {

HttpSession session = request.getSession(false);

if (session != null) {

Object mutex = WebUtils.getSessionMutex(session);

synchronized (mutex) {

mav = invokeHandlerMethod(request, response, handlerMethod);

}

}

else {

// No HttpSession available -> no mutex necessary

mav = invokeHandlerMethod(request, response, handlerMethod);

}

}

else {

// No synchronization on session demanded at all...

mav = invokeHandlerMethod(request, response, handlerMethod);

}

if (!response.containsHeader(HEADER_CACHE_CONTROL)) {

if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {

applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);

}

else {

prepareResponse(response);

}

}

return mav;

}

invokeHandlerMethod()方法的代码可以看到,其会调用invokeHandlerMethod()方法并返回一个ModelAndView对象。

invokeHandlerMethod()方法部分实现如下:

/**

* Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}

* if view resolution is required.

* @since 4.2

* @see #createInvocableHandlerMethod(HandlerMethod)

*/

@Nullable

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,

HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ServletWebRequest webRequest = new ServletWebRequest(request, response);

try {

WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);

// 设置解析方法参数的解析器

if (this.argumentResolvers != null) {

invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

}

// 设置处理执行结果的处理器

if (this.returnValueHandlers != null) {

invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);

}

invocableMethod.setDataBinderFactory(binderFactory);

invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

ModelAndViewContainer mavContainer = new ModelAndViewContainer();

mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

modelFactory.initModel(webRequest, mavContainer, invocableMethod);

mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);

asyncWebRequest.setTimeout(this.asyncRequestTimeout);

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

asyncManager.setTaskExecutor(this.taskExecutor);

asyncManager.setAsyncWebRequest(asyncWebRequest);

asyncManager.registerCallableInterceptors(this.callableInterceptors);

asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

if (asyncManager.hasConcurrentResult()) {

Object result = asyncManager.getConcurrentResult();

mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];

asyncManager.clearConcurrentResult();

LogFormatUtils.traceDebug(logger, traceOn -> {

String formatted = LogFormatUtils.formatValue(result, !traceOn);

return "Resume with async result [" + formatted + "]";

});

invocableMethod = invocableMethod.wrapConcurrentResult(result);

}

// 下面将分析这个方法

invocableMethod.invokeAndHandle(webRequest, mavContainer);

if (asyncManager.isConcurrentHandlingStarted()) {

return null;

}

return getModelAndView(mavContainer, modelFactory, webRequest);

}

finally {

webRequest.requestCompleted();

}

}

invokeHandlerMethod()方法主要将请求参数和处理方法进行封装,并通过封装后的方法对象ServletInvocableHandlerMethod进行方法调用:

/**

* Invoke the method and handle the return value through one of the

* configured {@link HandlerMethodReturnValueHandler HandlerMethodReturnValueHandlers}.

* @param webRequest the current request

* @param mavContainer the ModelAndViewContainer for this request

* @param providedArgs "given" arguments matched by type (not resolved)

*/

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,

Object... providedArgs) throws Exception {

// 分析这个方法

Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);

setResponseStatus(webRequest);

if (returnValue == null) {

if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {

mavContainer.setRequestHandled(true);

return;

}

}

else if (StringUtils.hasText(getResponseStatusReason())) {

mavContainer.setRequestHandled(true);

return;

}

mavContainer.setRequestHandled(false);

Assert.state(this.returnValueHandlers != null, "No return value handlers");

try {

// 将返回值通过这个方法封装到ModelAndViewContainer对象中

this.returnValueHandlers.handleReturnValue(

returnValue, getReturnValueType(returnValue), mavContainer, webRequest);

}

catch (Exception ex) {

if (logger.isTraceEnabled()) {

logger.trace(formatErrorForReturnValue(returnValue), ex);

}

throw ex;

}

}

这里要注意,invokeAndHandle()方法调用了invokeForRequest()方法,invokeForRequest()方法实现如下:(这个方法在InvocableHandlerMethod类中)

/**

* Invoke the method after resolving its argument values in the context of the given request.

* <p>Argument values are commonly resolved through

* {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.

* The {@code providedArgs} parameter however may supply argument values to be used directly,

* i.e. without argument resolution. Examples of provided argument values include a

* {@link WebDataBinder}, a {@link SessionStatus}, or a thrown exception instance.

* Provided argument values are checked before argument resolvers.

* <p>Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the

* resolved arguments.

* @param request the current request

* @param mavContainer the ModelAndViewContainer for this request

* @param providedArgs "given" arguments matched by type, not resolved

* @return the raw value returned by the invoked method

* @throws Exception raised if no suitable argument resolver can be found,

* or if the method raised an exception

* @see #getMethodArgumentValues

* @see #doInvoke

*/

@Nullable

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,

Object... providedArgs) throws Exception {

Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);

if (logger.isTraceEnabled()) {

logger.trace("Arguments: " + Arrays.toString(args));

}

return doInvoke(args);

}

从方法实现可以看出,invokeForRequest()方法会首先获取请求中的处理方法执行所需要的参数,然后调用doInvoke()方法如下

/**

* Invoke the handler method with the given argument values.

*/

@Nullable

protected Object doInvoke(Object... args) throws Exception {

ReflectionUtils.makeAccessible(getBridgedMethod());

try {

return getBridgedMethod().invoke(getBean(), args);

}

catch (IllegalArgumentException ex) {

assertTargetBean(getBridgedMethod(), getBean(), args);

String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");

throw new IllegalStateException(formatInvokeError(text, args), ex);

}

catch (InvocationTargetException ex) {

// Unwrap for HandlerExceptionResolvers ...

Throwable targetException = ex.getTargetException();

if (targetException instanceof RuntimeException) {

throw (RuntimeException) targetException;

}

else if (targetException instanceof Error) {

throw (Error) targetException;

}

else if (targetException instanceof Exception) {

throw (Exception) targetException;

}

else {

throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);

}

}

}

doInvoke方法会调用getBridgedMethod()方法获取到Controller中开发者自定义的处理方法,并获得方法的Method对象,然后通过反射调用Method.invoke()方法完成对Controller中自定义的调用。

回到ServletInvocableHandlerMethod类的invokeAndHandle()方法,调用自定义方法后,将返回值通过handleReturnValue()方法封装到ModelAndViewContainer对象中。

再回到RequestMappingHandlerAdapter类的invokeHandlerMethod()方法中,执行完invokeAndHandle()方法后,将会调用getModelAndView()方法并返回ModelAndView对象。getModelAndView()方法如下:

@Nullable

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,

ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {

modelFactory.updateModel(webRequest, mavContainer);

if (mavContainer.isRequestHandled()) {

return null;

}

ModelMap model = mavContainer.getModel();

ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());

if (!mavContainer.isViewReference()) {

mav.setView((View) mavContainer.getView());

}

if (model instanceof RedirectAttributes) {

Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();

HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

if (request != null) {

RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);

}

}

return mav;

}

ModelAndView类中封装了Controller中自定义方法执行后的返回值和视图对象。

回到DispatcherServlet中,至此doDispatch()方法中的handle()方法分析完毕。此时得到了ModelAndView对象。

以上是 SpringMVC02DispatchServlet的执行过程5HandlerAdapter.handle() 的全部内容, 来源链接: utcz.com/z/513245.html

回到顶部