三、SpringMVC原理

学习内容

1、Web环境下spring配置

2、根IoC容器的启动

3、DispatcherServlet的启动和初始化

4、MVC组件

5、MVC处理请求流程


 

一、web环境下spring配置

在web.xml中配置DispatcherServlet和ContextLoaderListener

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:applicationContext.xml</param-value>

</context-param>

 

<servlet>

<servlet-name>springmvc</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:spring/springmvc-servlet.xml</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>springmvc</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>


 

二、根IoC容器的启动

以ContextLoaderListener为起点,继承关系如下图:

 

 

生命周期与ServletContext对应。

public interface ServletContextListener extends EventListener {

 

//当ServletContext初始化时,回调这个方法,初始化Ioc容器

public void contextInitialized(ServletContextEvent sce);

 

//当ServletContext销毁时,回调这个方法,销毁Ioc容器

public void contextDestroyed(ServletContextEvent sce);

}

 

Ioc载入过程由ContextLoader中完成,过程大致为,从ServletContext中获取在web.xml中配置的参数,如spring配置文件路径以及其他容器启动参数等。然后进行配置文件加载等一系列Spring IoC容器初始化过程。此IoC容器类型为WebApplicationContext。

以ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key,IoC容器实例为value,放入ServletContext,以便全局获取。

public interface WebApplicationContext extends ApplicationContext {

 

//该常量为ServletContext中key,value为WebApplicationContext实例,则

该容器可在web应用全局获取

String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";


 

三、DispatcherServlet的启动和初始化

DispatcherServlet的继承关系如下

 

a、MVC Ioc容器的启动

由继承关系可知,在Servlet创建时,会进行Spring MVC IoC容器的初始化工作。DispatcherServlet也会创建一个IoC容器(用于存放MVC Bean)与之对应,并且设置双亲容器为根容器,由IoC工作原理可知,向IoC容器getBean时,会先向双亲容器中获取,无法得到才从自身获取。所以根容器可以被其他Servlet容器共享。

 

b、初始化

在Spring MVC IoC容器初始化完成后。接着对MVC组件初始化,在initStrategies()方法完成。

protected void initStrategies(ApplicationContext context) {

initMultipartResolver(context);

initLocaleResolver(context);

initThemeResolver(context);

initHandlerMappings(context);

initHandlerAdapters(context);

initHandlerExceptionResolvers(context);

initRequestToViewNameTranslator(context);

initViewResolvers(context);

initFlashMapManager(context);

}

 

initHandlerMappings()

initHandlerMappings() 方法从 SpringMVC 容器及 Spring 的容器中查找所有的 HandlerMapping 实例,并把它们放入到 handlerMappings 这个 list 中。这个方法并不是对 HandlerMapping 实例的创建,HandlerMapping 实例是在Spring MVC容器初始化完成创建的。

initHandlerAdapters ()、initViewResolvers()的工作都与initHandlerMappings()类似。


 

四、MVC组件

 

1、HandlerMapping

HandlerMapping的作用是根据当前请求的找到对应的 Handler,并将 Handler(处理器)与请求对应的所有 HandlerInterceptor(拦截器)封装到 HandlerExecutionChain 对象中。

HandlerMapping 接口的内部只有一个方法:

HandlerExecutionChain getHandler(HttpServletRequest request)。

HandlerMapping 是由 DispatcherServlet 调用,DispatcherServlet 会从容器中取出所有 HandlerMapping 实例并遍历,让 HandlerMapping 实例根据自己实现类的方式去尝试查找 Handler。

 

Handler 可以是 HandlerMethod(封装了 Controller 中的方法)对象,也可以是 Controller 对象、 HttpRequestHandler 对象或 Servlet 对象,而 Handler 具体是哪种对象,与所使用的 HandlerMapping 实现类有关。

HandlerMapping 实现类有两重类型,分别继承自 AbstractHandlerMethodMapping(得到 HandlerMethod)和 AbstractUrlHandlerMapping(得到 HttpRequestHandler、Controller 或 Servlet),它们又统一继承于 AbstractHandlerMapping。横线中为三个常见HandlerMapping 实现类。

 

a、AbstractUrlHandlerMapping

获取的 Handler 的类型实际是一个 Controller 类,所以一个 Controller 只能对应一个请求。

实现类有:

1) ControllerClassNameHandlerMapping:根据类名访问 Controller。

