1 Descripción general de la configuración automática de SpringMVC
Spring Boot proporciona una configuración automática para Spring MVC que funciona bien con la mayoría de las aplicaciones (no necesitamos una configuración personalizada en la mayoría de los escenarios).
La configuración automática agrega las siguientes funciones además de las predeterminadas de Spring:
-
Inclusión de
ContentNegotiatingViewResolver
yBeanNameViewResolver
frijoles. -
- Resolución de vistas de negociación de contenido y resolución de vistas de BeanName
-
Soporte para servir recursos estáticos, incluido el soporte para WebJars (tratado más adelante en este documento )).
-
- Recursos estáticos (incluidos webjars)
-
Registro automático de
Converter
,GenericConverter
yFormatter
beans. -
- registro automático
Converter,GenericConverter,Formatter
- registro automático
-
Compatibilidad con
HttpMessageConverters
(cubierto más adelante en este documento ). -
- Soporte
HttpMessageConverters
(luego cooperamos con la negociación de contenido para comprender el principio)
- Soporte
-
Registro automático de
MessageCodesResolver
(cubierto más adelante en este documento ). -
- Registro automático
MessageCodesResolver
(por internacionalización)
- Registro automático
-
Soporte estático
index.html
. -
- Compatibilidad con la página estática index.html
-
Soporte personalizado
Favicon
(cubierto más adelante en este documento ). -
- personalizar
Favicon
- personalizar
-
Uso automático de un
ConfigurableWebBindingInitializer
bean (tratado más adelante en este documento ). -
- Uso automático
ConfigurableWebBindingInitializer
(DataBinder es responsable de vincular los datos de solicitud a JavaBeans)
- Uso automático
Si desea mantener esas personalizaciones de Spring Boot MVC y realizar más personalizaciones de MVC (interceptores, formateadores, controladores de vista y otras características), puede agregar su propia @Configuration
clase de tipo WebMvcConfigurer
pero sin @EnableWebMvc
.
No utilice la anotación @EnableWebMvc. usar @Configuration
+ WebMvcConfigurer
reglas personalizadas
Si desea proporcionar instancias personalizadas de RequestMappingHandlerMapping
, RequestMappingHandlerAdapter
o ExceptionHandlerExceptionResolver
, y aún mantener las personalizaciones de Spring Boot MVC, puede declarar un bean de tipo WebMvcRegistrations
y usarlo para proporcionar instancias personalizadas de esos componentes.
Declara WebMvcRegistrations
cambiar el componente subyacente predeterminado
Si desea tomar el control completo de Spring MVC, puede agregar su propio @Configuration
anotado con @EnableWebMvc
o, alternativamente, agregar su propio @Configuration
anotado DelegatingWebMvcConfiguration
como se describe en el Javadoc de @EnableWebMvc
.
utilizar @EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC
2 Análisis funcional simple
2.1 Acceso a recursos estáticos
2.1.1 Directorio de recursos estáticos
Siempre que los recursos estáticos estén en el classpath: llamado /static
(o /public
o /resources
o/META-INF/resources
-
Acceso: ruta raíz del proyecto actual / + nombre de recurso estático
-
Principio:
静态映射/**
.Cuando llega una solicitud, primero diríjase al controlador para ver si se puede procesar. Todas las solicitudes que no se pueden procesar se entregan al controlador de recursos estáticos. Si no se encuentra el recurso estático, responderá con una página 404.
-
Cambiar la ruta de recursos estáticos predeterminados
spring: web: resources: static-locations: classpath:/abc
2.1.2 Prefijo de acceso a recursos estáticos
(predeterminado sin prefijo)
spring:
mvc:
static-path-pattern: /res/**
Proyecto actual + static-path-pattern
+ nombre de recurso estático = buscar en la carpeta de recursos estáticos
2.1.3 webjar
automapa / webjars /**
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
Dirección de acceso: http://localhost:8080/webjars/jquery/3.6.0/dist/jquery.js La dirección detrás debe seguir la ruta del paquete en la dependencia
2.2 Soporte de la página de bienvenida
-
index.html en la ruta del recurso estático
-
Las rutas de recursos estáticos se pueden configurar
-
Sin embargo, el prefijo de acceso de los recursos estáticos no se puede configurar. De lo contrario, no se puede acceder a index.html de forma predeterminada
spring: # mvc: # static-path-pattern: /res/** 这个会导致welcome page功能失效 web: resources: static-locations: classpath:/abc
-
-
el controlador puede manejar /index
2.3 PersonalizaciónFavicon
favicon.ico se puede colocar en el directorio de recursos estáticos. (Si el ícono no sale, borre el caché del navegador o cierre el navegador y vuelva a abrirlo)
spring:
# mvc:
# static-path-pattern: /res/** 这个会导致 Favicon 功能失效
2.4 Principio de configuración de recursos estáticos
-
SpringBoot inicia la clase de carga predeterminada (
xxxAutoConfiguration
clase de configuración automática) -
La clase de configuración automática de la función SpringMVC
WebMvcAutoConfiguration
entra en vigor@Configuration( proxyBeanMethods = false ) @ConditionalOnWebApplication( type = Type.SERVLET ) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) @ConditionalOnMissingBean({ WebMvcConfigurationSupport.class}) @AutoConfigureOrder(-2147483638) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}) public class WebMvcAutoConfiguration { }
-
Lo que hay en el contenedor.
@Configuration( proxyBeanMethods = false ) @Import({ WebMvcAutoConfiguration.EnableWebMvcConfiguration.class}) @EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class}) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware { }
-
Las propiedades relevantes del archivo de configuración están vinculadas a xxx . WebMvcProperties== primavera.mvc , WebProperties== primavera.web
2.4.1 La clase de configuración tiene un solo constructor parametrizado
//有参构造器所有参数的值都会从容器中确定
//WebProperties webProperties;获取和spring.web绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========
//DispatcherServletPath
//ServletRegistrationBean 给应用注册Servlet、Filter....
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
this.resourceProperties = webProperties.getResources();
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations;
this.mvcProperties.checkConfiguration();
}
2.4.2 Reglas predeterminadas para el manejo de recursos
Esta es la regla de configuración predeterminada para acceder a los recursos estáticos. Después de introducir el recurso estático de jQuery, este prefijo se ha configurado de forma predeterminada y /webjars/**
también se agrega /META-INF/resources/webjars/
la ruta de acceso al recurso estático .
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{
resource});
}
});
}
}
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
this.addResourceHandler(registry, pattern, (registration) -> {
registration.addResourceLocations(locations);
});
}
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, Consumer<ResourceHandlerRegistration> customizer) {
if (!registry.hasMappingForPattern(pattern)) {
ResourceHandlerRegistration registration = registry.addResourceHandler(new String[]{
pattern});
customizer.accept(registration);
registration.setCachePeriod(this.getSeconds(this.resourceProperties.getCache().getPeriod()));
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
this.customizeResourceHandlerRegistration(registration);
}
}
spring:
# mvc:
# static-path-pattern: /res/**
resources:
static-locations: classpath:/abc
add-mappings: false #禁用所有静态资源规则
@ConfigurationProperties("spring.web")
public class WebProperties {
private Locale locale;
private WebProperties.LocaleResolver localeResolver;
private final WebProperties.Resources resources;
public WebProperties() {
this.localeResolver = WebProperties.LocaleResolver.ACCEPT_HEADER;
this.resources = new WebProperties.Resources();
}
public Locale getLocale() {
return this.locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public WebProperties.LocaleResolver getLocaleResolver() {
return this.localeResolver;
}
public void setLocaleResolver(WebProperties.LocaleResolver localeResolver) {
this.localeResolver = localeResolver;
}
public WebProperties.Resources getResources() {
return this.resources;
}
public static class Resources {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private boolean customized;
private final WebProperties.Resources.Chain chain;
private final WebProperties.Resources.Cache cache;
public Resources() {
this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
this.addMappings = true;
this.customized = false;
this.chain = new WebProperties.Resources.Chain();
this.cache = new WebProperties.Resources.Cache();
}
2.4.3 Reglas de procesamiento de la página de bienvenida
// HandlerMapping:处理器映射。保存了每一个Handler能处理哪些请求。
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
return welcomePageHandlerMapping;
}
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
if (welcomePage != null && "/**".equals(staticPathPattern)) {
//要用欢迎页功能,必须是/**
logger.info("Adding welcome page: " + welcomePage);
this.setRootViewName("forward:index.html");
} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
//调用Controller /index
logger.info("Adding welcome page template: index");
this.setRootViewName("index");
}
}
2.4.4 icono de favoritos
El navegador enviará una solicitud /favicon para obtener el ícono, y no se obtendrá durante toda la sesión