SpringBoot学习笔记(四)WebMvc_开发语言

 

 一. 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 来编程式配置。