前面我们已经进行过SpringMVC的源码分析(详见《Spring源码DEBUG指南(3)——SpringMVC执行原理》),本篇主要以两段代码为切入点,梳理一下request请求在SpringMVC中的执行流程。
第一段代码,servlet的入口配置,它主要负责将request请求转交给SpringMVC
@Configuration
public class WebServletConfig {
@Bean
public ServletRegistrationBean<Servlet> servletConfig(DispatcherServlet dispatcherServlet){
ServletRegistrationBean<Servlet> servletBean =
new ServletRegistrationBean<>(dispatcherServlet);
//注意下面的拦截,一旦拦截住,就会把匹配到的部分删掉,只留下其它部分
//例如:index.html在拦截完成之后会变成 -> /index
//例如:/service/user/doRegister -> /user/doRegister
servletBean.getUrlMappings().clear(); //清空之前的默认配置,包括views中的默认index.jsp
servletBean.addUrlMappings("/service/*","*.html"); //添加2个拦截路径
return servletBean;
}
}
第二段代码,注册一个springmvc拦截器,负责对已经进入springmvc中,符合拦截条件的请求做拦截处理(包括:preHandle
、postHandle
、afterCompletion
三种处理)
@Configuration
public class MvcConfigurer implements WebMvcConfigurer{
@Autowired
private UserInterceptor userInterceptor;
//手动开启匹配后缀型配置,默认是关闭的(指的是request请求,而非视图解析器 )
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
}
//定义拦截器 添加需要匹配的路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor)
.addPathPatterns("/cart/**","/order/**");
}
}
那么这个servlet入口和拦截器,在执行过程中究竟是怎样影响我们请求的呢?
一图胜千言,一个request请求在SpringMVC中的“一日游”流程如下:
上图中拦截链的配置顺序为:InterceptorA -> InterceptorB -> InterceptorC,拦截链像一个环一样,将目标方法包裹了起来。
在SpringMVC的实现中,DispatcherServlet可是主角,整个执行流程都是它一手策划的,来来回回的执行逻辑都要靠它来转发和驱动。想要梳理源码的同学,直接定位到org.springframework.web.servlet.DispatcherServlet
这个类里面debug就好。