SpringMVC之组件概览

在这里会对各个组件进行宏观的介绍,在之后会详细介绍每个组件
HandlerMapping
它会根据request找到对应的处理器

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		for (HandlerMapping hm : this.handlerMappings) {
			if (logger.isTraceEnabled()) {
				logger.trace(
						"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
			}
			HandlerExecutionChain handler = hm.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
		return null;
	}

在查找的时候不单单只会返回给我们一个handler,还会将相关的拦截器和handler组成一个HandlerExecutionChain返回。
HandlerAdapter

public interface HandlerAdapter {

	boolean supports(Object handler);

	
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

	
	long getLastModified(HttpServletRequest request, Object handler);

}

它里面一共三个方法:
supports:判断是否可以使用某个Handler
handle:使用Handler来干活
getLastModified:获取资源的Last-Modified,它保存着资源最后一次修改的时间

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
			if (ha.supports(handler)) {
				return ha;
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

HandlerExceptionResolver:根据异常设置ModelAndView,之后再通过render方法进行渲染

public interface HandlerExceptionResolver {

	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);

}

在这个接口里面只定义了一个方法,他只需要根据错误类型解析出对应的ModelView
ViewResolver:将String类型的视图名和Locale解析为View类型的视图

public interface ViewResolver {
	View resolveViewName(String viewName, Locale locale) throws Exception;
}

BeanNameViewResolver是根据ViewName从ApplicationContext容器中查找响应的bean做View的,我们看一下它的源码:

public class BeanNameViewResolver extends WebApplicationObjectSupport implements ViewResolver, Ordered {

	private int order = Integer.MAX_VALUE;  // default: same as non-Ordered


	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public int getOrder() {
		return this.order;
	}


	@Override
	public View resolveViewName(String viewName, Locale locale) throws BeansException {
		ApplicationContext context = getApplicationContext();
		if (!context.containsBean(viewName)) {
			if (logger.isDebugEnabled()) {
				logger.debug("No matching bean found for view name '" + viewName + "'");
			}
			// Allow for ViewResolver chaining...
			return null;
		}
		if (!context.isTypeMatch(viewName, View.class)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Found matching bean for view name '" + viewName +
						"' - to be ignored since it does not implement View");
			}
			// Since we're looking into the general ApplicationContext here,
			// let's accept this as a non-match and allow for chaining as well...
			return null;
		}
		return context.getBean(viewName, View.class);
	}

}

根据viewName中Spring容器中查找Bean,如果查找不到或者查到后不是View类型则返回null,否则返回bean。
RequestToViewNameTranslator:ViewResolver是根据ViewName查找View,但有的Handler处理完后并没有设置View也没有设置viewName,这时就需要从request获取viewName

public interface 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;

}

这是它的接口定义,RequestToViewNameTranslator再SpringMVC容器里只可以配置一个,所以所有request到viewName的转换规则都要在一个Translator里面全部实现。
LocaleResolver:用于从request解析出Locale

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:解析主题,主题是通过一系列资源来具体体现的,要得到一个主题首先需要ThemeResolver根据Request解析出ThemeName,然后ThemeSource根据这个名字找到对应的Theme。

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

}

MultipartResolver:用于处理上传请求,处理方法是将普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取到File,如果上传多个文件,还可以调用getFileMap得到FileName->File结构的Map

public interface MultipartResolver {

	/**
	 * Determine if the given request contains multipart content.
	 * <p>Will typically check for content type "multipart/form-data", but the actually
	 * accepted requests might depend on the capabilities of the resolver implementation.
	 * @param request the servlet request to be evaluated
	 * @return whether the request contains multipart content
	 */
	boolean isMultipart(HttpServletRequest request);

	/**
	 * Parse the given HTTP request into multipart files and parameters,
	 * and wrap the request inside a
	 * {@link org.springframework.web.multipart.MultipartHttpServletRequest} object
	 * that provides access to file descriptors and makes contained
	 * parameters accessible via the standard ServletRequest methods.
	 * @param request the servlet request to wrap (must be of a multipart content type)
	 * @return the wrapped servlet request
	 * @throws MultipartException if the servlet request is not multipart, or if
	 * implementation-specific problems are encountered (such as exceeding file size limits)
	 * @see MultipartHttpServletRequest#getFile
	 * @see MultipartHttpServletRequest#getFileNames
	 * @see MultipartHttpServletRequest#getFileMap
	 * @see javax.servlet.http.HttpServletRequest#getParameter
	 * @see javax.servlet.http.HttpServletRequest#getParameterNames
	 * @see javax.servlet.http.HttpServletRequest#getParameterMap
	 */
	MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;

	/**
	 * Cleanup any resources used for the multipart handling,
	 * like a storage for the uploaded files.
	 * @param request the request to cleanup resources for
	 */
	void cleanupMultipart(MultipartHttpServletRequest request);

}

FlashMapManager:FlashMap主要用在redirect中传递参数。而FlashMapManager是用来管理FlashMap的

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

}

整个redirect的参数通过FlashMap传递的过程分为三步:
1、在处理器中将需要传递的参数设置到outputFlashMap中,设置方法是request.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE)拿到outputFlashMap,然后将参数设置进去
2、在RedirectView的renderMergedOutputModel方法中调用FlashMapManager的saveOutputFlashMap方法,将outputFlashMap中的参数设置到Session中
3、请求redirect后DispatcherServlet的doService会调用FlashMapManager的retrieveAndUpdate方法从Session中获取inputFlashMap并设置到Request的属性中备用,同时从Session中删除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值