SpringBoot对Spring MVC都做了哪些事?(一)

开发 架构
Spring Boot为Spring MVC提供了自动配置,可以很好地与大多数应用程序配合使用。

环境:Springboot2.4.12

Spring MVC自动配置

Spring Boot为Spring MVC提供了自动配置,可以很好地与大多数应用程序配合使用。

自动配置在Spring默认设置的基础上添加了以下功能:

  • 包含ContentNegotiatingViewResolverBeanNameViewResolver bean
  • 支持提供静态资源,包括对WebJars的支持(本文档后面会讲到)。
  • ConverterGenericConverterFormatterbean的自动注册。
  • HttpMessageConverters的支持(本文档后面会讲到)。
  • 自动注册MessageCodesResolver(本文档后面将介绍)。
  • 静态index.html的支持。
  • 自动使用ConfigurableWebBindingInitializerbean(本文档后面将介绍)。

如果你想保留那些Spring Boot MVC自定义,并做更多的MVC自定义(拦截器、格式化器、视图控制器和其他特性),你可以添加你自己的WebMvcConfigurer类型的@Configuration类,但不需要@EnableWebMvc。

如果你想提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,并且仍然保持Spring Boot MVC自定义,你可以声明一个WebMvcRegistrations类型的bean,并使用它来提供这些组件的自定义实例。

上面这段什么意思?就是我们可以自定义一个Class实现WebMvcRegistrations接口实现自定义的上面的RequestMappingHandlerMapping等相关的类。

WebMvcRegistrations接口

public interface WebMvcRegistrations {
default RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return null;
}
default RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
return null;
}
default ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() {
return null;
}
}

自动配置中又是如何使用(知道)我们自定义的这个WebMvcRegistrations 类呢?

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
// 注入自定义的WebMvcRegistrations
private final WebMvcRegistrations mvcRegistrations;
public EnableWebMvcConfiguration(ObjectProvider<WebMvcRegistrations> mvcRegistrations) {
// ...
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
}
}

这里RequestMappingHandlerMapping 为例说明自动配置是如何使用自定义的。接着上面的类中,有如下方法定义。

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
@Bean
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(...) {
// 调用父类的方法,这里就不进入父类方法了,父类方法中会调用createRequestMappingHandlerAdapter
// 方法,而此方法正好被当前类重写了
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager, conversionService, validator);
// ...
return adapter;
}
@Override
protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
// 判断是否存在自定义的WebMvcRegistrations接口
if (this.mvcRegistrations != null) {
RequestMappingHandlerAdapter adapter = this.mvcRegistrations.getRequestMappingHandlerAdapter();
if (adapter != null) {
return adapter;
}
}
return super.createRequestMappingHandlerAdapter();
}
}

以上就是自动配置实现自定义RequestMappingHandlerMapping 等相关WebMVC核心组件的方式。

如何完全的自己控制WebMVC的配置呢?

你可以添加自己的@Configuration注释@EnableWebMvc,或者自定义配置类 @Configuration注释且此类是DelegatingWebMvcConfiguration的子类。

如果你想定制Spring MVC使用的ConversionService,你可以提供一个带有addFormatters方法的WebMvcConfigurer bean。通过这个方法,你可以注册任何你喜欢的转换器,或者你可以委托给ApplicationConversionService上可用的静态方法。

HttpMessageConverters

Spring MVC使用HttpMessageConverter接口来转换HTTP请求和响应。合理的默认值是开箱即用的。例如,可以将对象自动转换为JSON(通过使用Jackson库)或XML(通过使用Jackson XML扩展(如果可用),或通过使用JAXB(如果Jackson XML扩展不可用)。缺省情况下,字符串是用UTF-8编码的。

如果你需要添加或自定义转换器,你可以使用Spring Boot的HttpMessageConverters类,如下所示:

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}

自动配置又是如何使用咱们自定义的配置?

  • HandlerAdapter设置HttpMessageConverter
