SpringMVC解决了哪些问题?
将web页面请求传给服务器
根据不同的请求处理不同的逻辑单元
返回处理结果数据并跳转至响应页面
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:spring/applicationContext.xml
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring/dispatcher-servlet.xml
1
DispatcherServlet
/
对于SpringMVC功能实现分析,首先从web.xml开始,我们先看一下ContextLoaderListener所提供的功能。
一般编程我们可以将Spring配置信息像这样传入Spring容器。
ApplicationConexct ac = new ClassPathXmlApplicationContext("applicationContext.xml");
但在Web下,我们通常是将路径以context-param的方式注册并使用ContextLoaderlistener进行监听读取。
ContextLoaderlistener在启动WEB容器时,自动装配ApplicationContext的配置信息。ContextLoaderlistener实现了ServletContextListener接口,web.xml配置这个监听器,启动容器时,默认执行它实现的方法,使用ServletContextListener接口,可以为客户端请求服务之前像ServletContext添加任意对象。
每一个web应用都有一个ServletContext与之相关联。ServletContext对象在应用启动时被创建,关闭时被销毁。ServletContext在全局范围内有效,类似于应用中的一个全局变量。
当然我们可以配置自己的ContextListener,放入ServletContext相关数据,运行时候获取。
@WebListener
public class MyDataContextListener implements ServletContextListener {
private ServletContext context = null;
@Override
public void contextInitialized(ServletContextEvent sce) {
this.context = sce.getServletContext();
context.setAttribute("myData", "this is myData");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
context = null;
}
}
容器启动后,会调用contextInitialized方法。initWebApplicationContext是用来初始化webApplicationContext。
WebApplicationContext继承自ApplicationContext,在这个基础上又制定了一些特殊的操作和属性。
大致步骤:
1.WebApplicationContext是否存在的验证。配置中只允许声明一次ServletContextListener,多次声明影响Spring执行逻辑。然后将创建的WebApplicationContext实例记录在ServletContext中,方便全局调用。
2.调用createWebApplicationContext方法,创建WebApplicationContext实例。
通过properties中key对应的value就是我们要创建的context类名称。
这样就创建了一个XmlWebApplicationContext并加入到了ServletContext中。最后映射当前的类加载器与创建的实例到全局变量currentContextPerThread中。
DispatcherServlet
servlet声明周期是由servlet容器来控制的,分为3个阶段:初始化、运行和销毁。
初始化阶段
servlet容器加载servlet类,把servlet类的class文件中的数据读到内存中。
servlet容器创建一个servletConfig对象,ServletConfig对象包含了servlet的初始化配置信息。
servlet容器创建一个servlet对象。
servlet容器调用serlvet对象的init方法进行初始化。
运行阶段
当servlet容器接收到一个请求时,servlet容器会针对这个请求创建servletRequest和servletResponse对象,然后调用service方法。并把两个参数传递给service方法。service方法通过servletRequest对象获得请求信息。处理该请求。再通过servletResponse对象生成这个请求的相应结果。然后销毁servletRequest和servletResponse对象。
销毁阶段
当web应用被终止时,servlet容器先调用servlet对象的destrory方法,然后再销毁servlet对象,同时也会销毁与servlet对象相关联的ServletConfig对象。我们可以在servlet的destory中可以释放我们所占用的资源。例如关闭数据库连接。
servlet框架由两个Java包组成:java.servlet和javax.servlet.http。java.servlet定义所有servlet类必须实现的接口和类。java.servlet.http采用HTTP通信协议的HttpServlet类。
如果自己实现了一个servlet那么还需要在web.xml中配置一下就好了
DispatcherServlet初始化
既然是servlet那么初始化是执行的init方法。
具体步骤:
1.对init-param中配置进行封装。并校验一些属性,防止没有期望的值。
2.将当前servlet实例转化成BeanWapper实例。
3.注册相对于Resource的属性编辑器。当DispatcherServlet属性注入过程遇到Resource类型的属性酒桶使用ResourceEditor去解析。
4.属性注入。注入contextConfigLocation、contextAttribute、namespace等属性。
5.servletBean的初始化。在ContextLoaderListener加载时已经创建了WebApplicationContext实例。这个initServletBean方法用于补充初始化。
初始化webApplicationContext的方法initWebApplicationContext,该方法工作就是创建或刷新WebApplicationContext实例并对servletr功能所使用的变量进行初始化。
configureAndRefreshWebApplicationContext方法是用来加载配置文件的。调用的是AbstactApplicationContext提供的refresh方法。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大文件大小,单位字节 -->
<property name="maxUploadSize" value="100000"/>
</bean>
localeResolver用来对国际化配置的。
1.基于URL参数控制xxx.jd.com?local=zh_CN
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
2.基于session的配置。通过校验用户会话中预置的属性。
3.基于Cookie的配置。通过cookie来获取locale对象。
themeResolver通过主题theme来控制网页风格。一个主题就是一组静态资源如图片或者CSS样式。
需要制定静态资源路径,并且配合相应的解析器。有cookie、session的。
handlerMapping,通过它可以找到摸个路径对应的Controller。
我们可以提供多个HandlerMapping,DispatcherServlet会根据我们优先级排序。如果HandlerMapping能够返回可用的Handler,则不再询问其他的HandlerMapping。
默认情况下,SpringMVC会加载当前系统所有实现了HandlerMappingHandler接口的bean。我们也可以设置detectAllHandlerMappings为false,这样它就只加载名为handlerMapping的bean。
handlerAdapters,典型适配器模式的使用。适配器模式是将一个类的接口是配成用户所期待的。
初始化它也是先检测detect是否为true,为true加载所有的HanderAdapter。如果没找到bean,则尝试加载默认的适配器。
DispatcherServlet.properties配置文件中指定了默认的adapter。
DispatcherServlet通过处理映射找到Controller后,会轮询处理器适配器HandlerAdapter模块,查找能够处理当前http请求的处理器适配器,处理器适配器模块根据控制器类型,例如简单的处理器类型、注解处理器类型、或远程调用处理器类型,来选择一个适当的处理器适配器的实现,从而适配当前http请求。
SpringMVC 处理器适配器详解
Http请求处理器适配器
仅仅支持对HTTP请求处理器的适配。简单地将HTTP请求对象和响应对象传递给HTTP请求处理器的实现,它并不需要返回值。主要应用在HTTP的远程调用上。
简单控制器处理器适配器
这个实现类将HTTP请求适配到一个控制器的实现进行处理。这里控制器的实现是一个简单的控制器接口的实现。客户端的业务逻辑通常是在控制器接口的实现类中实现的。
注解方法处理器适配器
这个类的实现基于注解实现,需要结合注解方法映射和注解方法处理器协同工作。通过解析声明在注解控制器的请求映射信息来解析相应的处理器方法来处理当前的HTTP请求。在处理过程中,它通过反射来发现处理器方法的参数,调用处理器方法,并映射返回值到模型和控制器对象,最后返回模型和控制器对象给DispatcherServlet。
handlerExceptionResolvers是用于异常处理的,使用这种方式只需要实现resolveException方法,该方法返回一个ModelAndView对象。Spring会搜索所有handlerExceptionResolvers的bean,逐个执行,知道返回ModelAndView。
viewNameTranslator用于当Controller处理器没有返回view或逻辑视图名称,并且方法没有往response输出流里写数据,Spring就会采用约定好的方式提供一个逻辑视图名称。通过getViewName方法来实现的。我们可以实现自己的ToViewNameTranslator接口来约定好没有返回视图名称的时候用什么视图名称。
默认无返回视图解析器通过改造url来得到默认视图的。
viewResolvers,当Controller将请求处理结果放入到ModelAndView中后,DispatcherServlet会根据ModelAndView选择合适的视图进行渲染。ViewResolver接口定义了resolverViewName方法,根据ViewName创建合适类型的View。
flashMapManager,提供了一个请求存储属性,可供其他请求使用。在使用重定向时非常必要。Flash attributaes在重定向之前缓存以便重定向后还能使用,并立即删除。(这个东西没什么用。单机还能玩一玩)
看完了初始化话,无非就是从sping中取出所有相关类型,排序。要么就是配置detect为false,使用默认名称的bean。如果没有那么就从默认策略中,取出默认的相关bean。