2) BeanNameUrlHandlerMapping:利用 BeanName 来作为 URL 使用。

3) ControllerBeanNameHandlerMapping:根据 Bean 名访问 Controller,与 BeanNameUrlHandlerMapping 类似,但是bean名称不用遵循URL公约。

4) SimpleUrlHandlerMapping:可以将 URL 与处理器的定义分离,还可以对 URL 进行统一的映射管理。

 

b、AbstractHandlerMethodMapping

获取的 Handler 的类型是 HandlerMethod,Handler 是一个方法,它保存了方法的信息(如Method),所以一个 Controller 就可以处理多个请求。

AbstractHandlerMapping 只有一个实现类 RequestMappingHandlerMapping。

 

 

2、HandlerAdapter

根据 Handler 来找到支持它的 HandlerAdapter,通过 HandlerAdapter 执行这个 Handler 得到 ModelAndView 对象。

HandlerAdapter 接口中的方法:

public interface HandlerAdapter {

 

//判断当前HandlerAdapter是否支持这个Handler

boolean supports(Object handler);

 

//调用Handler处理请求

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

 

//

long getLastModified(HttpServletRequest request, Object handler);

 

}

继承关系

 

a、RequestMappingHandlerAdapter

RequestMappingHandlerMapping 获取的 Handler 是 HadnlerMethod 类型,它代表 Controller 里要执行的方法,RequestMappingHandlerAdapter 可以执行 HadnlerMethod 对象。

RequestMappingHandlerAdapter 的 handle() 方法是在它的父类 AbstractHandlerMethodAdapter 类中实现

@Override

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

return handleInternal(request, response, (HandlerMethod) handler);

}

handleInternal() 方法是由 RequestMappingHandlerAdapter 实现,以此类推

b、HttpRequestHandlerAdapter:执行 HttpRequestHandler 类型的 Handler

c、SimpleControllerHandlerAdapter:执行 Controller 类型的 Handler

d、SimpleServletHandlerAdapter:执行 Servlet 类型的 Handler

 

3、ViewResolver

根据视图的名称将其解析为 View 类型的视图。通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Model 填入模板中,生成 html 或其他格式的文件。

解析策略有JSP 、Velocity、FreeMaker、PDF视图解析,如果设置了多个解析策略则可以通过 order 属性来设定其优先级,数值越小优先级越高,前面的视图解析器解析后就不会让后面的继续解析。默认的解析策略是 InternalResourceViewResolver,按照 JSP 页面来解析。

继承关系

标题


 

五、MVC处理请求流程

 

由DispatcherServlet为起点,进入源码可知,DispatcherServlet负责协调和组织各个组件完成初始化,及请求处理响应工作。

A、初始化:

在web容器启动时,对 DispatcherServlet 进行实例化,然后调用它的 init() 方法进行初始化,在这个初始化过程中先建立SpringMVC的IOC容器,然后对组件进行初始化。

 

B、请求处理响应:

客户端发出请求,web容器接收到这个请求后,如果匹配 DispatcherServlet 在 web.xml 中配置的映射路径,就将请求转交给 DispatcherServlet 处理;

DispatcherServlet 取出所有 HandlerMapping 实例(每个实例对应一个 HandlerMapping 接口的实现类)并遍历,每个 HandlerMapping 会根据请求信息,通过自己实现类中的方式去找到处理该请求的 Handler,并且将这个 Handler 与对应的 HandlerInterceptor 封装成一个 HandlerExecutionChain 对象,一旦有一个 HandlerMapping 可以找到 Handler 则退出循环。

DispatcherServlet 取出所有 HandlerAdapter 组件,根据已经找到的 Handler,再从所有 HandlerAdapter 中找到可以处理该 Handler 的 HandlerAdapter 对象。执行 HandlerExecutionChain 中所有拦截器的 preHandler() 方法,然后再利用 HandlerAdapter 执行 Handler ,执行完成得到 ModelAndView,再依次调用拦截器的 postHandler() 方法。

根据返回的ModelAndView,选择一个适合的ViewResolver,且必须是已经注册到Spring容器中的ViewResolver,返回给DispatcherServlet。ViewResolver 将 ModelAndView 解析成 View,然后 View 会调用 render() 方法再根据 ModelAndView 中的数据渲染出页面;

最后再依次调用拦截器的 afterCompletion() 方法。将渲染出的页面返回给客户端,请求结束。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值