您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

SpringBoot对SpringMVC的自动配置,你知道多少?

时间:2023-03-23 12:29:56  来源:  作者:Springboot实战案例锦集


Spring MVC自动配置

Spring Boot为Spring MVC提供了自动配置,可以在大多数应用程序中很好地工作。

自动配置在Spring默认的基础上添加了以下特性:

  • 包含ContentNegotiatingViewResolver和BeanNameViewResolver bean。
  • 支持提供静态资源,包括对WebJars的支持。
  • 自动注册Converter、GenericConverter和Formatter
  • 对HttpMessageConverters的支持。
  • MessageCodesResolver的自动注册。
  • 静态index.html支持。
  • 自动使用ConfigurableWebBindingInitializer bean。

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

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

public interface WebMvcRegistrations {


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

EnableWebMvcConfiguration

public static class EnableWebMvcConfiguration {
  private final WebMvcRegistrations mvcRegistrations;
  public EnableWebMvcConfiguration(ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider) {
    this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
  }
  @Override
  protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
    // 如果自定义了WebMvcRegistrations,则使用自定义的,其他的默认配置行为不变
    if (this.mvcRegistrations != null) {
      RequestMappingHandlerAdapter adapter = this.mvcRegistrations.getRequestMappingHandlerAdapter();
      if (adapter != null) {
        return adapter;
      }
    }
    return super.createRequestMappingHandlerAdapter();
  }
}

如果你想要完全控制Spring MVC,你可以添加你自己的@Configuration注解@EnableWebMvc,或者自定义配置类该类继承DelegatingWebMvcConfiguration并使用@Configuration注解。

消息转换HttpMessageConverters

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

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

@Configuration(proxyBeanMethods = false)
public class CustomHttpMessageConvertersConfiguration {


  @Bean
  public HttpMessageConverters customConverters() {
    HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();
    HttpMessageConverter<?> another = new AnotherHttpMessageConverter();
    return new HttpMessageConverters(additional, another);
  }
}

系统默认也提供了HttpMessageConverters Bean,其实我们可以直接将自定义的HttpMessageConverter注册为Bean即可:

public class HttpMessageConvertersAutoConfiguration {
  @Bean
  @ConditionalOnMissingBean
  // 这里的参数就能够收集所有HttpMessageConverter类型的Bean
  public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
    return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
  }  
}

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

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

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

@JsonComponent
public class MyJsonComponent {


  public static class Serializer extends JsonSerializer<MyObject> {
    @Override
    public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
      jgen.writeStartObject();
      jgen.writeStringField("name", value.getName());
      jgen.writeNumberField("age", value.getAge());
      jgen.writeEndObject();
    }
  }


  public static class Deserializer extends JsonDeserializer<MyObject> {


    @Override
    public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
      ObjectCodec codec = jsonParser.getCodec();
      JsonNode tree = codec.readTree(jsonParser);
      String name = tree.get("name").textValue();
      int age = tree.get("age").intValue();
      return new MyObject(name, age);
    }
  }
}

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

MessageCodesResolver

Spring MVC有一个生成错误代码的策略,用于从绑定错误中呈现错误消息:MessageCodesResolver。如果你设置
spring.mvc.message-codes-resolver-format属性PREFIX_ERROR_CODE或POSTFIX_ERROR_CODE,则spring Boot会为你创建一个属性。

静态内容

默认情况下,Spring Boot从类路径中名为/static(或/public或/resources或/META-INF/resources)的目录或ServletContext的根目录提供静态内容。它使用Spring MVC中的
ResourceHttpRequestHandler,因此您可以通过添加自己的WebMvcConfigurer并重写addResourceHandlers方法来修改该行为。

在独立的web应用程序中,不会启用容器中的默认servlet。可以使用
server.servlet.register-default-servlet属性启用它。

默认的servlet充当后备,如果Spring决定不处理ServletContext的根,则从ServletContext提供内容。大多数情况下,这不会发生(除非您修改默认的MVC配置),因为Spring总是可以通过DispatcherServlet处理请求。

