剖析SpringMVC流程与整合(八)
SpringMVC运行流程
- 流程图
- SpringMVC工作流程描述
- 用户向服务器发送请求, 请求被SpringMVC前端控制器DispatcherServlet捕获.
- DispatcherServlet对请求URL进行解析, 得到请求资源标识符(URI), 判断请求URI对应的映射.
- 若不存在
- 再去判断是否配置了 mvc:default-servlet-handler
- 若没配置, 则控制台报映射找不到, 客户端显示404错误.
-
如果有配置, 则执行目标资源(一般为静态资源, 如: HTML)
- 存在
- 继续执行.
- 若不存在
- 根据该URI, 调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器), 最后以HandlerExecutionChain对象的形式返回.
-
DispatcherServlet根据获得的Handler, 选择一个合适的HandlerAdapter.
- 如果成功获得HandlerAdapter后, 此时将开始执行拦截器的preHandler(...)方法 【正向】
- 提取Request中的模型数据, 填充Handler入参, 开始执行Handler(Controller)方法, 处理请求, 在填充Handler的入参过程中, 根据你的配置, Spring会做一些额外的工作.
-
HttpMessageConveter: 将请求消息(如Json, xml等数据)转换成一个对象, 将对象转换为指定的响应信息.
-
数据转换: 对请求消息进行数据转换. 如String转换成Integer, Double等.
-
数据格式化: 对请求消息进行数据格式化, 如将字符串转换成格式化数字或格式化日期等.
-
数据验证: 验证数据的有效性(长度, 格式等), 验证结果存储到BindingResult或Error中.
-
-
Handler执行完成后, 向DispatcherServlet返回一个ModelAndView对象.
- 此时将开始执行拦截器的postHandle(...)方法 【逆向】
-
根据返回的ModelAndView(此时会判断是否存在异常: 如果存在异常, 则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet, 根据Model和View, 来渲染视图.
-
在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】
- 将渲染结果返回给客户端.
Spring整合SpringMVC
- 整合问题
- 不整合
-
需要将Spring所管理的内容都交给SpringMVC管理, 这样会造成业务逻辑混乱.
-
- 整合
-
通常情况下, 类似于数据源, 事务, 整合其他框架都是放在Spring的配置文件中(而不是SpringMVC中)
-
实际上放入Spring配置文件对应的IOC容器中的还有Service和Dao
-
-
Spring的配置文件什么时候加载? 怎么加载?
-
因为监听器在项目开始时就启动, 所以将初始化spring的方法写入监听器中, 这样, spring会先servlet一步加载.
-
-
Spring提供好的监听器: ContextLoaderListener
- 在web.xml中配置ContextLoaderListener
<!-- 配置启动SpringIOC容器的Listener --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <listener> <!--默认回去找applicationContext.xml--> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
- web.xml中的执行顺序
- <context-param>
- <listener>
- <filter>
- <servlet>
- web.xml中的执行顺序
- ContextLoaderListener的作用
-
Spring和SpringMVC的关系
-
Spring是父容器, SpringMVC是子容器.
- 规定
-
子容器能够调用访问父容器中的bean, 而父容器不能调用访问子容器中的bean.
- 比如
controller层 -- service层 -- dao层 能通过controller访问到service和dao, 反之不行
-