SpringMVC的执行流程
Handle是什么?
Handler是一个Controller的对象和请求方式的组合的一个Object对象
HandleExcutionChains是HandleMapping返回的一个处理执行链,它是对Handle的二次封装,将拦截器关联到一起。然后,在DispatcherServlert中完成了拦截器链对handler的过滤。
DispatcherServlet要将一个请求交给哪个特定的Controller,它需要咨询一个Bean——这个Bean的名字为“HandlerMapping”。HandlerMapping是把一个URL指定到一个Controller上,(就像应用系统的web.xml文件使用将URL映射到servlet)。
处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
核心架构的具体流程步骤如下:
1.首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2.DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3.DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4.HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
5.ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6.View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
下边两个组件通常情况下需要开发:
Handler:处理器,即后端控制器用controller表示。
View:视图,即展示给用户的界面,视图中通常需要标签语言展示模型数据。
个人理解:
HandlerMapping处理器映射器是根据客户端发送过来的URL路径去匹配指定处理器:DispatcherServlet要将一个请求交给哪个特定的Controller,它需要咨询一个Bean——这个Bean的名字为“HandlerMapping”。HandlerMapping是把一个URL指定到一个Controller上,(就像应用系统的web.xml文件使用将URL映射到servlet)。而HandlerAdapter:处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);意思就是调用控制器类下面的对应路由所要执行的方法。
源码分析:
SpringMVC的执行流程:
SpringMVC注解解析
SpringMVC的xml配置解析
查阅源码得知,对于视图解析器的转发重定向操作在源码中已经有了默认的配置,就是转发前缀forward和重定向前缀redirect,平常不改视图名前缀redirect的话(就是默认forward),则浏览器发生页面跳转时就是原来的url,如下图所示
运行的效果就是这样:
而改成了redirect之后,如下图:
运行效果:
可以明显看出,浏览器地址栏的url变了。这就是redirect和forward的作用。
还有视图前缀和视图后缀;
大概意思就是,先看一下我们控制器中的方法,很明显返回的是一个"success.jsp",因为这个jsp文件是放在web目录下的,所以需要这么写,以便于跳转到success.jsp页面。
而当我们不将页面文件放在web目录下,而是放在web目录下的子目录下,就会出现无法访问的情况,必须加上前缀的目录名才可跳转到正常页面,如下
现在只有一个文件,所以还看不出有什么繁琐的地方,当发现有成百上千的文件时就会知道这样写一个视图名前缀或者视图名后缀是多么繁琐的事情,而查阅源码我们发现,而在源码当中prefix和suffix都是有set方法的,所以我们可以自己手动在SpringMVC的配置文件中自己写上视图解析的前后缀以方便解析。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--组件扫描:扫描mvc该知道的注解类,也就是controller类
同时包扫描要用到context命名空间,所以还要在头文件中加上命名空间
-->
<context:component-scan base-package="com.itheima.controller"></context:component-scan>
<bean id="ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--这是前缀-->
<property name="prefix" value="/jsp/"></property>
<!--这是后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
然后控制器中就不需要前后缀了
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class UserController {
@RequestMapping("/quick")
public String save(){
System.out.println("Controller save running...");
return "success";
}
}