SpringMVC请求处理流程
DispatchServlet全局的流程控制DispatchServlet接收到请求顺序遍历Spring容器中的HandlerMapping对象(可以注册多个HandlerMapping处理器映射器对象)根据每个HandlerMapping对象的映射规则找到对应的处理器Controller和处理方法遍历spring容器中的所有HandlerAdapter对象,查看当前处理器适配器对象是否能够支持适
DispatchServlet
全局的流程控制
- DispatchServlet接收到请求
- 顺序遍历Spring容器中的HandlerMapping对象(可以注册多个HandlerMapping处理器映射器对象)
- 根据每个HandlerMapping对象的映射规则找到对应的处理器Controller和处理方法
- 遍历spring容器中的所有HandlerAdapter对象,查看当前处理器适配器对象是否能够支持适配找到的处理器对象Controller,能则调用适配器的接口handle()方法处理请求,处理前有拦截器的先执行拦截处理
- DispatchServlet收到请求处理结果(包括模型数据和逻辑视图)
- DispatchServlet会找到Spring容器中的ViewResolver对象将逻辑视图解析成物理页面文件。
注意对于使用了@ResponseBody注解的方法,DispatchServlet会使用合适的消息转换器将请求处理结果转换后返回给前台。 - DispatchServlet找到物理视图文件后,DispatchServlet使用视图模板引擎将模型数据渲染到物理视图页面中
- 最后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;
}
参考
更多推荐
所有评论(0)