Spring MVC 的核心類DispatcherServlet入口為onRefresh()方法复唤,而onRefresh()方法有直接調(diào)用了initStrategies()方法恃疯。代碼如下:
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
HandlerMapping
它的作用是根據(jù)請求(request)找到相應的Handler和Intercepters壕吹。HandlerMapping接口中只有一個getHandler()方法完域。對應的文檔如下:
/**
* Return a handler and any interceptors for this request. The choice may be made
* on request URL, session state, or any factor the implementing class chooses.
* <p>The returned HandlerExecutionChain contains a handler Object, rather than
* even a tag interface, so that handlers are not constrained in any way.
* For example, a HandlerAdapter could be written to allow another framework's
* handler objects to be used.
* <p>Returns {@code null} if no match was found. This is not an error.
* The DispatcherServlet will query all registered HandlerMapping beans to find
* a match, and only decide there is an error if none can find a handler.
* @param request current HTTP request
* @return a HandlerExecutionChain instance containing handler object and
* any interceptors, or {@code null} if no mapping found
* @throws Exception if there is an internal error
*/
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
我們也可以實現(xiàn)HandlerMapping接口浦楣,Override getHandler()方法自己定義一個MyHandlerMapping限煞。
public class MyHandlerMapping implements HandlerMapping{
@Override
public HandlerExecutionChain getHandler(HttpServletRequest request)throws Exception{
String mothed = request.getMethod();
if(mothed.equalsIgnoreCase("Get")){
return get方法對應的Handler;
}else{
return 其他方法對應的Handler;
}
return null;
}
}
通過配置<bean>方式注冊到spring容器中障本。
HandlerAdapter
HandlerMapping返回處理請求的Controller實例后弛槐,需要一個幫助定位具體請求方法的處理類懊亡,這個類就是HandlerAdapter,HandlerAdapter是處理器適配器乎串,Spring MVC通過HandlerAdapter來實際調(diào)用處理方法店枣。HandlerAdapter定義了如何處理請求的策略,通過請求url、請求Method和處理器的RequestMapping定義鸯两,最終確定使用處理類的哪個方法來處理請求闷旧,并檢查處理類相應處理方法的參數(shù)以及相關的Annotation配置,確定如何轉(zhuǎn)換需要的參數(shù)傳入調(diào)用方法钧唐,并最終調(diào)用返回ModelAndView忙灼。HandlerAdapter接口的三個方法如下:
/**
* MVC framework SPI, allowing parameterization of the core MVC workflow.
*
* <p>Interface that must be implemented for each handler type to handle a request.
* This interface is used to allow the {@link DispatcherServlet} to be indefinitely
* extensible. The {@code DispatcherServlet} accesses all installed handlers through
* this interface, meaning that it does not contain code specific to any handler type.
*
* <p>Note that a handler can be of type {@code Object}. This is to enable
* handlers from other frameworks to be integrated with this framework without
* custom coding, as well as to allow for annotation-driven handler objects that
* do not obey any specific Java interface.
*
* <p>This interface is not intended for application developers. It is available
* to handlers who want to develop their own web workflow.
*
* <p>Note: {@code HandlerAdapter} implementors may implement the {@link
* org.springframework.core.Ordered} interface to be able to specify a sorting
* order (and thus a priority) for getting applied by the {@code DispatcherServlet}.
* Non-Ordered instances get treated as lowest priority.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
* @see org.springframework.web.servlet.handler.SimpleServletHandlerAdapter
*/
public interface HandlerAdapter {
/**
* Given a handler instance, return whether or not this {@code HandlerAdapter}
* can support it. Typical HandlerAdapters will base the decision on the handler
* type. HandlerAdapters will usually only support one handler type each.
* <p>A typical implementation:
* <p>{@code
* return (handler instanceof MyHandler);
* }
* @param handler handler object to check
* @return whether or not this object can use the given handler
*/
boolean supports(Object handler);
/**
* Use the given handler to handle this request.
* The workflow that is required may vary widely.
* @param request current HTTP request
* @param response current HTTP response
* @param handler handler to use. This object must have previously been passed
* to the {@code supports} method of this interface, which must have
* returned {@code true}.
* @throws Exception in case of errors
* @return ModelAndView object with the name of the view and the required
* model data, or {@code null} if the request has been handled directly
*/
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
/**
* Same contract as for HttpServlet's {@code getLastModified} method.
* Can simply return -1 if there's no support in the handler class.
* @param request current HTTP request
* @param handler handler to use
* @return the lastModified value for the given handler
* @see javax.servlet.http.HttpServlet#getLastModified
* @see org.springframework.web.servlet.mvc.LastModified#getLastModified
*/
long getLastModified(HttpServletRequest request, Object handler);
}
通過配置<bean>方式注冊到spring容器中。
HandlerExceptionResolver
/**
* Interface to be implemented by objects than can resolve exceptions thrown
* during handler mapping or execution, in the typical case to error views.
* Implementors are typically registered as beans in the application context.
*
* <p>Error views are analogous to the error page JSPs, but can be used with
* any kind of exception including any checked exception, with potentially
* fine-granular mappings for specific handlers.
*
* @author Juergen Hoeller
* @since 22.11.2003
*/
public interface HandlerExceptionResolver {
/**
* Try to resolve the given exception that got thrown during on handler execution,
* returning a ModelAndView that represents a specific error page if appropriate.
* <p>The returned ModelAndView may be {@linkplain ModelAndView#isEmpty() empty}
* to indicate that the exception has been resolved successfully but that no view
* should be rendered, for instance by setting a status code.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler, or {@code null} if none chosen at the
* time of the exception (for example, if multipart resolution failed)
* @param ex the exception that got thrown during handler execution
* @return a corresponding ModelAndView to forward to,
* or {@code null} for default processing
*/
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
ViewResolver
ViewResolver負責將String類型的邏輯視圖和Locale解析我View類型的視圖钝侠。它主要有一個方法缀棍,如下:
/**
* Resolve the given view by name.
* <p>Note: To allow for ViewResolver chaining, a ViewResolver should
* return {@code null} if a view with the given name is not defined in it.
* However, this is not required: Some ViewResolvers will always attempt
* to build View objects with the given name, unable to return {@code null}
* (rather throwing an exception when View creation failed).
* @param viewName name of the view to resolve
* @param locale Locale in which to resolve the view.
* ViewResolvers that support internationalization should respect this.
* @return the View object, or {@code null} if not found
* (optional, to allow for ViewResolver chaining)
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
*/
View resolveViewName(String viewName, Locale locale) throws Exception;
RequestToViewNameTranslator
ViewResolver是通過viewName 來查找View的,但有些Handler處理完后机错,并沒有設置View或者viewName爬范,這是就需要從request來獲取View了,如何從request來獲取view呢弱匪?那就是RequestToViewNameTranslator所做的事情了青瀑。此接口中只有一個方法,如下:
/**
* Translate the given {@link HttpServletRequest} into a view name.
* @param request the incoming {@link HttpServletRequest} providing
* the context from which a view name is to be resolved
* @return the view name (or {@code null} if no default found)
* @throws Exception if view name translation fails
*/
String getViewName(HttpServletRequest request) throws Exception;
LocaleResolver
ViewResolver (視圖解析器)在解析視圖的時候需要兩個參數(shù)viewName和Locale萧诫。viewName可以通過Handler處理后獲得或者通過RequestToViewNameTranslator從request中獲取斥难。Local從哪兒來呢?LocaleResolver可以從request中獲取Locale帘饶。LocaleResolver接口的方法哑诊,如下:
/**
* Interface for web-based locale resolution strategies that allows for
* both locale resolution via the request and locale modification via
* request and response.
*
* <p>This interface allows for implementations based on request, session,
* cookies, etc. The default implementation is
* {@link org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver},
* simply using the request's locale provided by the respective HTTP header.
*
* <p>Use {@link org.springframework.web.servlet.support.RequestContext#getLocale()}
* to retrieve the current locale in controllers or views, independent
* of the actual resolution strategy.
*
* <p>Note: As of Spring 4.0, there is an extended strategy interface
* called {@link LocaleContextResolver}, allowing for resolution of
* a {@link org.springframework.context.i18n.LocaleContext} object,
* potentially including associated time zone information. Spring's
* provided resolver implementations implement the extended
* {@link LocaleContextResolver} interface wherever appropriate.
*
*/
public interface LocaleResolver {
/**
* Resolve the current locale via the given request. Can return a default locale as
* fallback in any case.
* @param request the request to resolve the locale for
* @return the current locale (never {@code null})
*/
Locale resolveLocale(HttpServletRequest request);
/**
* Set the current locale to the given one.
* @param request the request to be used for locale modification
* @param response the response to be used for locale modification
* @param locale the new locale, or {@code null} to clear the locale
* @throws UnsupportedOperationException if the LocaleResolver implementation does not
* support dynamic changing of the locale
*/
void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale);
}
ThemeResolver
/**
* Interface for web-based theme resolution strategies that allows for
* both theme resolution via the request and theme modification via
* request and response.
*
* <p>This interface allows for implementations based on session,
* cookies, etc. The default implementation is
* {@link org.springframework.web.servlet.theme.FixedThemeResolver},
* simply using a configured default theme.
*
* <p>Note that this resolver is only responsible for determining the
* current theme name. The Theme instance for the resolved theme name
* gets looked up by DispatcherServlet via the respective ThemeSource,
* i.e. the current WebApplicationContext.
*
* <p>Use {@link org.springframework.web.servlet.support.RequestContext#getTheme()}
* to retrieve the current theme in controllers or views, independent
* of the actual resolution strategy.
*/
public interface ThemeResolver {
/**
* Resolve the current theme name via the given request.
* Should return a default theme as fallback in any case.
* @param request request to be used for resolution
* @return the current theme name
*/
String resolveThemeName(HttpServletRequest request);
/**
* Set the current theme name to the given one.
* @param request request to be used for theme name modification
* @param response response to be used for theme name modification
* @param themeName the new theme name
* @throws UnsupportedOperationException if the ThemeResolver implementation
* does not support dynamic changing of the theme
*/
void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}
FlashMapManager
/**
* A strategy interface for retrieving and saving FlashMap instances.
* See {@link FlashMap} for a general overview of flash attributes.
*/
public interface FlashMapManager {
/**
* Find a FlashMap saved by a previous request that matches to the current
* request, remove it from underlying storage, and also remove other
* expired FlashMap instances.
* <p>This method is invoked in the beginning of every request in contrast
* to {@link #saveOutputFlashMap}, which is invoked only when there are
* flash attributes to be saved - i.e. before a redirect.
* @param request the current request
* @param response the current response
* @return a FlashMap matching the current request or {@code null}
*/
FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);
/**
* Save the given FlashMap, in some underlying storage and set the start
* of its expiration period.
* <p><strong>NOTE:</strong> Invoke this method prior to a redirect in order
* to allow saving the FlashMap in the HTTP session or in a response
* cookie before the response is committed.
* @param flashMap the FlashMap to save
* @param request the current request
* @param response the current response
*/
void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}