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

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

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

1.簡(jiǎn)介

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

2. 實(shí)戰(zhàn)案例

2.1 Long精度丟失

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

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


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

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

圖片圖片

我們看到了2個(gè)結(jié)果,瀏覽器顯示的是正確的,但是通過 Network 查看數(shù)據(jù)錯(cuò)誤,接下來,我們?cè)偻ㄟ^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)該問題。接下來要解決也是非常的簡(jiǎn)單,我們只需要進(jìn)行簡(jiǎn)單的配置即可。

@Component
public class PackMapperCustomizer implements Jackson2ObjectMapperBuilderCustomizer {


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

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

圖片圖片

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

public class User {


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

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

2.2 @JsonValue序列化單個(gè)屬性值

@JsonValue注解用于指示一個(gè)方法,該方法將被用來轉(zhuǎn)換對(duì)象為JSON值。通常,這個(gè)方法會(huì)返回一個(gè)基本類型或其包裝類的實(shí)例,或者是其他可以直接序列化為JSON的對(duì)象。使用 @JsonValue 可以簡(jiǎn)化對(duì)象到JSON的轉(zhuǎn)換過程,使得特定屬性或計(jì)算結(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
}

當(dāng)接口返回該枚舉類時(shí),顯示如下:

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

圖片圖片

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

@JsonValue
private String desc ;

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

圖片圖片

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

public class User {


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

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

圖片圖片


2.3 自定義注解

有些時(shí)候,我們可能對(duì)輸出的某些字段要做特殊的處理在輸出到前端,比如:身份證號(hào),電話等信息,在前端展示的時(shí)候我們需要進(jìn)行脫敏處理,這時(shí)候通過自定義注解就非常的有用了。在Jackson中要自定義注解,我們可以通過@JacksonAnnotationsInside注解來實(shí)現(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全家桶實(shí)戰(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格式序列化

2010-09-26 14:49:41

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

2010-06-22 15:46:52

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

2025-06-18 02:12:00

2022-06-23 08:42:08

配置加密解密

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ù)值

2025-06-27 07:46:53

2024-10-07 08:40:56

Spring應(yīng)用程序Java

2010-03-03 11:41:29

2024-01-10 08:20:13

參數(shù)轉(zhuǎn)換技巧
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 欧美成人h版在线观看 | 久久久久九九九女人毛片 | 欧美中文字幕一区二区 | 欧美1—12sexvideos| 久久极品 | 懂色一区二区三区免费观看 | 国产精品18毛片一区二区 | 日韩一区二区免费视频 | 日韩综合在线 | 免费黄色在线观看 | av一二三四 | 羞羞网站在线观看 | 亚洲精品久久久一区二区三区 | 99一区二区 | 亚洲精品在线视频 | 91最新在线视频 | 91xxx在线观看 | 成人欧美一区二区三区黑人孕妇 | 高清成人av | 男人视频网站 | 久草免费在线视频 | 一区二区三区四区不卡视频 | 亚洲天堂av网 | 欧美一级二级三级视频 | 国产亚洲精品精品国产亚洲综合 | 一级在线 | 国产成人福利在线观看 | 成人黄色a | 噜噜噜色网 | 成人九区 | 午夜精品久久久久久久 | 操皮视频 | ww亚洲ww亚在线观看 | 国产日韩欧美激情 | 在线观看免费福利 | 超碰在线人人 | 天天玩天天干天天操 | 久久久久久免费毛片精品 | 国产精品美女久久久久久免费 | 日韩精品在线视频 | 亚洲精品成人在线 |