首页 > 编程语言 >spring-mvc3 源码分析

spring-mvc3 源码分析

时间:2023-06-11 15:00:52浏览次数:48  
标签:mvc3 spring mappedHandler request mavContainer 源码 null response processedRequest

1,进入sevlet的service方法 

     public void service(ServletRequest req, ServletResponse res) 

throws ServletException, IOException 

     { 

HttpServletRequest 
request; 

HttpServletResponse 
response; 

 

try { 

   request = (HttpServletRequest) req; 

   response = (HttpServletResponse) res; 

} catch (ClassCastException e) { 

   throw new ServletException("non-HTTP request or response"); 

} 

service(request, response); 

     } 

 } 

 2,spring的FrameworkServlet类 

/** 

* Delegate GET requests to processRequest/doService. 

* <p>Will also be invoked by HttpServlet's default implementation of {@code doHead}, 

* with a {@code NoBodyResponse} that just captures the content length. 

* @see #doService 

* @see #doHead 

*/ 

@Override 

protected final void doGet(HttpServletRequest request, HttpServletResponse response) 

throws ServletException, IOException { 



processRequest(request, response); 

} 

 3,spring的FrameworkServlet类 

 /** 

* Process this request, publishing an event regardless of the outcome. 

* <p>The actual event handling is performed by the abstract 

* {@link #doService} template method. 

*/ 

protected final void processRequest(HttpServletRequest request, HttpServletResponse response) 

throws ServletException, IOException { 



long startTime = System.currentTimeMillis(); 

Throwable failureCause = null; 



LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 

LocaleContext localeContext = buildLocaleContext(request); 



RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); 

ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); 



WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 

asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); 



initContextHolders(request, localeContext, requestAttributes); 



try { 

doService(request, response); 

} 

catch (ServletException ex) { 

failureCause = ex; 

throw ex; 

} 

catch (IOException ex) { 

failureCause = ex; 

throw ex; 

} 

catch (Throwable ex) { 

failureCause = ex; 

throw new NestedServletException("Request processing failed", ex); 

} 



finally { 

resetContextHolders(request, previousLocaleContext, previousAttributes); 

if (requestAttributes != null) { 

requestAttributes.requestCompleted(); 

} 



if (logger.isDebugEnabled()) { 

if (failureCause != null) { 

this.logger.debug("Could not complete request", failureCause); 

} 

else { 

if (asyncManager.isConcurrentHandlingStarted()) { 

logger.debug("Leaving response open for concurrent processing"); 

} 

else { 

this.logger.debug("Successfully completed request"); 

} 

} 

} 



publishRequestHandledEvent(request, startTime, failureCause); 

} 

} 



 4,DispatcherServlet类 



/** 

* Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch} 

* for the actual dispatching. 

*/ 

@Override 

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 

if (logger.isDebugEnabled()) { 

String requestUri = urlPathHelper.getRequestUri(request); 

String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; 

logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed + 

" processing " + request.getMethod() + " request for [" + requestUri + "]"); 

} 



// Keep a snapshot of the request attributes in case of an include, 

// to be able to restore the original attributes after the include. 

Map<String, Object> attributesSnapshot = null; 

if (WebUtils.isIncludeRequest(request)) { 

logger.debug("Taking snapshot of request attributes before include"); 

attributesSnapshot = new HashMap<String, Object>(); 

Enumeration<?> attrNames = request.getAttributeNames(); 

while (attrNames.hasMoreElements()) { 

String attrName = (String) attrNames.nextElement(); 

if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) { 

attributesSnapshot.put(attrName, request.getAttribute(attrName)); 

} 

} 

} 



// Make framework objects available to handlers and view objects. 

request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); 

request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); 

request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); 

request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); 



FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); 

if (inputFlashMap != null) { 

request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); 

} 

request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); 

request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); 



try { 

doDispatch(request, response); 

} 

finally { 

if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { 

return; 

} 

// Restore the original attribute snapshot, in case of an include. 

if (attributesSnapshot != null) { 

restoreAttributesAfterInclude(request, attributesSnapshot); 

} 

} 

} 

 5,DispatcherServlet类 

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 

HttpServletRequest processedRequest = request; 

HandlerExecutionChain mappedHandler = null; 

boolean multipartRequestParsed = false; 



WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 



try { 

ModelAndView mv = null; 

Exception dispatchException = null; 



try { 

processedRequest = checkMultipart(request); 

multipartRequestParsed = processedRequest != request; 



// Determine handler for the current request. 

mappedHandler = getHandler(processedRequest, false); 

if (mappedHandler == null || mappedHandler.getHandler() == null) { 

noHandlerFound(processedRequest, response); 

return; 

} 



// Determine handler adapter for the current request. 

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 



// Process last-modified header, if supported by the handler. 

String method = request.getMethod(); 

boolean isGet = "GET".equals(method); 

if (isGet || "HEAD".equals(method)) { 

long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 

if (logger.isDebugEnabled()) { 

String requestUri = urlPathHelper.getRequestUri(request); 

logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); 

} 

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { 

return; 

} 

} 



if (!mappedHandler.applyPreHandle(processedRequest, response)) { 

return; 

} 



try { 

// Actually invoke the handler. 

mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 

} 

finally { 

if (asyncManager.isConcurrentHandlingStarted()) { 

return; 

} 

} 



applyDefaultViewName(request, mv); 

mappedHandler.applyPostHandle(processedRequest, response, mv); 

} 

