自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Jackson在Spring Boot高級應(yīng)用技巧【Long精度丟失, @JsonValue, 數(shù)據(jù)脫敏】

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

1.簡介

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

2. 實戰(zhàn)案例

2.1 Long精度丟失

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

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


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

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

圖片圖片

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

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

圖片圖片

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

@Component
public class PackMapperCustomizer implements Jackson2ObjectMapperBuilderCustomizer {


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

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

圖片圖片

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

public class User {


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

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

2.2 @JsonValue序列化單個屬性值

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

現(xiàn)在有,如下的枚舉類:

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 注解即可。

圖片圖片

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

public class User {


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

這時候接口輸出的將是name屬性對應(yīng)的值。

圖片圖片


2.3 自定義注解

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

自定義注解

@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
}

最后,在前端展示結(jié)果如下:

圖片

敏感數(shù)據(jù)得到了脫敏處理。

責(zé)任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關(guān)推薦

2023-12-13 10:36:38

Long算法代碼

2024-01-22 08:46:37

MyBatis數(shù)據(jù)脫敏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格式序列化

2022-06-23 08:42:08

配置加密解密

2010-06-22 15:46:52

數(shù)據(jù)安全丟失防護

2010-09-26 14:49:41

部署終端數(shù)據(jù)丟失防護

2017-09-20 09:46:38

Spring BootSpring Clou內(nèi)存

2019-07-15 16:00:24

Docker架構(gòu)容器

2019-07-15 10:00:53

DockerJava容器

2024-09-12 13:13:58

2024-09-09 05:30:00

數(shù)據(jù)庫Spring

2024-10-25 14:39:26

BigDecimal精度數(shù)值

2024-10-07 08:40:56

Spring應(yīng)用程序Java

2024-01-10 08:20:13

參數(shù)轉(zhuǎn)換技巧

2010-03-03 11:41:29

2016-10-14 14:16:28

Spring BootJava應(yīng)用

2018-10-22 15:34:31

Spring Boo監(jiān)控視化
點贊
收藏

51CTO技術(shù)棧公眾號