spring-mvc3 源码分析

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);

}

}

}

参考:http://blog.csdn.net/joeyon1985/article/details/41083915

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/joeyon1985/article/details/41083915
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