最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot2中如何優(yōu)雅地個性化定制Jackson實現(xiàn)示例

 更新時間:2023年05月29日 10:51:54   作者:八卦程序  
這篇文章主要為大家介紹了Spring Boot2中如何優(yōu)雅地個性化定制Jackson實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

概述

本文的編寫初衷,是想了解一下Spring Boot2中,具體是怎么序列化和反序列化JSR 310日期時間體系的,Spring MVC應用場景有如下兩個:

  • 使用@RequestBody來獲取JSON參數(shù)并封裝成實體對象;
  • 使用@ResponseBody來把返回給前端的數(shù)據(jù)轉換成JSON數(shù)據(jù)。

對于一些Integer、String等基礎類型的數(shù)據(jù),Spring MVC可以通過一些內置轉換器來解決,無需用戶關心,但是日期時間類型(例如LocalDateTime),由于格式多變,沒有內置轉換器可用,就需要用戶自己來配置和處理了。

閱讀本文,假設讀者初步了解了如何使用Jackson。

測試環(huán)境

本文使用Spring Boot2.6.6版本,鎖定的Jackson版本如下:

<jackson-bom.version>2.13.2.20220328</jackson-bom.version>

Jackson處理JSR 310日期時間需要引入依賴:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.2</version>
</dependency>

Spring Boot自動配置

在spring-boot-autoconfigure包中,自動配置了Jackson:

package org.springframework.boot.autoconfigure.jackson;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
public class JacksonAutoConfiguration {
    // 詳細代碼略
}

其中有一段代碼配置了ObjectMapper

@Bean
@Primary
@ConditionalOnMissingBean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
   return builder.createXmlMapper(false).build();
}

可以看到ObjectMapper是由Jackson2ObjectMapperBuilder構建的。

再往下會看到如下代碼:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Jackson2ObjectMapperBuilder.class)
static class JacksonObjectMapperBuilderConfiguration {
   @Bean
   @Scope("prototype")
   @ConditionalOnMissingBean
   Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(ApplicationContext applicationContext,
         List&lt;Jackson2ObjectMapperBuilderCustomizer&gt; customizers) {
      Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
      builder.applicationContext(applicationContext);
      customize(builder, customizers);
      return builder;
   }
   private void customize(Jackson2ObjectMapperBuilder builder,
         List&lt;Jackson2ObjectMapperBuilderCustomizer&gt; customizers) {
      for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) {
         customizer.customize(builder);
      }
   }
}

發(fā)現(xiàn)在這里創(chuàng)建了Jackson2ObjectMapperBuilder,并且調用了customize(builder, customizers)方法,傳入Lis<Jackson2ObjectMapperBuilderCustomizer> 進行定制ObjectMapper。

Jackson2ObjectMapperBuilderCustomizer是個接口,只有一個方法,源碼如下:

@FunctionalInterface
public interface Jackson2ObjectMapperBuilderCustomizer {
   /**
    * Customize the JacksonObjectMapperBuilder.
    * @param jacksonObjectMapperBuilder the JacksonObjectMapperBuilder to customize
    */
   void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder);
}

簡單點說,Spring Boot會收集容器里面所有的Jackson2ObjectMapperBuilderCustomizer實現(xiàn)類,統(tǒng)一對Jackson2ObjectMapperBuilder進行設置,從而實現(xiàn)定制ObjectMapper。因此,如果我們想個性化定制ObjectMapper,只需要實現(xiàn)Jackson2ObjectMapperBuilderCustomizer接口并注冊到容器就可以了。

自定義Jackson配置類

廢話不多說,直接上代碼:

@Component
public class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer, Ordered {
    /** 默認日期時間格式 */
    private final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    /** 默認日期格式 */
    private final String dateFormat = "yyyy-MM-dd";
    /** 默認時間格式 */
    private final String timeFormat = "HH:mm:ss";
    @Override
    public void customize(Jackson2ObjectMapperBuilder builder) {
        // 設置java.util.Date時間類的序列化以及反序列化的格式
        builder.simpleDateFormat(dateTimeFormat);
        // JSR 310日期時間處理
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat);
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(dateFormat);
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(timeFormat);
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
        builder.modules(javaTimeModule);
        // 全局轉化Long類型為String,解決序列化后傳入前端Long類型精度丟失問題
        builder.serializerByType(BigInteger.class, ToStringSerializer.instance);
        builder.serializerByType(Long.class,ToStringSerializer.instance);
    }
    @Override
    public int getOrder() {
        return 1;
    }
}

這個配置類實現(xiàn)了三種個性化配置:

  • 設置java.util.Date時間類的序列化以及反序列化的格式;
  • JSR 310日期時間處理;
  • 全局轉化Long類型為String,解決序列化后傳入前端Long類型缺失精度問題。

當然,讀者還可以按自己的需求繼續(xù)進行定制其他配置。

測試

這里用JSR 310日期時間進行測試。

創(chuàng)建實體類User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String name;
    private LocalDate localDate;
    private LocalTime localTime;
    private LocalDateTime localDateTime;
}

創(chuàng)建控制器UserController

@RestController
@RequestMapping("user")
public class UserController {
    @PostMapping("test")
    public User test(@RequestBody User user){
        System.out.println(user.toString());
        return user;
    }
}

前端傳參

{
  "id": 184309536616640512,
  "name": "八卦程序",
  "localDate": "2023-03-01",
  "localTime": "09:35:50",
  "localDateTime": "2023-03-01 09:35:50"
}

后端返回數(shù)據(jù)

{
  "id": "184309536616640512",
  "name": "八卦程序",
  "localDate": "2023-03-01",
  "localTime": "09:35:50",
  "localDateTime": "2023-03-01 09:35:50"
}

