spring mvc

来源:互联网 发布:在线网络投资产品排行 编辑:程序博客网 时间:2024/06/13 22:38

  • Spring MVC
    • IOC容器在spirng mvc中的启动
      • 1 Web容器中的上下文
      • 2 ContextLoader建立Web环境的根上下文
    • Spring Web MVC的启动
      • 1 DispacherServlet概述
      • 2 DispacherServlet启动和初始化
    • Spring MVC的实现
      • 1 DispatcherSevlet的MVC初始化
    • HandlerMapping的配置以SimpleURLHandlerMapping为例
      • 1 HandlerMapping接口spring-webmvc下servlet中
      • 2 HandlerExecutionChain中Interceptor和Handler的配置
      • 3 使用HandlerMapping完成请求的映射处理
      • 4 Spring MVC对Http请求的分发处理
    • 视图的呈现
      • 1 概述
    • 2 jsp视图 参考P171


Spring MVC

1.IOC容器在spirng mvc中的启动

1.1. Web容器中的上下文

说明:

由ContextLoaderListener启动的上下文为根上下文.
在该上下文的基础上,与WEB MVC相关的上下文来保存控制器(DispatcherServlet)需要的MVC对象,作为根上下文的子上下文.

过程:

1.默认容器XmlWebApplicationContext(在…context.support中).
2.loadBeanDefinition()[和之前IOC实现的分析类似].
3.getConfigLocations()对Resource特别要求.

1.2. ContextLoader建立Web环境的根上下文

作用:在Web应用程序启动时载入IOC容器(或者说WebApplicationContext),由监听器完成

过程:

1.ContextLoaderListener–>contextInitialized()–>initWebApplicationContext(event.getServletContext())[在ContextLoader中实现]–>将创建的XmlWebApplicationContext对象放入WebApplicationContext的静态属性ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE中,然后存入ServletContext.

注: 在上面initWebApplicationContext中会调用createWebApplicationContext()

1.determineContextClass()决定使用什么样的类作为上下文:

protected Class<?> determineContextClass(ServletContext servletContext) {        //如果在ServletContext中配置了需要使用的CONTEXT_CLASS就使用该class!否则用默认的        String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);        if (contextClassName != null) {            try {                return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());            }            catch (ClassNotFoundException ex) {                throw new ApplicationContextException(                        "Failed to load custom context class [" + contextClassName + "]", ex);            }        }        else {            contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());            try {                return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());            }            catch (ClassNotFoundException ex) {                throw new ApplicationContextException(                        "Failed to load default context class [" + contextClassName + "]", ex);            }        }    }

2.在spring3中用reflash[如之前IOC容器分析]创建
2
在spring4中没看懂!

2. Spring Web MVC的启动

2.1 DispacherServlet概述

作用:建立自己的上下文来持有Spring MVC的bean对象(建立前从ServletContext中得到根上下文作为自己的双亲上下文).

2.2 DispacherServlet启动和初始化

过程(从FrameworkServlet[spring-webmvc下servlet中]入手):

1.初始化:在HttpServletBean对象的init(p152)方法中.

a.编程式的方式设置bean属性(PropertyValues,BeanWrapper等)
b.调用子类(FrameworkServlet)中的initServletBean

A.初始化上下文initWebApplicationContext()
接下来省略

3.Spring MVC的实现

3.1 DispatcherSevlet的MVC初始化

备注: 在DispatchServlet初始化过程中,让DispatchServlet持有一个IOC容器(WebApplicationContext)
位置: DispatcherSevlet中的initStrategies()
初始化具体实现如:

1.initHandlerMappings()默认从所有容器中获取HandlerMapping,也可以通过名字在当前IOC容器中用getBean()获取,如果没有找到HandlerMapping,就需要设定默认的HandlerMapping,可以设置在DispatcherServlet.properties中.
2…….

4.HandlerMapping的配置(以SimpleURLHandlerMapping为例)

4.1 HandlerMapping接口[spring-webmvc下servlet中]

a.getHandler()[AbstractHandlerMapping]获取http请求对应的HandlerExecutionChain(封装了具体的Controller)

备注:HandlerExecutionChain用到了典型的命令模式,持有Interceptor链(可以对handler增强)和handler(HTTP请求的Controller)对象

4.2 HandlerExecutionChain中Interceptor和Handler的配置

a.根据URL映射方式,注册Interceptor和handler,从而维护一个反映这种映射关系的HandlerExecutionChain。具体注册在SimpleURLHandlerMapping-->initApplicationContext()-->registerHandlers()中。

4.3 使用HandlerMapping完成请求的映射处理

取得Handler具体过程在AbstractUrlHandlerMapping的getHandlerInternal()中实现.

过程:request中取得请求的URL–>用URL匹配对应的Handler,如果没有对应的Handler返回Null,这样默认的Handler会被使用.

4.4 Spring MVC对Http请求的分发处理

位置: DispatcherServlet中的doService()(用来连接请求和业务逻辑[handler的handle函数中实现]),其中的doDispatch()完成实际的请求处理。

过程doDispatch
1. 为视图准备好一个ModelAndView(持有handler处理请求的结果)
2. mappedHandler = getHandler(processedRequest);[在上面提到的HandlerMapping中有解析]根据请求得到对应的handler
3. 调用handler的拦截器进行前处理
4. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());获取适配器,调用该适配器的handle()[实际上触发对Controller的handleRequest()方法的调用]
5. processDispatchResult()使用视图对ModelAndView数据的展示。

5 视图的呈现

5.1. 概述

作用:········
位置:DispatcherServlet中的render(mv, request, response);方法。
过程:

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {        //从request读取locale信息,设置response的locale值        Locale locale =                (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());        response.setLocale(locale);        View view;        String viewName = mv.getViewName();        if (viewName != null) {            // 根据ModleAndView中设置的视图名称进行解析,得到对应的视图对象.            view = resolveViewName(viewName, mv.getModelInternal(), locale, request);            if (view == null) {                throw new ServletException("Could not resolve view with name '" + mv.getViewName() +                        "' in servlet with name '" + getServletName() + "'");            }        }        else {            //  有可能ModelAndView中已经包含了View对象,则直接使用。            view = mv.getView();            if (view == null) {                throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +                        "View object in servlet with name '" + getServletName() + "'");            }        }        // Delegate to the View object for rendering.        if (logger.isDebugEnabled()) {            logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");        }        try {            if (mv.getStatus() != null) {                response.setStatus(mv.getStatus().value());            }            //调用view实现对数据进行呈现,并通过HttpResponse把视图呈现给http客户端。            view.render(mv.getModelInternal(), request, response);        }        catch (Exception ex) {            if (logger.isDebugEnabled()) {                logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +                        getServletName() + "'", ex);            }            throw ex;        }    }

a.上述代码中resolveViewName获取view(直接从上下文中获取):

    public View resolveViewName(String viewName, Locale locale) throws BeansException {        ApplicationContext context = obtainApplicationContext();        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);    }

b.具体视图的使用如下~~

5.2. jsp视图 参考P171

注:在exposeModelAsRequestAttributes()方法中,把ModelAndView中的模型数据和其他请求都放到HttpServletRequeest的属性中,所以这些数据就可以使用了。

原创粉丝点击