一、原理
废话不多说,上图
SpringMVC流程
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
注:DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制。
SpringMVC和Spring的区别
首先,Springmvc和Spring它俩都是容器,容器就是管理对象的地方,例如Tomcat,就是管理Servlet对象的,而SpringMVC容器和Spring容器,就是管理bean对象的地方,再说的直白点,Springmvc就是管理controller对象的容器,Spring就是管理service和dao的容器,这下你明白了吧。所以我们在Springmvc的配置文件里配置的扫描路径就是controller的路径,而spring的配置文件里自然配的就是service和dao的路径。
其次, Spring容器和Springmvc容器的关系是父子容器的关系。Spring容器是父容器,Springmvc是子容器。在子容器里可以访问父容器里的对象,但是在父容器里不可以访问子容器的对象,说的通俗点就是,在controller里可以访问service对象,但是在service里不可以访问controller对象。
而web容器又是什么鬼,
web容器是管理servlet,以及监听器(Listener)和过滤器(Filter)的。这些都是在web容器的掌控范围里。但他们不在spring和springmvc的掌控范围里。因此,我们无法在这些类中直接使用Spring注解的方式来注入我们需要的对象,是无效的,web容器是无法识别的。
但我们有时候又确实会有这样的需求,比如在容器启动的时候,做一些验证或者初始化操作,这时可能会在监听器里用到bean对象;又或者需要定义一个过滤器做一些拦截操作,也可能会用到bean对象。
那么在这些地方怎么获取spring的bean对象呢?下面我提供两个方法:
1、
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext context = (ApplicationContext) sce.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
UserService userService = (UserService) context.getBean("userService");
}
2、
public void contextInitialized(ServletContextEvent sce) {
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
UserService userService = (UserService) webApplicationContext.getBean("userService");
}
注意:以上代码有一个前提,那就是servlet容器在实例化ConfigListener并调用其方法之前,要确保spring容器已经初始化完毕!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,因此只需在web.xml中先配置初始化spring容器的Listener,然后在配置自己的Listener。