• SpringBoot3框架,Web开发(上)


    web场景,默认配置:

    1. 包含了 ContentNegotiatingViewResolver 和 BeanNameViewResolver 组件,方便视图解析
    2. 默认的静态资源处理机制: 静态资源放在 static 文件夹下即可直接访问
    3. 自动注册Converter,GenericConverter,Formatter组件,适配常见数据类型转换格式化需求
    4. 支持 HttpMessageConverters,可以方便返回json等数据类型
    5. 注册 MessageCodesResolver,方便国际化及错误消息处理
    6. 支持 静态 index.html
    7. 自动使用ConfigurableWebBindingInitializer,实现消息处理、数据绑定、类型转化、数据校验等功能

    Web开发的方式

    • 如果想保持 boot mvc 的默认配置,并且自定义更多的 mvc 配置,如:interceptors, formatters, view controllers 等。可以使用@Configuration注解添加一个 WebMvcConfigurer 类型的配置类,并不要标注 @EnableWebMvc
    • 如果想保持 boot mvc 的默认配置,但要自定义核心组件实例,比如:RequestMappingHandlerMapping, RequestMappingHandlerAdapter, 或ExceptionHandlerExceptionResolver,给容器中放一个 WebMvcRegistrations 组件即可
    • 如果想全面接管 Spring MVC,@Configuration 标注一个配置类,并加上 @EnableWebMvc注解,实现 WebMvcConfigurer 接口

    web开发有三种方式:

    方式用法效果
    全自动直接编写控制器逻辑全部使用自动配置默认效果
    手自一体@Configuration + 配置WebMvcConfigurer+配置 WebMvcRegistrations不要标注

    @EnableWebMvc
    保留自动配置效果

    手动设置部分功能

    定义MVC底层组件
    全手动@Configuration + 配置WebMvcConfigurer标注

    @EnableWebMvc
    禁用自动配置效果

    全手动设置

    如果有定制化需求,给容器中写一个配置类,在配置类上加上@Configuration注解,并不要标注@EnableWebMvc,让这个配置类实现WebMvcConfigurer接口,就可以实现手自一体的效果

    WebMvcAutoConfiguration

    • WebMvcAutoConfiguration会给项目配置两个Filter:
      1. HiddenHttpMethodFilter :用于页面表单提交Rest请求(GET、POST、PUT、DELETE)
      2. FormContentFilter: 表单内容Filter,GET(数据放URL后面)、POST(数据放请求体)请求可以携带数据,PUT、DELETE 的数据会被忽略。配置了FormContentFilter 后PUT、DELETE的数据就不会被忽略
    • WebMvcAutoConfiguration给容器中放了WebMvcConfigurer组件,给SpringMVC添加各种定制功能(用手自一体方式开发时会派上用场)
      1. WebMvcConfigurer接口提供了SpringMVC底层的所有组件入口
      2. 所有的功能最终会和配置文件进行绑定
        1. WebMvcProperties:和 spring.mvc配置绑定
        2. WebProperties:和 spring.web 配置绑定

    静态资源

    静态资源规则

    • 规则一:访问: /webjars/**路径就去 classpath:/META-INF/resources/webjars/下找资源.
    • 规则二:访问: /**路径就去 静态资源默认的四个位置找资源
      • classpath:/META-INF/resources/
      • classpath:/resources/
      • classpath:/static/
      • classpath:/public/
    • 规则三:静态资源默认都有缓存规则的设置
      • 如果浏览器访问了一个静态资源,会将其缓存,如果服务器中这个资源没有发生变化,下次访问时,可以直接使用其浏览器中的该静态资源的缓存,而不用给服务器发请求。
      • 有几个关于缓存的配置(直接通过配置文件spring.web
        • cachePeriod:缓存周期,即多久不用找服务器再请求该静态资源。默认没有缓存周期,以秒为单位。
        • cacheControl:HTTP缓存,即会存储与请求相关联的响应,并将存储的响应复用于后续请求
        • useLastModified:是否使用最后一次修改的资源,配合HTTP缓存使用,默认为true。即以最后一次修改资源的时间和使用其缓存资源进行对比,来判断是否要再次请求。

    欢迎页规则

    欢迎页规则在 WebMvcAutoConfiguration 中进行了定义:

    1. 静态资源目录下找 index.html
    2. 没有就在 templates下找index模板页

    Favicon

    Favicon是代表浏览器标签页的图标的,浏览器会到服务器静态资源目录下找 favicon.ico,再以其资源作为标签页的图标

    自定义静态资源规则

    在配置文件中自定义静态资源规则:

    1. #1、spring.web:
    2. # 1.配置国际化的区域信息
    3. # 2.静态资源策略(开启、处理链、缓存)
    4. #开启静态资源映射规则
    5. spring.web.resources.add-mappings=true
    6. #设置缓存
    7. spring.web.resources.cache.period=3600
    8. ##缓存详细合并项控制,覆盖period配置:
    9. ## 浏览器第一次请求服务器,服务器告诉浏览器此资源缓存7200秒,7200秒以内的所有此资源访问不用发给服务器请求,7200秒以后发请求给服务器
    10. spring.web.resources.cache.cachecontrol.max-age=7200
    11. ## 共享缓存
    12. spring.web.resources.cache.cachecontrol.cache-public=true
    13. #使用资源 last-modified 时间,来对比服务器和浏览器的资源是否相同没有变化。相同返回 304
    14. spring.web.resources.cache.use-last-modified=true
    15. #自定义静态资源文件夹位置
    16. spring.web.resources.static-locations=classpath:/a/,classpath:/b/,classpath:/static/
    17. #2、 spring.mvc
    18. ## 2.1. 自定义webjars路径前缀
    19. spring.mvc.webjars-path-pattern=/wj/**
    20. ## 2.2. 静态资源访问路径前缀
    21. spring.mvc.static-path-pattern=/static/**

    在配置类中自定义静态资源规则:(第一种写法)

    1. @Configuration//这是一个配置类
    2. public class MyConfig implements WebMvcConfigurer {
    3. @Override
    4. public void addResourceHandlers(ResourceHandlerRegistry registry) {
    5. //保留以前规则
    6. //自己写新的规则。
    7. registry.addResourceHandler("/static/**")
    8. .addResourceLocations("classpath:/a/","classpath:/b/")
    9. .setCacheControl(CacheControl.maxAge(1180, TimeUnit.SECONDS));
    10. }
    11. }

    (第二种写法)

    1. @Configuration //这是一个配置类,给容器中放一个 WebMvcConfigurer 组件,就能自定义底层
    2. public class MyConfig /*implements WebMvcConfigurer*/ {
    3. @Bean
    4. public WebMvcConfigurer webMvcConfigurer(){
    5. return new WebMvcConfigurer() {
    6. @Override
    7. public void addResourceHandlers(ResourceHandlerRegistry registry) {
    8. registry.addResourceHandler("/static/**")
    9. .addResourceLocations("classpath:/a/", "classpath:/b/")
    10. .setCacheControl(CacheControl.maxAge(1180, TimeUnit.SECONDS));
    11. }
    12. };
    13. }
    14. }

    容器中只要有一个 WebMvcConfigurer 组件。配置的底层行为都会生效

    1. WebMvcAutoConfiguration 是一个自动配置类,它里面有一个 EnableWebMvcConfiguration
    2. EnableWebMvcConfiguration继承于 DelegatingWebMvcConfiguration,这两个都生效
    3. DelegatingWebMvcConfiguration利用 DI 把容器中 所有 WebMvcConfigurer 注入进来
    4. 当调用 DelegatingWebMvcConfiguration的方法配置底层规则,而DelegatingWebMvcConfiguration调用所有 WebMvcConfigurer的配置底层方法。

    路径匹配

    Ant风格路径用法(AntPathMatcher)

    Ant 风格的路径模式语法具有以下规则:

    • *:表示任意数量的字符。
    • ?:表示任意一个字符
    • **:表示任意数量的目录。
    • {}:表示一个命名的模式占位符
    • []:表示字符集合,例如[a-z]表示小写字母,[a-z]+表示任意个小写字符
    • 要为{}中的路径变量指定字符集合,可以使用{路径变量:[字符集合]}

    PathPatternParser

    PathPatternParser比起Ant,效率更高,兼容 AntPathMatcher语法,并支持更多类型的路径模式,即使用PathPatternParser路径匹配时还能继续使用Ant的语法规则,但是有一点有改变:

    • PathPatternParser用**表示任意层目录时只能将**放在最末尾
    • 如果要将**放在路径中间而不是末尾,需要将路径匹配改回Ant,改回Ant配置方式如下:
    1. # 改变路径匹配策略:
    2. # ant_path_matcher 老版策略;
    3. # path_pattern_parser 新版策略;
    4. spring.mvc.pathmatch.matching-strategy=ant_path_matcher
    • SpringBoot3默认是PathPatternParser的匹配规则

    内容协商

    内容协商能让一套系统适配多端数据返回

    多端内容适配

    • SpringBoot 多端内容适配
      • 基于请求头内容协商:(默认开启)
        • 客户端向服务端发送请求,携带HTTP标准的Accept请求头
          • Accept: application/jsontext/xmltext/yaml
          • 服务端根据客户端请求头期望的数据类型进行动态返回
      • 基于请求参数内容协商:(需要开启)
        • 发送请求 GET /projects/spring-boot?format=json
        • 匹配到 @GetMapping("/projects/spring-boot")
        • 根据参数协商,优先返回 json 类型数据【需要开启参数匹配设置
        • 发送请求 GET /projects/spring-boot?format=xml,优先返回 xml 类型数据

    如果要返回xml数据格式:

    • 导入支持写出xml内容的依赖:
    1. <dependency>
    2. <groupId>com.fasterxml.jackson.dataformatgroupId>
    3. <artifactId>jackson-dataformat-xmlartifactId>
    4. dependency>
    • 在对应实体类上标注@JacksonXmlElement注解:
    1. @JacksonXmlRootElement // 可以写出为xml文档
    2. @Data
    3. public class Person {
    4. private Long id;
    5. private String userName;
    6. private String email;
    7. private Integer age;
    8. }

    开启基于请求参数的内容协商:

    1. # 开启基于请求参数的内容协商功能。 默认参数名:format。 默认此功能不开启
    2. spring.mvc.contentnegotiation.favor-parameter=true
    3. # 指定内容协商时使用的参数名。默认是 format
    4. spring.mvc.contentnegotiation.parameter-name=type

    内容协商原理

    可以通过定制HttpMessageConverter类来实现多端内容协商,通过编写WebMvcConfigurer提供的configureMessageConverters底层,来修改底层的MessageConverter,以实现定制多端内容协商。

    • @ResponseBody注解由HttpMessageConverter处理
      • 请求来到DispatcherServlet的doDispatch方法进行处理
      • 在HandlerMapping中校验成功后,来到HandlerAdapter,利用HandlerAdapter调用handler方法(使用反射的方法invokeHandlerMethod()来执行目标方法)
      • 目标方法执行之前,准备好了HandlerMethodArgumentResolver和HandlerMethodReturnValueHandler
        • HandlerMethodArgumentResolver:参数解析器,确定目标方法的每个参数值
        • HandlerMethodReturnValueHandler:返回值处理器,确定目标方法的返回值怎么处理
      • invokeAndHandler方法真正执行目标方法,目标方法执行完成,会返回返回值对象
      • 找到返回值处理器HandlerMethodReturnValueHandler
      • 最终找到RequestResponseBodyMethodProcessor,能处理标注了@RequestBody注解的方法
      • RequestResponseBodyMethodProcessor调用writeWithMessageConverters,利用MessageConverter将返回值写出去
    • HttpMessageConverter会先进行内容协商
      • 遍历所有的MessageConverter,找到目标内容类型的数据
      • 要返回json形式的数据的话,MappingJackson2HttpMessageConverter支持写出json数据,最后写出数据

    几种默认HttpMessageConverters

    WebMvcAutoConfiguration提供几种默认HttpMessageConverters

    • EnableWebMvcConfiguration通过 addDefaultHttpMessageConverters添加了默认的MessageConverter;如下:
      • ByteArrayHttpMessageConverter: 支持字节数据读写
      • StringHttpMessageConverter: 支持字符串读写
      • ResourceHttpMessageConverter:支持资源读写
      • ResourceRegionHttpMessageConverter: 支持分区资源写出
      • AllEncompassingFormHttpMessageConverter:支持表单xml/json读写
      • MappingJackson2HttpMessageConverter: 支持请求响应体Json读写

    系统提供默认的MessageConverter 功能有限,仅用于json或者普通返回数据。额外增加新的内容协商功能,必须增加新的HttpMessageConverter

    自定义内容返回

    以导入yaml格式为例:

    • 导入依赖
    1. <dependency>
    2. <groupId>com.fasterxml.jackson.dataformatgroupId>
    3. <artifactId>jackson-dataformat-yamlartifactId>
    4. dependency>
    • 将要返回的对象以yaml形式写出
    1. Person person = new Person();
    2. person.setId(1L);
    3. person.setUserName("张三");
    4. person.setEmail("aaa@qq.com");
    5. person.setAge(18);
    6. //取消文档的开始标记(disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER))
    7. YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
    8. ObjectMapper mapper = new ObjectMapper(factory);
    9. String s = mapper.writeValueAsString(person);

    编写配置

    1. #新增一种媒体类型
    2. spring.mvc.contentnegotiation.media-types.yaml=text/yaml

    配置类方式

    自定义Converter

    1. public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter {
    2. private ObjectMapper objectMapper = null;
    3. public MyYamlHttpMessageConverter(){
    4. //告诉SpringBoot这个MessageConverter支持哪种媒体类型
    5. super(new MediaType("text","yaml", Charset.forName("UTF-8")));
    6. YAMLFactory factory = new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
    7. this.objectMapper = new ObjectMapper(factory);
    8. }
    9. @Override
    10. protected boolean supports(Class clazz) {//是否支持指定类型的转化
    11. //可以在方法内进行类型判断,返回相应的true和false
    12. return true;
    13. }
    14. @Override//指定请求中的数据如何转化
    15. protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
    16. return null;
    17. }
    18. @Override//指定响应中的数据如何转化
    19. protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    20. try (OutputStream body = outputMessage.getBody()){
    21. this.objectMapper.writeValue(body,o);
    22. }
    23. }
    24. }
    25. 最后在WebMvcConfigurer配置类中配置其Converter即可

      1. @Bean
      2. public WebMvcConfigurer webMvcConfigurer(){
      3. return new WebMvcConfigurer() {
      4. @Override //配置一个能把对象转为yaml的messageConverter
      5. public void configureMessageConverters(List> converters{
      6. converters.add(new MyYamlHttpMessageConverter());
      7. }
      8. };
      9. }

      配置步骤:

      • 配置媒体类型支持:
      • 编写对应的HttpMessageConverter,要告诉Boot这个支持的媒体类型
      • 把MessageConverter组件加入到底层
        • 容器中放一个WebMvcConfigurer 组件,并配置底层的MessageConverter

       

    26. 相关阅读:
      ArcGIS Pro SDK (九)几何 1 空间参考
      Spring Boot系列之条件注解
      MQTT协议知识梳理,看完你就懂了!
      SEO外语网站批量翻译软件
      LeetCode(力扣)17. 电话号码的字母组合Python
      nodejs+vue大学食堂订餐系统elementui
      腾讯T14开源的“Oracle与MySQL实战手册”看完被彻底惊艳了
      docker容器镜像管理+compose容器编排(持续更新中)
      面试:换肤方案
      鸿蒙开发学习笔记1
    27. 原文地址:https://blog.csdn.net/2302_79468488/article/details/136750710