catch (Exception ex) { 

dispatchException = ex; 

} 

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 

} 

catch (Exception ex) { 

triggerAfterCompletion(processedRequest, response, mappedHandler, ex); 

} 

catch (Error err) { 

triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); 

} 

finally { 

if (asyncManager.isConcurrentHandlingStarted()) { 

// Instead of postHandle and afterCompletion 

mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); 

return; 

} 

// Clean up any resources used by a multipart request. 

if (multipartRequestParsed) { 

cleanupMultipart(processedRequest); 

} 

} 

} 

 6,AbstractHandlerMethodAdapter类 extends WebContentGenerator implements HandlerAdapter, Ordered 

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 

throws Exception { 

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

} 

 7,AbstractHandlerMethodAdapter类 extends WebContentGenerator implements HandlerAdapter, Ordered 

@Override 

protected final ModelAndView handleInternal(HttpServletRequest request, 

HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { 



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

// Always prevent caching in case of session attribute management. 

checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); 

} 

else { 

// Uses configured default cacheSeconds setting. 

checkAndPrepare(request, response, true); 

} 



// 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) { 

return invokeHandleMethod(request, response, handlerMethod); 

} 

} 

} 



return invokeHandleMethod(request, response, handlerMethod); 

} 

 8,ServletInvocableHandlerMethod类 

public final void invokeAndHandle(ServletWebRequest webRequest, 

ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { 



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



setResponseStatus(webRequest); 



if (returnValue == null) { 

if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) { 

mavContainer.setRequestHandled(true); 

return; 

} 

} 

else if (StringUtils.hasText(this.responseReason)) { 

mavContainer.setRequestHandled(true); 

return; 

} 



mavContainer.setRequestHandled(false); 



try { 

this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); 

} 

catch (Exception ex) { 

if (logger.isTraceEnabled()) { 

logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex); 

} 

throw ex; 

} 

} 



 9,InvocableHandlerMethod 

private Object invoke(Object... args) throws Exception { 

ReflectionUtils.makeAccessible(this.getBridgedMethod()); 

try { 

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

} 

catch (IllegalArgumentException e) { 

String msg = getInvocationErrorMessage(e.getMessage(), args); 

throw new IllegalArgumentException(msg, e); 

} 

catch (InvocationTargetException e) { 

// Unwrap for HandlerExceptionResolvers ... 

Throwable targetException = e.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 { 

String msg = getInvocationErrorMessage("Failed to invoke controller method", args); 

throw new IllegalStateException(msg, targetException); 

} 

} 

} 

 10,业务方法 



 11,InvocableHandlerMethod 

public final Object invokeForRequest(NativeWebRequest request, 

ModelAndViewContainer mavContainer, 

Object... providedArgs) throws Exception { 

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



if (logger.isTraceEnabled()) { 

StringBuilder builder = new StringBuilder("Invoking ["); 

builder.append(this.getMethod().getName()).append("] method with arguments "); 

builder.append(Arrays.asList(args)); 

logger.trace(builder.toString()); 

} 



Object returnValue = invoke(args); 



if (logger.isTraceEnabled()) { 

logger.trace("Method [" + this.getMethod().getName() + "] returned [" + returnValue + "]"); 

} 



return returnValue; 

} 

 12,HandlerMethodReturnValueHandlerComposite 

public void handleReturnValue( 

Object returnValue, MethodParameter returnType, 

ModelAndViewContainer mavContainer, NativeWebRequest webRequest) 

throws Exception { 



HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 

Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]"); 

handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); 

} 

 13,HandlerMethodReturnValueHandlerComposite 

/** 

* Iterate over registered {@link HandlerMethodReturnValueHandler}s and invoke the one that supports it. 

* @exception IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found. 

*/ 

public void handleReturnValue( 

Object returnValue, MethodParameter returnType, 

ModelAndViewContainer mavContainer, NativeWebRequest webRequest) 

throws Exception { 



HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType); 

Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]"); 

handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest); 

} 



 14,ViewNameMethodReturnValueHandler 

public void handleReturnValue( 

Object returnValue, MethodParameter returnType, 

ModelAndViewContainer mavContainer, NativeWebRequest webRequest) 