public class WebMvcConfigurationSupport {
@Nullable
private List<HttpMessageConverter<?>> messageConverters;
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
// HandlerAdapter设置消息转换器
adapter.setMessageConverters(getMessageConverters());
}
protected final List<HttpMessageConverter<?>> getMessageConverters() {
// 默认为null
if (this.messageConverters == null) {
this.messageConverters = new ArrayList<>();
// 该方法在子类中重写了,调用子类DelegatingWebMvcConfiguration#configureMessageConverters方法
configureMessageConverters(this.messageConverters);
if (this.messageConverters.isEmpty()) {
// 添加系统默认的消息转换器
addDefaultHttpMessageConverters(this.messageConverters);
}
extendMessageConverters(this.messageConverters);
}
return this.messageConverters;
}
}
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 获取容器中所有的自定义的WebMvcConfigurer
// 这里会有一个系统提供的配置类WebMvcAutoConfigurationAdapter
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 分别调用(内部for)WebMvcConfigurer#configureMessageConverters方法
this.configurers.configureMessageConverters(converters);
}
}

系统提供的WebMvcConfigurer 实现类WebMvcAutoConfigurationAdapter。

public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
public WebMvcAutoConfigurationAdapter(ObjectProvider<HttpMessageConverters> messageConvertersProvider) {
// ...
this.messageConvertersProvider = messageConvertersProvider;
// ...
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 在上面的WebMvcConfigurerComposite#configureMessageConverters方法中会执行该方法。
// 该方法先获取有效的HttpMessageConverters
// ifAvailable方法接受一个Consumer函数式接口,将HttpMessageConverters#getConverters中的获取到的
// HttpMessageConverter添加到当前的List集合中
this.messageConvertersProvider.ifAvailable((customConverters) -> converters.addAll(customConverters.getConverters()));
}
}

以上就将自定义的HttpMessageConverter 添加到了容器中。

自定义JSON序列号和反序列化

如果你使用Jackson来序列化和反序列化JSON数据,你可能需要编写自己的JsonSerializer和JsonDeserializer类。自定义序列化器通常通过模块注册到Jackson,但Spring Boot提供了一个替代的@JsonComponent注释,可以更容易地直接注册Spring bean。

你可以在JsonSerializer、JsonDeserializer或KeyDeserializer实现中直接使用@JsonComponent注释。你也可以在包含序列化器/反序列化器作为内部类的类上使用它,如下所示:

@JsonComponent
public class Example {
public static class Serializer extends JsonSerializer<SomeObject> {
// ...
}
public static class Deserializer extends JsonDeserializer<SomeObject> {
// ...
}

}

ApplicationContext中的所有@JsonComponent bean都会自动向Jackson注册。因为@JsonComponent是用@Component进行元注释的,所以通常的组件扫描规则也适用。

Spring Boot还提供了JsonObjectSerializer和JsonObjectDeserializer基类,它们在序列化对象时提供了标准Jackson版本的有用替代方案。

责任编辑:姜华 来源: 今日头条
相关推荐

2022-08-02 07:55:28

MVCJersey

2022-07-26 07:47:47

SpringMVC

2022-07-29 09:12:14

Springservlet容器

2021-01-06 08:24:38

人工智能消费领域AI

2020-12-08 09:30:25

CPU内存I

2021-07-16 09:58:02

物联网

2017-11-13 15:48:36

架构Spring Clou演进

2017-11-14 09:03:36

Spring Clou架构演进

2021-08-06 22:45:09

人工智能AI

2014-08-10 14:35:23

2017-06-08 09:36:42

京东服务器

2022-05-19 07:01:34

架构

2019-02-24 23:45:42

5G运营商网络

2021-01-03 10:37:50

前端开发技术

2023-06-07 08:13:46

PixiJSCanvas 库

2019-12-09 09:50:18

程序员技能开发者

2017-06-26 14:52:45

微软智能云合作

2014-11-12 00:01:29

京东

2019-05-14 09:18:18

程序员PythonJava

2014-03-26 14:23:36

Microsoft AWindows Azu微软
点赞
收藏

51CTO技术栈公众号