springmvc也是在spring framework中的,不是一个单独的项目
MVC就是和Tomcat有关。
01.MVC启动的第一步,启动Tomcat(这个和springboot的run方法启动Tomcat有关)
02.SpringMVC中,最为核心的就是DispatcherServlet,在启动Tomcat的过程中:
DispatcherServlet加载到Tomcat中,依然还是靠SpringBoot的自动配置DispatcherServletAutoConfiguration。
实际上该类的逻辑就是定义了四个类,分别是:
1.DispatcherServletRegistrationCondition:决定是否注册DispatcherServlet到Servlet容器,beanFactory中有,servlet中没有,则加载
2.DefaultDispatcherServletCondition:决定是否加载DispatcherServlet
3.DispatcherServletRegistrationConfiguration:负责注册DispatcherServlet到Servlet容器,并进行一些设置。
4.DispatcherServletConfiguration:负责加载DispatcherServlet并进行一些配置
@AutoConfigureOrder(-2147483648)
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
//存在DispatcherServlet.class文件才加载
@ConditionalOnClass({DispatcherServlet.class})
//在webServerFactory自动配置完成后才加载,防止工厂还没设置好
@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";
public DispatcherServletAutoConfiguration() {
}
//第一个类,决定是否注册DispatcherServlet到web容器
@Order(2147483637)
private static class DispatcherServletRegistrationCondition extends SpringBootCondition {
private DispatcherServletRegistrationCondition() {
}
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
ConditionOutcome outcome = this.checkDefaultDispatcherName(beanFactory);
return !outcome.isMatch() ? outcome : this.checkServletRegistration(beanFactory);
}
private ConditionOutcome checkDefaultDispatcherName(ConfigurableListableBeanFactory beanFactory) {
List<String> servlets = Arrays.asList(beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false));
boolean containsDispatcherBean = beanFactory.containsBean("dispatcherServlet");
return containsDispatcherBean && !servlets.contains("dispatcherServlet") ? ConditionOutcome.noMatch(this.startMessage().found("non dispatcher servlet").items(new Object[]{"dispatcherServlet"})) : ConditionOutcome.match();
}
private ConditionOutcome checkServletRegistration(ConfigurableListableBeanFactory beanFactory) {
Builder message = this.startMessage();
List<String> registrations = Arrays.asList(beanFactory.getBeanNamesForType(ServletRegistrationBean.class, false, false));
boolean containsDispatcherRegistrationBean = beanFactory.containsBean("dispatcherServletRegistration");
if (registrations.isEmpty()) {
return containsDispatcherRegistrationBean ? ConditionOutcome.noMatch(message.found("non servlet registration bean").items(new Object[]{"dispatcherServletRegistration"})) : ConditionOutcome.match(message.didNotFind("servlet registration bean").atAll());
} else if (registrations.contains("dispatcherServletRegistration")) {
return ConditionOutcome.noMatch(message.found("servlet registration bean").items(new Object[]{"dispatcherServletRegistration"}));
} else {
return containsDispatcherRegistrationBean ? ConditionOutcome.noMatch(message.found("non servlet registration bean").items(new Object[]{"dispatcherServletRegistration"})) : ConditionOutcome.match(message.found("servlet registration beans").items(Style.QUOTE, registrations).append("and none is named dispatcherServletRegistration"));
}
}
private Builder startMessage() {
return ConditionMessage.forCondition("DispatcherServlet Registration", new Object[0]);
}
}
//第二个类,决定是否创建DispatcherServlet对象
@Order(2147483637)
private static class DefaultDispatcherServletCondition extends SpringBootCondition {
private DefaultDispatcherServletCondition() {
}
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Builder message = ConditionMessage.forCondition("Default DispatcherServlet", new Object[0]);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
List<String> dispatchServletBeans = Arrays.asList(beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false));
if (dispatchServletBeans.contains("dispatcherServlet")) {
return ConditionOutcome.noMatch(message.found("dispatcher servlet bean").items(new Object[]{"dispatcherServlet"}));
} else if (beanFactory.containsBean("dispatcherServlet")) {
return ConditionOutcome.noMatch(message.found("non dispatcher servlet bean").items(new Object[]{"dispatcherServlet"}));
} else {
return dispatchServletBeans.isEmpty() ? ConditionOutcome.match(message.didNotFind("dispatcher servlet beans").atAll()) : ConditionOutcome.match(message.found("dispatcher servlet bean", "dispatcher servlet beans").items(Style.QUOTE, dispatchServletBeans).append("and none is named dispatcherServlet"));
}
}
}
@Configuration(
proxyBeanMethods = false
)
//负责将DispatcherServlet注册到servlet容器中,即tomcat中
//原理是创建一个DispatcherServletRegistrationBean对象
@Conditional({DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({WebMvcProperties.class})
@Import({DispatcherServletAutoConfiguration.DispatcherServletConfiguration.class})
protected static class DispatcherServletRegistrationConfiguration {
protected DispatcherServletRegistrationConfiguration() {
}
@Bean(
name = {"dispatcherServletRegistration"}
)
@ConditionalOnBean(
value = {DispatcherServlet.class},
name = {"dispatcherServlet"}
)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
//创建DispatcherServletRegistrationBean,
//包含一个DispatcherServlet和一个urlMapping
//即DispatcherServlet负责处理的请求路径
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath());
registration.setName("dispatcherServlet");
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}
}
@Configuration(
proxyBeanMethods = false
)
//负责加载DispatcherServlet
@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;
}
}
}



