一. WebMvcAutoConfiguration
@Configuration
//当前环境必须是WebMvc(Servlet)环境
@ConditionalOnWebApplication(type = Type.SERVLET)
//当前运行环境的classpath中必须有Servlet类,DispatcherServlet类,WebMvcConfigurer类
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
//如果没有自定义WebMvc的配置类,则使用本自动配置
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration
webMvcAutoConfiguration必须在DispatcherServerletAutoConfiguration,TaskExecutionAutoConfiguration,ValidationAutoConfiguration执行完后再执行
二.DispatcherServletAutoConfiguration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration
DispatcherServerlet自动配置。他起作用应该依赖于一个已经存在嵌入式WeB服务器的独立应用程序,使用SpringBootServletInitializer
的可部署应用程序
三.ServletWebServerFactoryAutoConfiguration
@Configuration
//在自动配置中具有最高优先级执行
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration
3.1 EmbeddedTomcat
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
条件装配注解@conditionalOnClass可以看到,classpath下必须有Tomcat这个类,改配置才会生效
对比jetty:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.webapp.WebAppContext;
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty
3.2 ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
// ......
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (this.beanFactory == null) {
return;
}
// 编程式注入组件
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class);
}
private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
它实现了ImprotBeanDefinitionRegistrar接口,在registerBeanDefinitions中可以编程式的向IOC
容器注入组件,他注册的组件是WebServerFactoryCustomizerBeanPostProcessor
、ErrorPageRegistrarBeanPostProcessor
3.3 WebServerFactoryCustomizerBeanPostProcessor
Bean的后置处理器,他将Bean工厂中的所有WebServerFactoryCustomizer类型的Bean应用于WebServerFactory类型的Bean
-----执行组件定制器
y类型
3.4ErrorPageRegistrarBeanPostProcessor
所有设置的错误页跳转规则注册到错误处理器
public interface ErrorPageRegistry {
/**
* 添加错误页面
*/
void addErrorPages(ErrorPage... errorPages);
}
3.5SpringBoot的Customizer
修改SpringBoot配置,都是通过application.yml显式的声明配置,使用customizer定制器机制
- 在WbeMvc模型中,使用customizer修改配置,可以实现WebServerFactoryCustomizer接口
- 该接口可以传入泛型,泛型的类型是ServletWebServerFactory
@Order(0)
@Component
class WebMvcCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>, Ordered {
@Override
public void customize(TomcatServletWebServerFactory factory) {
factory.setPort(9090);
factory.setContextPath("/demo");
}
@Override
public int getOrder() {
return 0;
}
}
Customizer可以设置配置顺序(上面的@Order注解或者Ordered接口)。通过配置执行顺序们可以自定义覆盖某些自动配置,达到个性化配置
3.6ServerProperties来源
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
/**
* Server HTTP port.
*/
private Integer port;
/**
* Network address to which the server should bind.
*/
private InetAddress address;
@configurationProperties作用:可用于某个类上,设置属性profix用于指定工程的全局配置文件
(appication.properties或application.yml)中配置的根信息
@configurationProperties可以实现指定属性开头的属性值注入
四.SpringBoot注册传统Servlet三大组件
4.1组件扫描@ServletComponentScan
- 在启动类上标注@servletComponentScan注解,指定
value/basePackage,
指定即可指定包以及子包下所有的Servlet组件 - 注册Servlet,Filter,Listener组件可以直接在Servlet上标注@WebServlet等注解
4.2 借助RegistrationBean
- 自定义Servlet可以创建ServletRegistrationBean<T extends Servelt>
- 在配置类中注册ServletRegistrationBean,创建对下传入参数Servlet和urlMapping
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("demo servlet");
}
}
public class DemoServletRegistryBean extends ServletRegistrationBean<DemoServlet> {
public DemoServletRegistryBean(DemoServlet servlet, String... urlMappings) {
super(servlet, urlMappings);
}
}
@Configuration
public class ServletConfiguration {
@Bean
public DemoServletRegistryBean demoServletRegistryBean() {
return new DemoServletRegistryBean(new DemoServlet(), "/demo/servlet");
}
}
五.WebMvcAutoConfiguration
5.1 WebMvcConfiguration
@Configuration
// 导入配置类
@Import(EnableWebMvcConfiguration.class)
// 启用WebMvcProperties、ResourceProperties
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware
5.2EnableWebMvcConfiguration
注册核心组件
SpringWebMvc最核心的两个组件:处理器适配器,处理器映射器
// 处理器适配器
@Bean
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
adapter.setIgnoreDefaultModelOnRedirect(
this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
return adapter;
}
// 处理器映射器
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
// Must be @Primary for MvcUriComponentsBuilder to work
return super.requestMappingHandlerMapping();
}
Hibernate-Validator 参数校验器
@Bean
@Override
public Validator mvcValidator() {
if (!ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
return super.mvcValidator();
}
return ValidatorAdapter.get(getApplicationContext(), getValidator());
}
注册了全局异常处理器
@Override
// 全局异常处理器
protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {
if (this.mvcRegistrations != null && this.mvcRegistrations.getExceptionHandlerExceptionResolver() != null) {
return this.mvcRegistrations.getExceptionHandlerExceptionResolver();
}
return super.createExceptionHandlerExceptionResolver();
}
@Override
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
super.configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
addDefaultHandlerExceptionResolvers(exceptionResolvers);
}
if (this.mvcProperties.isLogResolvedException()) {
for (HandlerExceptionResolver resolver : exceptionResolvers) {
if (resolver instanceof AbstractHandlerExceptionResolver) {
((AbstractHandlerExceptionResolver) resolver).setWarnLogCategory(resolver.getClass().getName());
}
}
}
}
总结
- 自动配置类执行顺序,WebMvcAutoconfiguration执行顺序在ServletWebServerFactoryAutoConfiguration,dispatchServletAutoConfiguration之后
- SpringBoot会根据当前classpath下的类来决定装配哪些组件,启动哪种类型的Web容器
- WebMvc的配置包括消息转换器、视图解析器、处理器映射器、处理器适配器、静态资源映射配置、主页设置、应用图标设置等。
- 配置 SpringBoot 应用除了可以使用 properties、yml 之外,还可以使用 Customizer 来编程式配置。