throws Exception { 



if (returnValue == null) { 

return; 

} 

else if (returnValue instanceof String) { 

String viewName = (String) returnValue; 

mavContainer.setViewName(viewName); 

if (isRedirectViewName(viewName)) { 

mavContainer.setRedirectModelScenario(true); 

} 

} 

else { 

// should not happen 

throw new UnsupportedOperationException("Unexpected return type: " + 

returnType.getParameterType().getName() + " in method: " + returnType.getMethod()); 

} 

} 



 15,RequestMappingHandlerAdapter 

private ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, 

HandlerMethod handlerMethod) throws Exception { 

 

ServletWebRequest webRequest = new ServletWebRequest(request, response); 



WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); 

ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); 

ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory); 



ModelAndViewContainer mavContainer = new ModelAndViewContainer(); 

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

modelFactory.initModel(webRequest, mavContainer, requestMappingMethod); 

mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); 



requestMappingMethod.invokeAndHandle(webRequest, mavContainer); 

modelFactory.updateModel(webRequest, mavContainer); 



if (mavContainer.isRequestHandled()) { 

return null; 

} 

else { 

ModelMap model = mavContainer.getModel(); 

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

if (!mavContainer.isViewReference()) { 

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

} 

if (model instanceof RedirectAttributes) { 

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

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

} 

return mav; 

} 

} 



 16,ModelAndView 

/** 

* Creates new ModelAndView given a view name and a model. 

* @param viewName name of the View to render, to be resolved 

* by the DispatcherServlet's ViewResolver 

* @param model Map of model names (Strings) to model objects 

* (Objects). Model entries may not be <code>null</code>, but the 

* model Map may be <code>null</code> if there is no model data. 

*/ 

public ModelAndView(String viewName, Map<String, ?> model) { 

this.view = viewName; 

if (model != null) { 

getModelMap().addAllAttributes(model); 

} 

} 

 17,DispatcherServlet 

 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 

HttpServletRequest processedRequest = request; 

HandlerExecutionChain mappedHandler = null; 

int interceptorIndex = -1; 



try { 

ModelAndView mv; 

boolean errorView = false; 



try { 

processedRequest = checkMultipart(request); 



// Determine handler for the current request. 

mappedHandler = getHandler(processedRequest, false); 

if (mappedHandler == null || mappedHandler.getHandler() == null) { 

noHandlerFound(processedRequest, response); 

return; 

} 



// Determine handler adapter for the current request. 

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 



                 // Process last-modified header, if supported by the handler. 

String method = request.getMethod(); 

boolean isGet = "GET".equals(method); 

if (isGet || "HEAD".equals(method)) { 

long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 

if (logger.isDebugEnabled()) { 

String requestUri = urlPathHelper.getRequestUri(request); 

logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); 

} 

if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { 

return; 

} 

} 



// Apply preHandle methods of registered interceptors. 

HandlerInterceptor[] interceptors = mappedHandler.getInterceptors(); 

if (interceptors != null) { 

for (int i = 0; i < interceptors.length; i++) { 

HandlerInterceptor interceptor = interceptors[i]; 

if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) { 

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 

return; 

} 

interceptorIndex = i; 

} 

} 



// Actually invoke the handler. 

mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 



// Do we need view name translation? 

if (mv != null && !mv.hasView()) { 

mv.setViewName(getDefaultViewName(request)); 

} 



// Apply postHandle methods of registered interceptors. 

if (interceptors != null) { 

for (int i = interceptors.length - 1; i >= 0; i--) { 

HandlerInterceptor interceptor = interceptors[i]; 

interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv); 

} 

} 

} 

catch (ModelAndViewDefiningException ex) { 

logger.debug("ModelAndViewDefiningException encountered", ex); 

mv = ex.getModelAndView(); 

} 

catch (Exception ex) { 

Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 

mv = processHandlerException(processedRequest, response, handler, ex); 

errorView = (mv != null); 

} 



// Did the handler return a view to render? 

if (mv != null && !mv.wasCleared()) { 

render(mv, processedRequest, response); 

if (errorView) { 

WebUtils.clearErrorRequestAttributes(request); 

} 

} 

else { 

if (logger.isDebugEnabled()) { 

logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + 

"': assuming HandlerAdapter completed request handling"); 

} 

} 



// Trigger after-completion for successful outcome. 

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null); 

} 



catch (Exception ex) { 

// Trigger after-completion for thrown exception. 

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); 

throw ex; 

} 

catch (Error err) { 

ServletException ex = new NestedServletException("Handler processing failed", err); 

// Trigger after-completion for thrown exception. 

triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex); 

throw ex; 

} 



finally { 

// Clean up any resources used by a multipart request. 

if (processedRequest != request) { 

cleanupMultipart(processedRequest); 

} 

} 

 
}

标签:mvc3,spring,mappedHandler,request,mavContainer,源码,null,response,processedRequest
From: https://blog.51cto.com/u_16088628/6457901

相关文章