ContentNegotiation内容协商机制(二)---Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】(下)

简介: ContentNegotiation内容协商机制(二)---Spring MVC内容协商实现原理及自定义配置【享学Spring MVC】(下)

这里解释了 该文 的顺序(后缀 > 请求参数 > HTTP首部Accept)现象。Spring MVC是通过它来创建ContentNegotiationManager进而管理协商策略的。


内容协商的配置:ContentNegotiationConfigurer


虽然说默认情况下Spring开启的协商支持能覆盖我们绝大部分应用场景了,但不乏有的时候我们也还是需要对它进行个性化的,那么这部分就讲解下对它的个性化配置~


ContentNegotiationConfigurer

它用于"收集"配置项,根据你提供的配置项来创建出一个ContentNegotiationManager。


public class ContentNegotiationConfigurer {
  private final ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean();
  private final Map<String, MediaType> mediaTypes = new HashMap<String, MediaType>();
  public ContentNegotiationConfigurer(@Nullable ServletContext servletContext) {
    if (servletContext != null) {
      this.factory.setServletContext(servletContext);
    }
  }
  // @since 5.0
  public void strategies(@Nullable List<ContentNegotiationStrategy> strategies) {
    this.factory.setStrategies(strategies);
  }
  ...
  public ContentNegotiationConfigurer defaultContentTypeStrategy(ContentNegotiationStrategy defaultStrategy) {
    this.factory.setDefaultContentTypeStrategy(defaultStrategy);
    return this;
  }
  // 手动创建出一个ContentNegotiationManager 此方法是protected 
  // 唯一调用处是:WebMvcConfigurationSupport
  protected ContentNegotiationManager buildContentNegotiationManager() {
    this.factory.addMediaTypes(this.mediaTypes);
    return this.factory.build();
  }
}


ContentNegotiationConfigurer可以认为是提供一个设置ContentNegotiationManagerFactoryBean的入口(自己内容new了一个它的实例),最终交给WebMvcConfigurationSupport向容器内注册这个Bean:


public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
  ...
  // 请注意是BeanName为:mvcContentNegotiationManager
  // 若实在有需要,你是可以覆盖的~~~~
  @Bean
  public ContentNegotiationManager mvcContentNegotiationManager() {
    if (this.contentNegotiationManager == null) {
      ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
      configurer.mediaTypes(getDefaultMediaTypes()); // 服务端默认支持的后缀名-->MediaType们~~~
      // 这个方法就是回调我们自定义配置的protected方法~~~~
      configureContentNegotiation(configurer);
      // 调用方法生成一个管理器
      this.contentNegotiationManager = configurer.buildContentNegotiationManager();
    }
    return this.contentNegotiationManager;
  }
  // 默认支持的协商MediaType们~~~~
  protected Map<String, MediaType> getDefaultMediaTypes() {
    Map<String, MediaType> map = new HashMap<>(4);
    // 几乎不用
    if (romePresent) {
      map.put("atom", MediaType.APPLICATION_ATOM_XML);
      map.put("rss", MediaType.APPLICATION_RSS_XML);
    }
    // 若导了jackson对xml支持的包,它就会被支持
    if (jaxb2Present || jackson2XmlPresent) {
      map.put("xml", MediaType.APPLICATION_XML);
    }
    // jackson.databind就支持json了,所以此处一般都是满足的
    // 额外还支持到了gson和jsonb。希望不久将来内置支持fastjson
    if (jackson2Present || gsonPresent || jsonbPresent) {
      map.put("json", MediaType.APPLICATION_JSON);
    }
    if (jackson2SmilePresent) {
      map.put("smile", MediaType.valueOf("application/x-jackson-smile"));
    }
    if (jackson2CborPresent) {
      map.put("cbor", MediaType.valueOf("application/cbor"));
    }
    return map;
  }
  ...
}


Tips:WebMvcConfigurationSupport@EnableWebMvc导进去的。


配置实践


有了上面理论的支撑,那么使用Spring MVC协商的最佳实践配置可参考如下(大多数情况下都无需配置):

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorParameter(true)
        //.parameterName("mediaType")
        //.defaultContentTypeStrategy(new ...) // 自定义一个默认的内容协商策略
        //.ignoreAcceptHeader(true) // 禁用Accept协商方式
        //.defaultContentType(MediaType.APPLICATION_JSON) // 它的效果是new FixedContentNegotiationStrategy(contentTypes)  增加了对固定策略的支
        //.strategies(list);
        //.useRegisteredExtensionsOnly() //PathExtensionContentNegotiationStrategy.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);
        ;
    }
}


总结


本文从原理上分析了Spring MVC对内容协商策略的管理、使用以及开放的配置,旨在做到心中有数,从而更好、更安全、更方便的进行扩展,对下文内容协商视图的理解有非常大的帮助作用,有兴趣的可持续关注~


相关文章
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
14915 60
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1555 13
|
7月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
583 4
|
8月前
|
监控 安全 Java
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
Spring Boot 通过 Actuator 模块提供了强大的健康检查功能,帮助开发者快速了解应用程序的运行状态。默认健康检查可检测数据库连接、依赖服务、资源可用性等,但在实际应用中,业务需求和依赖关系各不相同,因此需要实现自定义健康检查来更精确地监控关键组件。本文介绍了如何使用 @HealthEndpoint 注解及实现 HealthIndicator 接口来扩展 Spring Boot 的健康检查功能,从而提升系统的可观测性与稳定性。
598 0
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
1049 1
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——拦截自定义异常
本文介绍了在实际项目中如何拦截自定义异常。首先,通过定义异常信息枚举类 `BusinessMsgEnum`,统一管理业务异常的代码和消息。接着,创建自定义业务异常类 `BusinessErrorException`,并在其构造方法中传入枚举类以实现异常信息的封装。最后,利用 `GlobalExceptionHandler` 拦截并处理自定义异常,返回标准的 JSON 响应格式。文章还提供了示例代码和测试方法,展示了全局异常处理在 Spring Boot 项目中的应用价值。
610 0
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
2425 15
|
设计模式 Java Spring
Spring Boot监听器的底层实现原理
Spring Boot监听器的底层实现原理主要基于观察者模式(也称为发布-订阅模式),这是设计模式中用于实现对象之间一对多依赖的一种常见方式。在Spring Boot中,监听器的实现依赖于Spring框架提供的事件监听机制。
623 1
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
989 3