springMVC是讲spring应用到web开发中。因此要明白springmvc我们得先看看spring和web这两部分。
spring
spring是一个IoC容器,帮助我们处理类的依赖,web开发中应该也有许多的类,他们的控制由spring来反转。
web
web中的servlet
先来看看最原始的,不使用任何框架的情况下,我们是怎么处理请求的。java的web开发,实际上是处理servlet。web服务器比如Tomcat是一个servlet容器。我们并不直接和client的request打交道。client的request都先由servlet容器处理,然后生成request和response交给我们处理,我们从request中解析数据,将处理的结果写入response中,这就是大概的流程,可以参照下面的图片。
下面是一个简单的例子:
|
|
|
|
我们定义了一个servlet叫做home,home绑定了url : /。当我们访问http://localhost:8080时,servlet容器就从web.xml中找到这个映射,再找到对应的servlet交给HomeServlet处理,HomeServlet向response中写入一个html。
web中的servletcontex
servletcontext是什么呢?每个web应用都有一个servletcontext和 至少一个servlet。servletcontex用于访问web应用参数、访问服务器信息、全局共享一些信息等。比如:可能所有servlet都会用到的一些对象,我们可以将其设置为servletcontext的属性。
如何将spring应用到web上
spring是IoC容器,将各种类的控制反转。而web开发中的类,我觉的大致分为两类:
- servletcontext相关的用于全局的一些类
- servlet相关的,只和这个servlet相关的类
好了再看看springmvc。他主要有两个WebApplicationContex。以我目前的理解,他们其实正是和上面两个方面的类对应。
我们有一些全局共享的类,我们将他们的控制交给root applicationcontext来管理。
另一些只有和servlet相关的类:Controller等,我们将其交给某个DispatchServlet创建的webapplicationcontext来管理。
再来看看dispatchservlet,为什么要有他呢,目前我的理解是为了简化web开发,因为按照最原始的方式开发,我们每增加一个接口就添加一个servlet,这样就需要频繁的配置web.xml。为了解决这个问题,创建一个前端控制器DispatchServlet,他统一接收然后分发给controller。而注解的方式来映射请求和controller,更简单一点。
ok,将他们结合起来,就是在适当的时机创建适当的WebApplicationContex,在用ApplicationContext来管理Beans。这样就将spring应用到了web开发中。
适当的时机
那应该什么时候创建WebApplicationContext呢?
RootApplicationContext
RootApplicationContex是一个带有公共色彩的IoC。我们很容易想到生成一个IoC,将他放到全局的servletcontext,那么这个IoC不就可以全局为我们使用了么。
既然他需要依赖全局的servletcontext,那么就容易联想到应该在全局的servletcontext初始化完成后,就创建这个IoC,然后再将他作为属性添加到servletcontext中。
那么怎么监听servletcontext初始化完成呢?当然是在web.xml中配置一个listener,并指定一个实现了servletcontextlistener的类来监听啦。springmvc也确实是这么做的,他提供一个ContextLoaderListener,这个类实现了servletcontextlistener接口,因此servletcontext初始化完成后会通知ContextLoaderListener,ContextLoaderListener会在这个回调中去初始化Root WebApplicationContext,然后作为属性添加到servletcontext中。
明白了上面的流程,我们就知道了,如果我希望创建一个Root ApplicationContext来管理一些公用的Beans,那么需要在wen.xml中配置一个Listener:
|
|
不过只配置这个还不够,我们还需要指定这个IoC需要管理的Beans。默认springmvc是创建一个xmlWebApplicationContext,因此需要一个xml的路径,这个路径默认是:WEB-INF/application.xml。不过你可以在web.xml中改变:
|
|
创建WebApplication的参数还有几个,下面介绍下:
|
|
|
|
最后我们可能会想,如果我并没有全局公共的类,因此也不需要一个Root IoC,可以么?是可以的,我们可以不用生成他,方法也就是不配置listener。
WebApplocationContext
这个既然描述的是管理某个Servlet的Bean的IoC,那么他的创建时机也就是这个servlet初始化的时候。springmvc提供了DispatchServlet来作为前端控制器,并生成一个IoC。
DispatchServlet–>FrameworkServlet–>HttpServletBean–>HttpServlet。这是继承关系。
HttpServletBean负责将初始化参数设置到该组件上(contextClass,contextConfigLocation等)。并提供一个initServletBean交给子类实现。
FramworkServlet重写了这个方法。通过contextclass找到对应的class初始化。然后config他。然后如果提供了contextInitializerClasses,那么调用initializer方法。提供onRefresh方法供重载。
DispatchServlet重写了onRefresh,实现了对DispatchServlet的初始化:
|
|
通过WebApplicationInitializer代替web.xml
Servlet3.0+之后可以通过代码来配置。主要是因为servlet容器会查找实现了ServletContainerInitailizer接口的类,如果能发现的话就会用它来配置容器。SpringMvc为这个接口提供了实现类:SpringServletContainerInitializer.这个类又会去找实现了WebApplicationInitializer的类。
|
|
当然spring 也提供了一些实现类:
|
|
如果你更喜欢xml,可以参照:
|
|