一、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;
}
}
分享到:
相关推荐
SpringMVC DispatcherServlet 初始化过程详解 DispatcherServlet 是 SpringMVC 框架中的核心组件,对于 SpringMVC 的请求处理和响应起着至关重要的作用。DispatcherServlet 的初始化过程是 SpringMVC 实现原理的...
在本文中,我们将深入探讨`DispatcherServlet`的初始化流程,这是SpringMVC的核心组件。`DispatcherServlet`扮演着中央调度者的角色,负责接收请求、解析请求信息,并调用合适的控制器进行业务逻辑处理。 首先,让...
SpringMVC DispatcherServlet重写、自定义拦截器拦截器源码
在 DispatcherServlet 的 init() 方法中,除了初始化 SpringIOC 容器外,还会初始化一些 SpringMVC 组件,包括: * MultipartResolver:处理multipart请求 * LocaleResolver:处理语言环境 * ThemeResolver:处理...
DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请求的入口,本篇将深入源码分析它的初始化过程。 首先,从DispatcherServlet的名称上可以看出它是一个Servlet,通过一张图来看一下它的实现...
同时,我们还指定了初始化参数contextConfigLocation,用于加载SpringMVC的配置文件spring-mvc.xml。 二、SpringMVC的配置文件 在SpringMVC的配置文件spring-mvc.xml中,我们需要配置controller的扫描路径和视图...
1. **加载配置**:`DispatcherServlet`会在初始化阶段读取配置文件(如`servlet-context.xml`),通过`WebApplicationContext`加载Bean定义。这个过程中,你可以自定义拦截器、视图解析器、异常处理器等关键组件。 ...
8. initViewResolvers:初始化ViewResolvers来解析视图。 9. initFlashMapManager:初始化FlashMapManager来管理跨请求的属性。 在处理请求时,DispatcherServlet首先从HandlerMappings中提取对应的Handler。...
总结,SpringMVC的处置流程始于Web应用的初始化,包括ContextLoaderListener加载根上下文和DispatcherServlet初始化子上下文。接着,DispatcherServlet负责接收和分发请求,通过HandlerMapping找到处理器,...
SpringMVC URL 与 Controller 方法初始化源码流程 Visio 文档 文档可以直接通过Visio进行编辑,方便二次修改、学习
在SpringMVC中 所有的请求都由dispatcherServlet处理(url-pattern配置的是/),当配置文件中有对静态资源的处理 时候 ,先匹配 welcome-file-list 中的文件,依次查找,找到了就 返回,如果没有找到就继续匹配到...
SpringMVC URL 与 Controller 方法初始化源码流程 Visio 文档 文档可以直接通过Visio进行编辑,方便二次修改、学习
SpringMVC中的DispatcherServlet在初始化时,会创建一个属于自己的ApplicationContext,我们通常称之为子容器。这个子容器负责处理与SpringMVC相关的bean,如Controller、ViewResolver、HandlerMapping等。...
03springmvc注解驱动开发的servlet3.0初始化配置类.avi
在`hou_job_springmvc2`或`hou_spring_mvc2`项目中,你可能会找到对应的配置文件(如`web.xml`),里面会定义DispatcherServlet的初始化参数。 2. **配置文件**:SpringMVC的配置通常在XML文件(如`servlet-context...
首先,Spring会初始化并管理所有组件,包括SpringMVC的DispatcherServlet、Controller以及Hibernate的SessionFactory。然后,当用户发起HTTP请求时,DispatcherServlet捕获请求并转发给相应的Controller。Controller...
这些文件定义了DispatcherServlet的初始化参数,控制器的映射,视图解析器等。 3. **@Controller注解**:标记在类上,表示该类为SpringMVC的控制器,处理来自客户端的请求。控制器中的方法通过@RequestMapping注解...
`web.xml`是应用的部署描述符,用于配置前端控制器DispatcherServlet和SpringMVC的初始化参数。`spring-servlet.xml`是SpringMVC的核心配置文件,用于定义处理器映射器、视图解析器以及其他Bean。 **3. 最少的Jar包...