SpringMVC请求处理流程

DispatchServlet

全局的流程控制

  1. DispatchServlet接收到请求
  2. 顺序遍历Spring容器中的HandlerMapping对象(可以注册多个HandlerMapping处理器映射器对象)
  3. 根据每个HandlerMapping对象的映射规则找到对应的处理器Controller和处理方法
  4. 遍历spring容器中的所有HandlerAdapter对象,查看当前处理器适配器对象是否能够支持适配找到的处理器对象Controller,能则调用适配器的接口handle()方法处理请求,处理前有拦截器的先执行拦截处理
  5. DispatchServlet收到请求处理结果(包括模型数据和逻辑视图)
  6. DispatchServlet会找到Spring容器中的ViewResolver对象将逻辑视图解析成物理页面文件。
    注意对于使用了@ResponseBody注解的方法,DispatchServlet会使用合适的消息转换器将请求处理结果转换后返回给前台。
  7. DispatchServlet找到物理视图文件后,DispatchServlet使用视图模板引擎将模型数据渲染到物理视图页面中
  8. 最后DispatchServlet将渲染后的页面返回给前台,请求结束。

HandlerMapping

在这里插入图片描述
HandlerMapping的使用主要分为两步:注册和查找。
根据请求的url映射到对应的处理器(Controller)的某个处理方法上
映射成功后返回一个HandlerExecutionChain对象(处理器执行链),其中包括处理器(Controller)以及拦截器

BeanNameUrlHandlerMapping(默认)

根据url和Bean的name进行映射找到处理器对象Controller

<bean name="/user/login.do" class="com.spring.web.controller.LoginController"/>
SimpleUrlHandlerMapping

初始化时会自动调用模板方法initApplicationContext()
AbstractUrlHandlerMapping类中定义了一个Map<String, Object>类型的变量handlerMap,用来存储url与handler的对应关系

// 存储url与handler的对应关系
private final Map<String, Object> handlerMap = new LinkedHashMap<>();
// 注册handler的方法
protected void registerHandler(String[] urlPaths, String beanName) 
			throws BeansException, IllegalStateException {}
protected void registerHandler(String urlPath, Object handler) 
			throws BeansException, IllegalStateException {}
// 根据url在该变量中找到相应的handler
// url是可以根据正则表达式来查找的,所以lookupHandler方法中还会根据url可能会查找到多个,
// 然后根据正则的匹配关系找到最符合的handler对象返回
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
}
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	<property name="mappings">
		<props>
			<prop key="/index">/HelloWorld</prop>
		</props>
	</property>
</bean>
<bean name="/HelloWorld" class="com.wangbiao.springMVC.HelloWorld"></bean>

上面xml定义的对应关系会被解析设置到SimpleUrlHandlerMapping类中的urlmap变量中

private final Map<String, Object> urlMap = new LinkedHashMap<>();
// 重写了父类AbstractHandlerMapping的initApplicationContext方法
public void initApplicationContext() throws BeansException {
    // 调用父类AbstractHandlerMapping的方法,主要功能是实现interceptor的初始化
    super.initApplicationContext();
    // 将本类中的urlmap注册到父类AbstractUrlHandlerMapping的handlerMap变量中
    registerHandlers(this.urlMap);
}
RequestMappingHandlerMapping

根据注解@Controller和@RequestMapping和url进行映射匹配对象的处理器Controller和处理方法

WelcomePageHandlerMapping

HandlerAdapter

public interface HandlerAdapter {
	boolean supports(Object handler);
	@Nullable
	ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 
				throws Exception;
	long getLastModified(HttpServletRequest request, Object handler);
}
private void initHandlerAdapters(ApplicationContext context) {
}
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
	if (this.handlerAdapters != null) {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (ha.supports(handler)) {
				return ha;
			}
		}
	}
}
HttpRequestHandlerAdapter

主要是适配静态资源处理器

SimpleControllerHandlerAdapter

适配实现了Controller接口或Controller接口子类的处理器

RequestMappingHandlerAdapter

适配使用注解@Controller和@RequestMapping标识的处理器

SimpleServletHandlerAdapter

适配实现了Servlet接口或Servlet的子类的处理器

ViewResolver

视图解析器

public interface ViewResolver {
	@Nullable
	// 根据一个逻辑的视图名称,获取到这个名称应该使用的View对象
	View resolveViewName(String viewName, Locale locale) throws Exception;
}

SpringMVC中可以同时定义多个ViewResolver视图解析器,然后它们会组成一个ViewResolver链
order越小,对应的 ViewResolver将有越高的解析视图的权利
像InternalResourceViewResolver这种能解析所有的视图,即永远能返回一个非空View对象的ViewResolver一定要把它放在ViewResolver链的最后面

ResourceBundleViewResolver

属性配置文件:

resourceBundle.(class)=org.springframework.web.servlet.view.InternalResourceView  
resourceBundle.url=/index.jsp  
test.(class)=org.springframework.web.servlet.view.InternalResourceView  
test.url=/test.jsp 

除了(class)之外,还 有(scope)、(parent)、(abstract)、(lazy-init)

UrlBasedViewResolver

拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。
URLBasedViewResolver支持返回的视图名称中包含redirect:前缀
URLBasedViewResolver还支持forword:前缀

private String prefix = "";
private String suffix = "";
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">  
   <property name="prefix" value="/WEB-INF/" />  
   <property name="suffix" value=".jsp" />  
   <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  
</bean> 
BeanNameViewResolver

BeanNameViewResolver要求视图bean对象都定义在Spring的application context中
BeanNameViewResolver不会进行视图缓存

<bean id="test" class="org.springframework.web.servlet.view.InternalResourceView">  
   <property name="url" value="/index.jsp"/>  
</bean>
XmlViewResolver

在指定的配置文件中寻找视图bean对象
支持视图缓存

<bean class="org.springframework.web.servlet.view.XmlViewResolver">  
   <property name="location" value="/WEB-INF/views.xml"/>  
   <property name="order" value="1"/>  
</bean>
InternalResourceViewResolver 内部资源视图解析器

展现jsp

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="contentType" value="text/html"/>        
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>
JstlView

使用JSTL的时候

ThymeleafViewResolver
FreeMarkerViewResolver
VolocityViewResolver

View

用于处理视图,然后返回给客户端

public interface View {
	void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
			throws Exception;
}

参考

HandlerMapping简介
ViewResolver简介

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