SpringMVC 请求流程
SpringMVC Spring 面试 About 17,885 words结合 Spring Boot
Spring Boot 2.6.0
流程梳理
容器初始化阶段
IOC
容器refresh
时加载自动配置类DispatcherServletAutoConfiguration
,DispatcherServlet
被注入到容器RequestMappingHandlerMapping
扫描所有Bean
将请求映射信息等信息保存在mappingRegistry
中,完成初始化后被注入到容器RequestMappingHandlerAdapter
请求真正执行的类被注入到容器
收到请求时
- 第一次收到请求时会初始化
DispatcherServlet
相关处理器HandlerMapping
等被加载到集合中 - 然后走到真正处理执行请求的
doDispatch
方法中- 根据路径和参数等信息包装的
request
找到对应的RequestMappingHandlerMapping
- 根据
RequestMappingHandlerMapping
的HandlerMethod
(包装了类对象和方法信息)找到RequestMappingHandlerAdapter
- 执行拦截器的前置处理器
- 反射调用方法(
@Controller
中的@RequestMapping
方法) - 执行拦截器的后置处理器
- 回调拦截器的
afterCompletion
- 根据路径和参数等信息包装的
源码解析
IOC
容器finishBeanFactoryInitialization
阶段初始化DispatcherServletAutoConfiguration
类
// DispatcherServlet 自动配置类
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";
@Configuration(proxyBeanMethods = false)
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {
// 注册 DispatcherServlet
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}
}
}
Spring Boot
启动时加载RequestMappingHandlerMapping
和RequestMappingHandlerAdapter
。
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
// 存放 @RequestMapping 映射的处理映射器 RequestMappingHandlerMapping
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
// Must be @Primary for MvcUriComponentsBuilder to work
return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider);
}
// 处理 @RequestMapping 映射的处理映射器适配器 RequestMappingHandlerAdapter
@Bean
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcValidator") Validator validator) {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager,
conversionService, validator);
adapter.setIgnoreDefaultModelOnRedirect(
this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
return adapter;
}
}
}
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
@Bean
@SuppressWarnings("deprecation")
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
// ...
}
}
创建IOC
容器时,会加载RequestMappingHandlerMapping
,而RequestMappingHandlerMapping
父类的父类AbstractHandlerMethodMapping
实现了InitializingBean
。
所以在Bean
生命周期的initializeBean
初始化阶段会调用InitializingBean
接口的afterPropertiesSet
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements MatchableHandlerMapping, EmbeddedValueResolverAware {
@Override
@SuppressWarnings("deprecation")
public void afterPropertiesSet() {
// 省略了加载配置的代码...
// 调用父类(没复写)的父类 AbstractHandlerMethodMapping 的 afterPropertiesSet
super.afterPropertiesSet();
}
@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
// 创建请求映射信息
RequestMappingInfo info = createRequestMappingInfo(method);
if (info != null) {
RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
if (typeInfo != null) {
info = typeInfo.combine(info);
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info);
}
}
return info;
}
@Nullable
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
// 查找方法上是否有 @RequestMapping 注解(@GetMapping 等相关注解包含了 @RequeMapping)
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class ? getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}
// 创建请求映射信息
protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, @Nullable RequestCondition<?> customCondition) {
RequestMappingInfo.Builder builder = RequestMappingInfo
.paths(resolveEmbeddedValuesInPatterns(requestMapping.path()))
.methods(requestMapping.method())
.params(requestMapping.params())
.headers(requestMapping.headers())
.consumes(requestMapping.consumes())
.produces(requestMapping.produces())
.mappingName(requestMapping.name());
if (customCondition != null) {
builder.customCondition(customCondition);
}
return builder.options(this.config).build();
}
}
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
public void afterPropertiesSet() {
// 调用自身方法
initHandlerMethods();
}
protected void initHandlerMethods() {
// 获取所有的 Bean
for (String beanName : getCandidateBeanNames()) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
// 注册
processCandidateBean(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
// 获取的是 ApplicationContext 中所有的类型(Object.class)
protected String[] getCandidateBeanNames() {
return (this.detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(obtainApplicationContext(), Object.class) : obtainApplicationContext().getBeanNamesForType(Object.class));
}
protected void processCandidateBean(String beanName) {
Class<?> beanType = null;
beanType = obtainApplicationContext().getType(beanName);
// isHandler 判断类上是不是 @Controller 或者 @RequestMapping 标注
if (beanType != null && isHandler(beanType)) {
// 探测 HandlerMethod
detectHandlerMethods(beanName);
}
}
protected void detectHandlerMethods(Object handler) {
Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());
if (handlerType != null) {
// 如果是代理类则获取原始类
Class<?> userType = ClassUtils.getUserClass(handlerType);
// 查找出所有类中包含的所有 method 并过滤出 @RequestMapping 标注的方法
Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> {
// 调用子类 RequestMappingHandlerMapping 实现的方法
return getMappingForMethod(method, userType);
});
// 遍历找到符合的每个类
methods.forEach((method, mapping) -> {
Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
// 注册到 mappingRegistry 中
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
}
// handler 类名
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
// 将类名和方法名注册到 mappingRegistry
this.mappingRegistry.register(mapping, handler, method);
}
}
DispatcherServlet
在DispatcherServletAutoConfiguration
自动配置类配置中,所以是随着IOC
容器创建而生成的单例Bean
,但他的初始化工作是在首次请求过来时完成的。
public class DispatcherServlet extends FrameworkServlet {
// Handler 映射集合,initStrategies 后会填充数据
@Nullable
private List<HandlerMapping> handlerMappings;
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
// ...
initHandlerMappings(context);
// ...
}
private void initHandlerMappings(ApplicationContext context) {
// ...
// RequestMappingHandlerMapping、
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
}
// ...
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
// RequestMappingHandlerMapping
mappedHandler = getHandler(processedRequest);
// 获取 RequestMappingHandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 前置处理器,如果被拦截器拦截了就不再往下执行
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 真正调用方法
// 这步方法执行完成后已经响应给调用者
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 后置处理器
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 对于 REST 请求 这步操作主要是调用拦截器的 afterCompletion 操作
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
// 获取 HandlerMapping 并包装为 HandlerExecutionChain 执行链
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
// 调用 AbstractHandlerMapping 中的方法,实际类型是 RequestMappingHandlerMapping
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
// 获取 HandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
}
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware {
@Override
@Nullable
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 调用子类 AbstractHandlerMethodMapping 实现的方法
Object handler = getHandlerInternal(request);
// 添加过滤器到执行链
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
return executionChain;
}
}
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
@Override
@Nullable
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
String lookupPath = initLookupPath(request);
this.mappingRegistry.acquireReadLock();
try {
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
this.mappingRegistry.releaseReadLock();
}
}
}
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
@Override
public final boolean supports(Object handler) {
// handler 确实为 HandlerMethod 类型
// supportsInternal 为子类 RequestMappingHandlerAdapter 复写的方法,一直为 true
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 调用子类 RequestMappingHandlerAdapter 实现的方法
return handleInternal(request, response, (HandlerMethod) handler);
}
}
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
@Override
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
// 调用自身方法
mav = invokeHandlerMethod(request, response, handlerMethod);
return mav;
}
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
// 包装 HandlerMethod
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 调用包装类 ServletInvocableHandlerMethod 中的方法,准备反射调用
invocableMethod.invokeAndHandle(webRequest, mavContainer);
return getModelAndView(mavContainer, modelFactory, webRequest);
}
}
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 调用父类方法,准备参数及准备反射调用
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// ...
}
}
public class InvocableHandlerMethod extends HandlerMethod {
@Nullable
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 获取方法参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
// 调用自身方法
return doInvoke(args);
}
@Nullable
protected Object doInvoke(Object... args) throws Exception {
// 获取 BridgedMethod 方法,没有 BridgedMethod 就返回原方法
Method method = getBridgedMethod();
// 反射调用方法
return method.invoke(getBean(), args);
}
}
error 控制器
spring-boot-autoconfigure-2.6.0.jar
包下,默认引入SpringMVC
后会加载。
package org.springframework.boot.autoconfigure.web.servlet.error;
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
}
Views: 2,398 · Posted: 2021-12-29
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...