文章目录
SpringMVC学习笔记
1. 执行流程
2. dispatcherServlet初始化过程
- 执行静态代码块。加载配置文件DispatcherServlet.properties ,初始化属性defaultStrategies。用于后续init方法中的默认策略。
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
- 无参构造或者传入上下文的有参构造都会调用父类的set方法将dispatchOptionsRequest的值设为true(父类默认false)。该参数用于决定该servlet是否分发HTTP OPTIONS请求到doService方法。
- onRefresh()方法。调用initStrategies方法初始化策略。
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* 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);
}
- MultipartResolver: 文件上传。先从上下文中获取bean,如果没有则不提供该解析器。
/**
* Initialize the MultipartResolver used by this class.
* <p>If no bean is defined with the given name in the BeanFactory for this namespace,
* no multipart handling is provided.
*/
private void initMultipartResolver(ApplicationContext context) {
try {
this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// Default is no multipart resolver.
this.multipartResolver = null;
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
"': no multipart request handling provided");
}
}
}
public interface MultipartResolver {
// 判断请求是否包含文件流
boolean isMultipart(HttpServletRequest request);
// 将请求解析成MultipartHttpServletRequest
MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
void cleanupMultipart(MultipartHttpServletRequest request);
}
- LocaleResolver: 国际化。先从上下文获取,没有则从默认策略中取。
- ThemeResolver: 主题。先从上下文获取,没有则从默认策略中取。
- HandlerMappings: 处理器映射器。
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// 扫描所有的handlerMapping
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// 找到当前容器所有的处理器映射器,包括父级容器的
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
// 只扫描beanName为“handlerMapping”的处理器映射器
else {
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
// 将其设为单例
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
// 如果以上扫描之后没有找到handlerMapping,则从默认策略中获取
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
- HandlerAdapters: 处理器适配器。
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
// 扫描所有的处理器适配器
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
// 找当前容器中以及父级容器中所有的处理器适配器
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
// 只扫描beanName为“handlerAdapter”的处理器适配器
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
// 设置为单例
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
// 如果以上代码没有获取到处理器映射器,则从默认策略中获取。
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}
- HandlerExceptionResovlers: 处理器异常。和处理器映射器、处理器适配器的初始化方法类似。
- RequestToViewNameTranslator: 请求视图转换器
- ViewResolvers:视图解析器。
public interface ViewResolver {
@Nullable
View resolveViewName(String viewName, Locale locale) throws Exception;
}
private void initViewResolvers(ApplicationContext context) {
this.viewResolvers = null;
// 根据属性判断是否扫描全部视图解析器
if (this.detectAllViewResolvers) {
// Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
// 扫描当前容器以及父容器中所有的视图解析器
Map<String, ViewResolver> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.viewResolvers = new ArrayList<>(matchingBeans.values());
// We keep ViewResolvers in sorted order.
AnnotationAwareOrderComparator.sort(this.viewResolvers);
}
}
// 只扫描beanName为“viewResolver”的bean
else {
try {
ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
// 单例
this.viewResolvers = Collections.singletonList(vr);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default ViewResolver later.
}
}
// Ensure we have at least one ViewResolver, by registering
// a default ViewResolver if no other resolvers are found.
// 没有获取到识图解析器,则从默认策略中获取
if (this.viewResolvers == null) {
this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
}
}
}
- FlashMapManager: flashMap检索和保存。重定向属性存储(maybe)。
3. 关键方法
- getDefaultStrategy(ApplicationContext context, Class strategyInterface),该方法用于initStrategies()中初始化各个属性。
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
List<T> strategies = getDefaultStrategies(context, strategyInterface);
------------------------------------------------
if (strategies.size() != 1) {
throw new BeanInitializationException(
"DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
}
return strategies.get(0);
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
String key = strategyInterface.getName();
String value = defaultStrategies.getProperty(key);
// 默认策略配置中有则遍历生产类,没有则返回空
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
List<T> strategies = new ArrayList<>(classNames.length);
for (String className : classNames) {
try {
// 反射生成策略类,此处使用getAutowireCapableBeanFactory创建bean
Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
Object strategy = createDefaultStrategy(context, clazz);
strategies.add((T) strategy);
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find DispatcherServlet's default strategy class [" + className +
"] for interface [" + key + "]", ex);
}
catch (LinkageError err) {
throw new BeanInitializationException(
"Unresolvable class definition for DispatcherServlet's default strategy class [" +
className + "] for interface [" + key + "]", err);
}
}
return strategies;
}
else {
// 返回空
return new LinkedList<>();
}
}
- doService(HttpServletRequest request, HttpServletResponse response)
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 打印日志
if (logger.isDebugEnabled()) {
String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
}
// Keep a snapshot of the request attributes in case of an include,
// to be able to restore the original attributes after the include.
// 保存一份副本,用于doInclude类型请求(maybe)
Map<String, Object> attributesSnapshot = null;
if (WebUtils.isIncludeRequest(request)) {
attributesSnapshot = new HashMap<>();
Enumeration<?> attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
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());
if (this.flashMapManager != null) {// ???
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);
}
// 关键方法 “the actual dispatching”
try {
doDispatch(request, response);
}
finally {
// ??释放资源
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Restore the original attribute snapshot, in case of an include.
if (attributesSnapshot != null) {
restoreAttributesAfterInclude(request, attributesSnapshot);
}
}
}
}
- doDispatch(HttpServletRequest request, HttpServletResponse response)
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);// 如果request不为空并且isMultipart,则将request解析成为MultipartHttpServletRequest
multipartRequestParsed = (processedRequest != request);// 是否是文件流请求
// Determine handler for the current request.
// 遍历处理器映射器list,获取与当前requset匹配的第一个处理器执行链
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
// 404
noHandlerFound(processedRequest, response);
return;
}
// Determine handler adapter for the current request.
// 通过处理器执行链获取处理器映射器。遍历处理器映射器list,返回第一个supports(handler)为true的处理器适配器
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)) {
// 处理lastModified(????)
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 处理器执行链调用拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 处理器适配器调用controller
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 如果是异步请求则return
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 给空mv设置默认name
applyDefaultViewName(processedRequest, mv);
// 处理器执行链调用拦截器的postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 将异常设置到mv中,调用拦截器的afterCompletion方法
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// 处理异常
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Throwable err) {
triggerAfterCompletion(processedRequest, response, mappedHandler,
new NestedServletException("Handler processing failed", err));
}
// 释放资源
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
4. doService
- 打印日志
- 保存request副本用于include
- 给request设置属性(localeResolver、themeResolver、flashMapManager)
- 调用doDispatcher
- 处理异常、释放资源
5. doDispatcher
- 判断是否为文件流请求并解析(multipartResolver)
- 遍历handlerMappings,根据request用getHandle()找到handler(handlerMappings)
- 遍历handlerAdapters,根据handler用supports()找到adapter(handlerAdapters)
- 处理last-modify
- 调用拦截器的preHandle方法
- 处理器执行(调用controller)
- 判断是否为异步,异步则return
- 给没有值的mv设置默认name(requestToViewNameTranslator)
- 调用拦截器的postHandle方法
- 捕获dispatcherException
- 处理dispatcher异常、解析modelAndView;调用拦截器的afterCompletion方法(viewResolver、dispatcherExceptionHandler)
- 处理异常、释放资源
6. SpringMVC容器和Spring容器关系(not sure)
两者都是容器,都能管理对象。springMVC管理controller对象,spring容器管理service、dao对象。SpringMVC容器和Spring容器是父子容器的概念,Spring容器为父容器,SpringMVC容器为子容器,子容器可以访问父容器中管理的对象,但是父容器不能访问子容器中的对象。