@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({ HttpProperties.
class
, WebMvcProperties.
class
})
protected
static
class
DispatcherServletConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
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 = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public
MultipartResolver multipartResolver(MultipartResolver resolver) {
return
resolver;
}
}
@Configuration(proxyBeanMethods = false)
@Conditional(DispatcherServletRegistrationCondition.
class
)
@ConditionalOnClass(ServletRegistration.
class
)
@EnableConfigurationProperties(WebMvcProperties.
class
)
@Import(DispatcherServletConfiguration.
class
)
protected
static
class
DispatcherServletRegistrationConfiguration {
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.
class
, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public
DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration =
new
DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return
registration;
}
}
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private
static
class
DefaultDispatcherServletCondition
extends
SpringBootCondition {
@Override
public
ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage.forCondition(
"Default DispatcherServlet"
);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
List<String> dispatchServletBeans = Arrays
.asList(beanFactory.getBeanNamesForType(DispatcherServlet.
class
, false, false));
if
(dispatchServletBeans.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return
ConditionOutcome
.noMatch(message.found(
"dispatcher servlet bean"
).items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
if
(beanFactory.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return
ConditionOutcome.noMatch(
message.found(
"non dispatcher servlet bean"
).items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
if
(dispatchServletBeans.isEmpty()) {
return
ConditionOutcome.match(message.didNotFind(
"dispatcher servlet beans"
).atAll());
}
return
ConditionOutcome.match(message.found(
"dispatcher servlet bean"
,
"dispatcher servlet beans"
)
.items(Style.QUOTE, dispatchServletBeans)
.append(
"and none is named "
+ DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
}
@Order(Ordered.LOWEST_PRECEDENCE - 10)
private
static
class
DispatcherServletRegistrationCondition
extends
SpringBootCondition {
@Override
public
ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
ConditionOutcome outcome = checkDefaultDispatcherName(beanFactory);
if
(!outcome.isMatch()) {
return
outcome;
}
return
checkServletRegistration(beanFactory);
}
private
ConditionOutcome checkDefaultDispatcherName(ConfigurableListableBeanFactory beanFactory) {
List<String> servlets = Arrays
.asList(beanFactory.getBeanNamesForType(DispatcherServlet.
class
, false, false));
boolean containsDispatcherBean = beanFactory.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
if
(containsDispatcherBean && !servlets.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {
return
ConditionOutcome.noMatch(
startMessage().found(
"non dispatcher servlet"
).items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));
}
return
ConditionOutcome.match();
}
private
ConditionOutcome checkServletRegistration(ConfigurableListableBeanFactory beanFactory) {
ConditionMessage.Builder message = startMessage();
List<String> registrations = Arrays
.asList(beanFactory.getBeanNamesForType(ServletRegistrationBean.
class
, false, false));
boolean containsDispatcherRegistrationBean = beanFactory
.containsBean(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
if
(registrations.isEmpty()) {
if
(containsDispatcherRegistrationBean) {
return
ConditionOutcome.noMatch(message.found(
"non servlet registration bean"
)
.items(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
return
ConditionOutcome.match(message.didNotFind(
"servlet registration bean"
).atAll());
}
if
(registrations.contains(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)) {
return
ConditionOutcome.noMatch(message.found(
"servlet registration bean"
)
.items(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
if
(containsDispatcherRegistrationBean) {
return
ConditionOutcome.noMatch(message.found(
"non servlet registration bean"
)
.items(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
return
ConditionOutcome.match(message.found(
"servlet registration beans"
).items(Style.QUOTE, registrations)
.append(
"and none is named "
+ DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));
}
private
ConditionMessage.Builder startMessage() {
return
ConditionMessage.forCondition(
"DispatcherServlet Registration"
);
}
}
}