成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Jackson在Spring Boot高級應用技巧【Long精度丟失, @JsonValue, 數據脫敏】

開發 前端
在Web開發中,使用JavaScript處理大數值(如Long類型)時,可能會遇到精度丟失的問題。這是因為JavaScript中的數字一律采用IEEE-754標準的64位浮點數表示,這種格式可以很好地處理大多數數字運算,但對于非常大的整數(超出2^53 - 1),就可能出現精度損失,這就非常的惡心了,可能會讓你感到莫名其妙。

1.簡介

  • Long類型在前端缺失精度
  • @JsonValue序列化單個屬性值
  • 自定義注解的應用 

2. 實戰案例

2.1 Long精度丟失

在Web開發中,使用JavaScript處理大數值(如Long類型)時,可能會遇到精度丟失的問題。這是因為JavaScript中的數字一律采用IEEE-754標準的64位浮點數表示,這種格式可以很好地處理大多數數字運算,但對于非常大的整數(超出2^53 - 1),就可能出現精度損失,這就非常的惡心了,可能會讓你感到莫名其妙。當從后端獲取到Long類型的值并嘗試在前端展示時,如果該值超過了JavaScript安全整數范圍,那么顯示的結果可能不準確,如下示例:

@RestController
@RequestMapping("/longs")
public class LongController {


  @GetMapping("")
  public Map<String, Object> getData() {
    return Map.of("code", 0, "data", 123456789012345678L) ;
  }
}

接口返回了一個17位的Long類型數據,我們先直接通過瀏覽器訪問,結果如下:

圖片圖片

我們看到了2個結果,瀏覽器顯示的是正確的,但是通過 Network 查看數據錯誤,接下來,我們再通過Ajax獲取數據。

function getData() {
  axios.get('http://localhost:8080/longs')
    .then(resp => {
      console.log(resp.data) ;
    }).catch((error) => {
      console.log(error) ;
    });
}

圖片圖片

在這種前后端分離的架構下,千萬的小心,如果你返回的Long類型超過了前端number的范圍,那么將出現該問題。接下來要解決也是非常的簡單,我們只需要進行簡單的配置即可。

@Component
public class PackMapperCustomizer implements Jackson2ObjectMapperBuilderCustomizer {


  @Override
  public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
    jacksonObjectMapperBuilder.serializerByType(Long.class, ToStringSerializer.instance) ;
  }
}

這里我們將Long類型轉換為String類型。再次運行上面的代碼

圖片圖片

通過自定義 Jackson2ObjectMapperBuilderCustomizer 屬于全局的,項目中所有的Long都會被轉換為String進行輸出。這可能不是我們希望的,我們可能只是希望有針對的處理,這時候我們就可以通過注解的方式了,如下示例:

public class User {


  @JsonSerialize(using = ToStringSerializer.class)
  private Long id ;
  private String name ;
  // getters, setters
}

通過上面注解的方式就能針對性的控制輸出字段類型。

2.2 @JsonValue序列化單個屬性值

@JsonValue注解用于指示一個方法,該方法將被用來轉換對象為JSON值。通常,這個方法會返回一個基本類型或其包裝類的實例,或者是其他可以直接序列化為JSON的對象。使用 @JsonValue 可以簡化對象到JSON的轉換過程,使得特定屬性或計算結果能夠直接作為JSON輸出,而無需定義復雜的序列化邏輯。

現在有,如下的枚舉類:

public enum PaymentStatus {


  NO_PAY(0, "未支付"), PAID(1, "已支付") ;
  
  PaymentStatus(int code, String desc) {
    this.code = code ;
    this.desc = desc ;
  }
  private Integer code ;
  private String desc ;
  // getters, setters
}

當接口返回該枚舉類時,顯示如下:

@GetMapping("")
public PaymentStatus status() {
  return PaymentStatus.PAID ;
}

圖片圖片

輸出了枚舉的字符串形式,如果我們要顯示具體的code或者是desc,那么我們就可以使用 @JsonValue 注解。

@JsonValue
private String desc ;

在需要輸出的字段上添加 @JsonValue 注解即可。

圖片圖片

如果該注解應用到一個普通的Java Bean對象中的某個屬性時,如下示例:

public class User {


  @JsonSerialize(using = ToStringSerializer.class)
  private Long id ;
  @JsonValue
  private String name ;
}

這時候接口輸出的將是name屬性對應的值。

圖片圖片


2.3 自定義注解

有些時候,我們可能對輸出的某些字段要做特殊的處理在輸出到前端,比如:身份證號,電話等信息,在前端展示的時候我們需要進行脫敏處理,這時候通過自定義注解就非常的有用了。在Jackson中要自定義注解,我們可以通過@JacksonAnnotationsInside注解來實現,如下示例:

自定義注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerializer.class)
public @interface Sensitive {


  int start() default 0 ;
  
  int end() default 0 ;
  
  String mask() default "*" ;
}

自定義序列化處理器SensitiveSerializer

public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {


  private Sensitive sensitive;


  @Override
  public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    String val = value;
    if (sensitive != null && StringUtils.hasLength(val)) {
      String m = sensitive.mask();
      int start = sensitive.start();
      int end = sensitive.end();
      int totalLength = value.length();


      if (totalLength <= 2) {
        val = totalLength == 1 ? value + m : value.substring(0, 1) + m;
      } else if (totalLength <= 6) {
        val = value.substring(0, 1) + String.join("", Collections.nCopies(totalLength - 2, m))
            + value.substring(totalLength - 1);
      } else {
        int prefixLength = Math.min(start, totalLength - 1);
        int suffixLength = Math.min(end, totalLength - 1);


        if (prefixLength > totalLength) {
          prefixLength = totalLength / 2;
        }
        if (suffixLength > totalLength) {
          suffixLength = totalLength / 2;
        }


        int maskLength = Math.max(0, totalLength - (prefixLength + suffixLength));
        if (maskLength == 0) {
          prefixLength -= 2;
          suffixLength -= 2;
          maskLength = Math.max(2, totalLength - (prefixLength + suffixLength));
        }


        prefixLength = Math.min(prefixLength, totalLength - 1);
        suffixLength = Math.min(suffixLength, totalLength - 1);


        maskLength = totalLength - prefixLength - suffixLength;


        val = value.substring(0, prefixLength) + String.join("", Collections.nCopies(maskLength, m))
            + value.substring(totalLength - suffixLength);
      }
    }
    gen.writeString(val);
  }


  @Override
  public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
      throws JsonMappingException {
    sensitive = property.getAnnotation(Sensitive.class);
    return this;
  }
}

接下來,在輸出的Java Bean中使用上面的注解。

public class User {


  @JsonSerialize(using = ToStringSerializer.class)
  private Long id ;
  private String name ;
  @Sensitive(start = 6, end = 4)
  private String idCard ;
  @Sensitive(start = 4, end = 3)
  private String phone ;
  // getters, setters
}

最后,在前端展示結果如下:

圖片

敏感數據得到了脫敏處理。

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2023-12-13 10:36:38

Long算法代碼

2024-01-22 08:46:37

MyBatis數據脫敏Spring

2024-09-30 11:51:07

2025-01-13 12:46:31

SpringBootJacksonJSON

2025-01-21 08:10:00

2022-06-27 08:16:34

JSON格式序列化

2010-09-26 14:49:41

部署終端數據丟失防護

2010-06-22 15:46:52

數據安全丟失防護

2022-06-23 08:42:08

配置加密解密

2025-06-18 02:12:00

2017-09-20 09:46:38

Spring BootSpring Clou內存

2019-07-15 16:00:24

Docker架構容器

2019-07-15 10:00:53

DockerJava容器

2024-09-12 13:13:58

2024-09-09 05:30:00

數據庫Spring

2024-10-25 14:39:26

BigDecimal精度數值

2024-10-07 08:40:56

Spring應用程序Java

2010-03-03 11:41:29

2024-01-10 08:20:13

參數轉換技巧

2018-10-22 15:34:31

Spring Boo監控視化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久精品国产亚洲一区二区三区 | 草久网 | 亚洲小说图片 | 综合久久国产 | 国产专区免费 | 国产欧美精品区一区二区三区 | 午夜免费福利电影 | 欧美久| 日韩欧美一区二区三区四区 | 国产欧美日韩视频 | www97影院 | 久久久久国产精品午夜一区 | 亚洲一区二区视频在线播放 | 一级片av | 亚洲国产一区视频 | 九九伦理电影 | 欧美一级免费 | 91免费观看国产 | 欧美四虎| 欧美日韩理论 | 亚洲一区视频在线 | 久久这里只有精品首页 | 激情av | av天天看| 在线一区二区三区 | 亚洲精品视频播放 | 爱操影视 | 久久久久久久网 | 久久99精品国产 | 亚洲国产精品日韩av不卡在线 | 无码一区二区三区视频 | 欧美精品一区在线 | 日韩欧美在线观看视频 | 国产激情一区二区三区 | 国产精品激情 | 狠狠色综合网站久久久久久久 | 中文字幕亚洲精品 | 亚洲一区在线播放 | 99爱在线| 91精品久久久久久久久久入口 | 一级片在线播放 |