可以看到,前端傳入了什么數(shù)據(jù),后端就返回了什么數(shù)據(jù),唯一的區(qū)別就是后端返回的id是字符串了,可以防止前端(例如JavaScript)出現(xiàn)精度丟失問題。

同時也證明LocalDateTime等日期時間類型,到后端參觀了一圈,又正常返回了(沒有被拒,也沒有遭到后端毒打變形,例如變成時間戳回來,導致親媽都不認識了)。

前端表白被拒

如果不配置JacksonConfig呢,Spring MVC在嘗試內置轉換器無果后,會報異常如下:
JSON parse error: Cannot deserialize value of type java.time.LocalDateTime

返回給前端的數(shù)據(jù)如下:

{
  "timestamp": "2023-03-01T09:53:02.158+00:00",
  "status": 400,
  "error": "Bad Request",
  "path": "/user/test"
}

你懂的,被拒了。

總結

核心類ObjectMapper

ObjectMapper是jackson-databind模塊最為重要的一個類,它完成了數(shù)據(jù)處理的幾乎所有功能。
盡管Spring MVC在處理前端傳遞的JSON參數(shù)時,進行了一系列眼花繚亂的操作,但是一頓操作猛如虎,最終還是靠ObjectMapper來完成序列化和反序列化。因此,只需要對Spring Boot默認提供的ObjectMapper進行個性化定制即可。

不要覆蓋默認配置

我們通過實現(xiàn)Jackson2ObjectMapperBuilderCustomizer接口并注冊到容器,進行個性化定制,Spring Boot不會覆蓋默認ObjectMapper的配置,而是進行了合并增強,具體還會根據(jù)Jackson2ObjectMapperBuilderCustomizer實現(xiàn)類的Order優(yōu)先級進行排序,因此上面的JacksonConfig配置類還實現(xiàn)了Ordered接口。

默認的Jackson2ObjectMapperBuilderCustomizerConfiguration優(yōu)先級是0,因此如果我們想要覆蓋配置,設置優(yōu)先級大于0即可。

注意:在SpringBoot2環(huán)境下,不要將自定義的ObjectMapper對象注入容器,這樣會將原有的ObjectMapper配置覆蓋!

QueryString格式參數(shù)

需要注意的是,Jackson不能解決QueryString格式參數(shù)的問題,因為Spring對于這類參數(shù)用的是Converter類型轉換機制,那就是另一條參數(shù)綁定之路了(不好意思,Jackson沒在這條路上幫忙)。

需要自定義參數(shù)類型轉換器來處理日期時間類型,需要另寫文章介紹了,更多關于Spring Boot2定制Jackson的資料請關注腳本之家其它相關文章!

相關文章

  • Java項目時的命名規(guī)范使用及說明

    Java項目時的命名規(guī)范使用及說明

    文章總結了SpringBoot項目命名規(guī)范,包括項目、包、類、方法、變量、配置文件、Starter、API、數(shù)據(jù)庫和其它命名規(guī)則,以確保代碼的一致性和可讀性
    2026-01-01
  • springboot @validated List校驗失效問題

    springboot @validated List校驗失效問題

    這篇文章主要介紹了springboot @validated List校驗失效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java 程序設計總復習題(java基礎代碼)

    Java 程序設計總復習題(java基礎代碼)

    這篇文章主要介紹了Java 程序設計總復習題,主要是java基礎代碼,方便學習java的同學
    2021-05-05
  • Maven重復依賴問題解決(同一個jar多個版本)

    Maven重復依賴問題解決(同一個jar多個版本)

    本文主要介紹了Maven重復依賴問題解決(同一個jar多個版本),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • Java循環(huán)結構之多重循環(huán)及continue?break

    Java循環(huán)結構之多重循環(huán)及continue?break

    這篇文章主要介紹了Java循環(huán)結構之多重循環(huán)及continue?break,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-09-09
  • SpringBoot2 集成測試組件的七種方法

    SpringBoot2 集成測試組件的七種方法

    下面圍繞幾個自己開發(fā)過程中常用的測試工具和手段,做簡單的總結,不在于對比方式的好壞,存在即合理,在不同場景中對合理手段的選擇,快速解決問題才是根本目的。
    2021-06-06
  • Spring context:component-scan的使用及說明

    Spring context:component-scan的使用及說明

    這篇文章主要介紹了Spring context:component-scan的使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Mybatis應用mysql存儲過程查詢數(shù)據(jù)實例

    Mybatis應用mysql存儲過程查詢數(shù)據(jù)實例

    下面小編就為大家分享一篇Mybatis應用mysql存儲過程查詢數(shù)據(jù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • SpringMVC中Controller層獲取前端請求參數(shù)的方式匯總

    SpringMVC中Controller層獲取前端請求參數(shù)的方式匯總

    這篇文章主要介紹了SpringMVC中Controller層獲取前端請求參數(shù)的幾種方式,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • java隨機字符串生成示例

    java隨機字符串生成示例

    這篇文章主要介紹了java隨機字符串生成示例,這個字符隨機生成類可以生成多種組合的字符串,比如大+小字符+數(shù)字+符號,需要的朋友可以參考下
    2014-03-03

最新評論

浠水县| 长沙市| 分宜县| 肃南| 绍兴市| 云霄县| 闽侯县| 莱芜市| 长丰县| 鲁山县| 慈溪市| 司法| 天津市| 屏边| 崇文区| 桃源县| 大连市| 久治县| 永仁县| 荣昌县| 义马市| 广西| 仁怀市| 潮安县| 金湖县| 筠连县| 南召县| 万山特区| 山丹县| 湘潭县| 隆子县| 雷州市| 成安县| 建平县| 宁乡县| 南充市| 土默特左旗| 桓台县| 开江县| 新龙县| 阿勒泰市|