SpringMVC DispatcherServlet的viewResolvers初始化

 

一、ViewResolver 接口
public interface ViewResolver {
//通过给定的名字解析返回View对象
View resolveViewName(String viewName, Locale locale) throws Exception;
}



二、InternalResourceViewResolver ViewResolver 实现类

public class InternalResourceViewResolver extends UrlBasedViewResolver {
//判断jstl类是否存在
private static final boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.core.Config", InternalResourceViewResolver.class.getClassLoader());
.........


public InternalResourceViewResolver() {
//实例创建时,默认使用InternalResourceView作为View
Class viewClass = requiredViewClass();
if (viewClass.equals(InternalResourceView.class) && jstlPresent) {
//如果JSTL API存在则使用JstlView作为View
	viewClass = JstlView.class;
		}
setViewClass(viewClass);
	}





UrlBasedViewResolver InternalResourceViewResolver 的父类

支持AbstractUrlBasedView的子类如:InternalResourceView、VelocityView、FreeMarkerView 可以通过该类的viewClass属性注入。
视图名称可以是资源的URL,或者通过指定prefix 和suffix组合成url
prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" ->
"/WEB-INF/jsp/test.jsp"
redirect:myAction.do 重定向到指定action,不会当视图名称解析。
forward:myAction.do请求转发。


public class UrlBasedViewResolver extends AbstractCachingViewResolver implements Ordered {
//有对应的setter和getter方法
private Class viewClass;
private String prefix = "";
private String suffix = "";
.....


//父类AbstractCachingViewResolver实现了ViewResolver接口,在实现该接口resolveViewName方法是调用了createView(viewName, locale);
@Override
protected View createView(String viewName, Locale locale) throws Exception {
                  if (!canHandle(viewName, locale)) {
			return null;
		}
//视图名前缀redirect:返回会重定向视图
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());

}
//视图名前缀forward:请求转发处理view
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
//普通视图名称解析生成View		
 return super.createView(viewName, locale);
}

//根据视图名加载View对象
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View result = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);
return (view.checkResource(locale) ? result : null);
}

//根据指定的视图名创建View的实例,并配置。这个view对象不会被spring容器的生命周期方法管理。
子类会首先调用super.buildView(viewName)也就是这个方法,然后再设置其他属性。
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils.instantiateClass(getViewClass());
view.setUrl(getPrefix() + viewName + getSuffix());
String contentType = getContentType();
if (contentType != null) {
	view.setContentType(contentType);
}
view.setRequestContextAttribute(getRequestContextAttribute());
view.setAttributesMap(getAttributesMap());
return view;
	}
}



======================================================================
三、View对象创建完成,JstlView作为View对象render渲染过程
(View在SpringMVC中作用)
3.1 View接口

public interface View {
//命名响应状态  
  String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
//根据给定的model渲染视图。
//第一步:预处理请求,在jsp中,就是将modle中的对象设置到请求属性中。
//第二步:实际的渲染处理,如包含一个JSP通过RequestDispatcher的include方法
void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}


3.2 AbstractView 抽象类对View接口render方法实现

public abstract class AbstractView extends WebApplicationObjectSupport implements View, BeanNameAware {

......

public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (logger.isTraceEnabled()) {
	logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
		" and static attributes " + this.staticAttributes);
}

//结合model
Map<String, Object> mergedModel =
new HashMap<String, Object>(this.staticAttributes.size() + (model != null ? model.size() : 0));
mergedModel.putAll(this.staticAttributes);
if (model != null) {
mergedModel.putAll(model);
}


if (this.requestContextAttribute != null) {
mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel));
}
//预处理响应
prepareResponse(request, response);
//实际渲染过程在InternalResourceView子类中实现。
renderMergedOutputModel(mergedModel, request, response);
}



protected void prepareResponse(HttpServletRequest request, HttpServletResponse response) {
		if (generatesDownloadContent()) {
			response.setHeader("Pragma", "private");
			response.setHeader("Cache-Control", "private, must-revalidate");
		}
	}



//将模型设置为request的属性
protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception {
for (Map.Entry<String, Object> entry : model.entrySet()) {
	String modelName = entry.getKey();
	Object modelValue = entry.getValue();
	if (modelValue != null) {
	request.setAttribute(modelName, modelValue);
if (logger.isDebugEnabled()) {
logger.debug("Added model object '" + modelName + "' of type [" + modelValue.getClass().getName() +
							"] to request in view with name '" + getBeanName() + "'");
				}
			}
			else {
		request.removeAttribute(modelName);
	if (logger.isDebugEnabled()) {
logger.debug("Removed model object '" + modelName +
"' from request in view with name '" + getBeanName() + "'");
				}
			}
		}
	}
....
}


3.3 AbstractView 的子类InternalResourceView




protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

//判断是否需要返回一个包装后的request对象
HttpServletRequest requestToExpose = getRequestToExpose(request);

//将model对象设置为request的属性
exposeModelAsRequestAttributes(model, requestToExpose);

//由子类JstlView实现,绑定spring或local资源文件
exposeHelpers(requestToExpose);

//获取请求的url地址 
String dispatcherPath = prepareForRendering(requestToExpose, response);

// 获取RequestDispatcher 对象
RequestDispatcher rd = requestToExpose.getRequestDispatcher(dispatcherPath);
if (rd == null) {
throw new ServletException(
"Could not get RequestDispatcher for [" + getUrl() + "]: check that this file exists within your WAR");
}


if (useInclude(requestToExpose, response)) {
response.setContentType(getContentType());
if (logger.isDebugEnabled()) {
logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
rd.include(requestToExpose, response);
}

else {

exposeForwardRequestAttributes(requestToExpose);
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
}
rd.forward(requestToExpose, response);
}



protected HttpServletRequest getRequestToExpose(HttpServletRequest originalRequest) {
		if (this.exposeContextBeansAsAttributes || this.exposedContextBeanNames != null) {
//返回Request的包装类,作用是在调用request的getAttribute方法时先从WebApplicationContext中找定义的bean对象,如果没有才从request对象中取属性
也就是将webApplicationContext容器中的bean作为request中的属性对象,暴露给的RequestDispatcher(请求转发到JSP页面转换成的servlet时可以从request中获取Ioc定义的bean或handle处理后的model对象)
return new ContextExposingHttpServletRequest(
originalRequest, getWebApplicationContext(), this.exposedContextBeanNames);
		}
		return originalRequest;
	}


}




















你可能感兴趣的:(spring,bean,jsp,servlet,IOC)