默认情况下,资源映射在/**上,但您可以使用
spring.mvc.static-path-pattern属性对其进行调优。例如,将所有资源重新定位到/resources/**可以通过以下方式实现:

spring:
  mvc:
    static-path-pattern: "/resources/**"

你还可以使用spring.web.resources自定义静态资源位置。static-locations属性(用目录位置列表替换默认值)。根servlet上下文路径“/”也会自动添加为位置。

除了前面提到的“标准”静态资源位置之外,还有一个针对Webjars内容的特殊情况。任何路径在/webjars/**中的资源,如果它们被打包成webjars格式,就会从jar文件中提供。

Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用缓存破坏静态资源或为Webjars使用版本不可知的URL等用例。

要为Webjars使用与版本无关的URL,请添加Webjars定位器核心依赖项。然后声明您的Webjar。以jQuery为例,添加“
/webjars/jQuery/jQuery.min.js”会导致“/Webjar/jQuery/x.y.z/jQuery.min.js”,其中x.y.z是Webjar版本。

要使用缓存破坏,以下配置为所有静态资源配置缓存破坏解决方案,从而有效地在URL中添加内容哈希,如<link href=“
/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css”/>:​

spring:
  web:
    resources:
      chAIn:
        strategy:
          content:
            enabled: true
            paths: "/**"

路径匹配与内容协商

Spring MVC可以通过查看请求路径并将其与应用程序中定义的映射(例如,Controller方法上的@GetMapping注释)进行匹配,将传入的HTTP请求映射到处理程序。

Spring Boot默认选择禁用后缀模式匹配,这意味着像"GET/projects/Spring Boot.json"这样的请求将不会与@GetMapping("/projects/Spring Boot")映射匹配。这被认为是Spring MVC应用程序的最佳实践。这个功能在过去主要适用于没有发送正确的“Accept”请求头的HTTP客户端;我们需要确保向客户端发送正确的内容类型。如今,内容协商更加可靠。

还有其他方法可以处理那些不一致地发送正确的"Accept"请求头的HTTP客户端。我们可以使用查询参数来确保像"GET/projects/spring-boot?format=json"这样的请求将被映射到@GetMapping("/projects/spring-boot"),而不是使用后缀匹配:

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true

或者自定义参数名称:

spring:
  mvc:
    contentnegotiation:
      favor-parameter: true
      parameter-name: "myparam"

大多数标准media type都支持开箱即用,但你也可以定义新的:

spring:
  mvc:
    contentnegotiation:
      media-types:
        markdown: "text/markdown"

后缀模式匹配已弃用,并将在将来的版本中删除。如果你理解注意事项,并且仍然希望你的应用程序使用后缀模式匹配,则需要以下配置:

spring:
  mvc:
    contentnegotiation:
      favor-path-extension: true
    pathmatch:
      use-suffix-pattern: true
 

ConfigurableWebBindingInitializer

Spring MVC使用WebBindingInitializer为特定请求初始化WebDataBinder。如果你创建自己的ConfigurationWebBindingInitializer@Bean,则Spring Boot会自动配置Spring MVC以使用它。

错误处理

默认情况下,Spring Boot提供了一个/error映射,以合理的方式处理所有错误,并且它在servlet容器中注册为“全局”错误页面。对于机器客户端,它会生成一个JSON响应,其中包含错误、HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“白标签”错误视图,它以HTML格式呈现相同的数据(要自定义它,请添加一个解决错误的视图)。

服务器有很多。如果要自定义默认错误处理行为,可以设置的错误属性。

要完全替换默认行为,可以实现ErrorController并注册该类型的bean定义,或者添加ErrorAttributes类型的bean以使用现有机制,但替换内容。

你也可以定义一个带有@ControllerAdvice注解的类来定制JSON文档,以返回特定的控制器和/或异常类型,如下例所示:

@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice extends ResponseEntityExceptionHandler {


  @ResponseBody
  @ExceptionHandler(MyException.class)
  public ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
    HttpStatus status = getStatus(request);
    return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()), status);
  }


  private HttpStatus getStatus(HttpServletRequest request) {
    Integer code = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
    HttpStatus status = HttpStatus.resolve(code);
    return (status != null) ? status : HttpStatus.INTERNAL_SERVER_ERROR;
  }


}

完毕!!!



Tags:SpringBoot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  Search: SpringBoot  点击:(17)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19  Search: SpringBoot  点击:(86)  评论:(0)  加入收藏
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: SpringBoot  点击:(91)  评论:(0)  加入收藏
公司用了六年的 SpringBoot 项目部署方案,稳得一批!
本篇和大家分享的是springboot打包并结合shell脚本命令部署,重点在分享一个shell程序启动工具,希望能便利工作。 profiles指定不同环境的配置 maven-assembly-plugin打发布压...【详细内容】
2024-01-10  Search: SpringBoot  点击:(163)  评论:(0)  加入收藏
简易版的SpringBoot是如何实现的!!!
SpringBoot作为目前最流行的框架之一,同时是每个程序员必须掌握的知识,其提供了丰富的功能模块和开箱即用的特性,极大地提高了开发效率和降低了学习成本,使得开发人员能够更专注...【详细内容】
2023-12-29  Search: SpringBoot  点击:(135)  评论:(0)  加入收藏
用 SpringBoot+Redis 解决海量重复提交问题
前言 一:搭建redis的服务Api 二:自定义注解AutoIdempotent 三:token创建和检验 四:拦截器的配置 五:测试用例 六:总结前言:在实际的开发项目中,一个对外暴露的接口往往会面临很多...【详细内容】
2023-12-20  Search: SpringBoot  点击:(53)  评论:(0)  加入收藏
SpringBoot中如何优雅地个性化定制Jackson
当使用 JSON 格式时,Spring Boot 将使用ObjectMapper实例来序列化响应和反序列化请求。在本教程中,我们将了解配置序列化和反序列化选项的最常用方法。一、默认配置默认情况下...【详细内容】
2023-12-20  Search: SpringBoot  点击:(132)  评论:(0)  加入收藏
springboot-如何集成Validation进行参数校验
一、步骤概览 二、步骤说明1.引入依赖包在 pom.xml 文件中引入 validation 组件,它提供了在 Spring Boot 应用程序中进行参数校验的支持。<!-- WEB 程序依赖包 --><dependen...【详细内容】
2023-12-13  Search: SpringBoot  点击:(157)  评论:(0)  加入收藏
优雅的springboot参数校验,你学会了吗?
前言在后端的接口开发过程,实际上每一个接口都或多或少有不同规则的参数校验,有一些是基础校验,如非空校验、长度校验、大小校验、格式校验;也有一些校验是业务校验,如学号不能重...【详细内容】
2023-11-29  Search: SpringBoot  点击:(200)  评论:(0)  加入收藏
Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?
前言通过这篇文章来大家分享一下,另外一个Springboot的扩展点BeanDefinitionRegistryPostProcessor,一般称这类扩展点为容器级后置处理器,另外一类是Bean级的后置处理器;容器级...【详细内容】
2023-11-27  Search: SpringBoot  点击:(175)  评论:(0)  加入收藏
▌简易百科推荐
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(8)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(12)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(54)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(39)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(50)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(68)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(86)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(86)  评论:(0)  加入收藏
花 15 分钟把 Express.js 搞明白,全栈没有那么难
Express 是老牌的 Node.js 框架,以简单和轻量著称,几行代码就可以启动一个 HTTP 服务器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都与 Express 息息相关。Express 框...【详细内容】
2024-01-16  程序员成功  微信公众号  Tags:Express.js   点击:(88)  评论:(0)  加入收藏
站内最新
站内热门
站内头条