springboot请求响应流程
springboot相对于springMVC来说,只是增加了大量的自动配置,从而节省开发人员的配置,其核心部分都是使用的springMVC的。因此,两者处理流程没什么不同。
下面这张图是网上找的:
看到上图,DisPatchServelet是一个非常重要的组件。它负责接收前端请求,并进行分发,以及返回响应。
看一下它的继承关系:
Servlet是一个接口:
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
servlet是一个接口,是Java的一个Web组件,用于动态的生成内容,它运行在Servlet容器中,不可单独存在。而Tomcat就是一个著名的Servlet容器,也是一个Web服务器。
Servlet容器采用多线程单实例的模式,每当有一个新请求过来,会创建一个线程(线程池,可能是新创建的,也可能是已经初始化过的),执行Servlet的service方法。当然,这种模式要考虑线程安全性,而DispatchServlet内部机制保证了线程安全。
springboot的DisPatchServeLet并不需要再配置,而是通过SPI机制加载的。
当我们再应用入口使用注解:
@SpringBootApplication就会自动加载各种配置。
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
在springboot-autoconfigure的META-INF中有spring.factories中可看到:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
//配置DispatchServelet
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
//WebMVC 加载 RequestHandlerMapping Bean
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
上面可以看到org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
RequestMappingHandlerMapping就是注册了Controller 和RestController注解的handler和方法,进行路由注册。
该配置就是创建DispatchServelet bean,但是ConditionalBean ,即当不存在时创建
@Configuration(
proxyBeanMethods = false
)
@Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({HttpProperties.class, WebMvcProperties.class})
protected static class DispatcherServletConfiguration {
protected DispatcherServletConfiguration() {
}
@Bean(
name = {"dispatcherServlet"}
)
public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());
return dispatcherServlet;
}
@Bean
@ConditionalOnBean({MultipartResolver.class})
@ConditionalOnMissingBean(
name = {"multipartResolver"}
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
return resolver;
}
}
上面是创建了DisPatchServlet Bean。
springboot默认情况下,在应用器动时,不会进行DispatchServlet的初始化,而是在第一次请求到来时进行。当然,这个是可以配置的,可以配置成启动时进行初始化。
这是会调用DisPatchServlet的onRefresh方法,并调用初时化方法,这时候会初时化各种组件。
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
//初始化文件解析器
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
//初始化HandlerMapping
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
//初始化异常解析器
this.initHandlerExceptionResolvers(context);
// 初始化请求到视图名称翻译器
this.initRequestToViewNameTranslator(context);
// 初始化视图解析器
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
其中最最重要的,就是handlermapping的初始化,它初始化了路由和controller的映射。
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
try {
HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException var3) {
;
}
}
if (this.handlerMappings == null) {
this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No HandlerMappings declared for servlet '" + this.getServletName() + "': using default strategies from DispatcherServlet.properties");
}
}
}
上述方法主要是从IOC容器中获取HanderMapping Bean。那么Bean是从何而来呢?
在最上面说到了springboot的自动配置以及SPI机制。AutoConfiguration中有一个
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
该类实例化的Bean:
@Bean
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;
}
}
@Bean
@Primary
public RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider);
}
requestMappingHandlerMapping就是创建HandlerMapping,其会创建一个RequestMappingHandlerMapping,而该类继承了InitializingBean。
public void afterPropertiesSet() {
this.config = new BuilderConfiguration();
this.config.setUrlPathHelper(this.getUrlPathHelper());
this.config.setPathMatcher(this.getPathMatcher());
this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
this.config.setContentNegotiationManager(this.getContentNegotiationManager());
super.afterPropertiesSet();
}
父类的方法:
public void afterPropertiesSet() {
this.initHandlerMethods();
}
protected void initHandlerMethods() {
String[] var1 = this.getCandidateBeanNames();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
String beanName = var1[var3];
if (!beanName.startsWith("scopedTarget.")) {
this.processCandidateBean(beanName);
}
}
this.handlerMethodsInitialized(this.getHandlerMethods());
}
上述方法是循环处理侯选的bean name.具体处理方法:
protected void processCandidateBean(String beanName) {
Class beanType = null;
try {
beanType = this.obtainApplicationContext().getType(beanName);
} catch (Throwable var4) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Could not resolve type for bean '" + beanName + "'", var4);
}
}
if (beanType != null && this.isHandler(beanType)) {
this.detectHandlerMethods(beanName);
}
}
上面的isHandler就是判断是不是Controller何RequestMapping注解的,如果是就处理。
protected boolean isHandler(Class<?> beanType) {
return AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class);
}
具体处理就是根据Method对象生成RequestMappingInfo对象,如果类上有@RequestMapping注解,那么也生成RequestMappingInfo对象,将这两个RequestMappingInfo对象进行合并遍历Method、RequestMappingInfo对应的map集合并注册到对应的mappingLookup、urlLookup、registry集合中。具体注册过程是加了读写锁的。
public void register(T mapping, Object handler, Method method) {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && AbstractHandlerMethodMapping.KotlinDelegate.isSuspend(method)) {
throw new IllegalStateException("Unsupported suspending handler method detected: " + method);
} else {
this.readWriteLock.writeLock().lock();
try {
HandlerMethod handlerMethod = AbstractHandlerMethodMapping.this.createHandlerMethod(handler, method);
this.validateMethodMapping(handlerMethod, mapping);
this.mappingLookup.put(mapping, handlerMethod);
List<String> directUrls = this.getDirectUrls(mapping);
Iterator var6 = directUrls.iterator();
while(var6.hasNext()) {
String url = (String)var6.next();
this.urlLookup.add(url, mapping);
}
String name = null;
if (AbstractHandlerMethodMapping.this.getNamingStrategy() != null) {
name = AbstractHandlerMethodMapping.this.getNamingStrategy().getName(handlerMethod, mapping);
this.addMappingName(name, handlerMethod);
}
CorsConfiguration corsConfig = AbstractHandlerMethodMapping.this.initCorsConfiguration(handler, method, mapping);
if (corsConfig != null) {
this.corsLookup.put(handlerMethod, corsConfig);
}
this.registry.put(mapping, new AbstractHandlerMethodMapping.MappingRegistration(mapping, handlerMethod, directUrls, name));
} finally {
this.readWriteLock.writeLock().unlock();
}
}
}
上面就是DispatchServlet的一个创建过程了。
那么当一个请求过来时,具体是怎么处理的呢。
1、上面也提到了,Tomcat将请求进行处理封装,转发给Servlet容器。
2、调用DispatchServlet 的service方法。
3、DispatchServlet进行分发,找到对应的Controller方法进行处理。
参考资料:
【原创】005 | 搭上SpringBoot请求处理源码分析专车
微信分享/微信扫码阅读
