偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

API接口優(yōu)化!基于Spring Boot 實(shí)現(xiàn)Deflate壓縮技術(shù)

開發(fā) 前端
在本篇文章中,我們將探討Deflate壓縮,包括它為什么重要、何時(shí)使用它以及如何在Spring Boot應(yīng)用程序中實(shí)現(xiàn)它。通過(guò)本篇文章你將清楚地了解如何使用Deflate壓縮來(lái)優(yōu)化應(yīng)用程序的性能。

環(huán)境:SpringBoot3.2.5

1. 簡(jiǎn)介

一個(gè)應(yīng)用的性能是決定用戶體驗(yàn)好壞的關(guān)鍵因素。提高性能的最有效方法之一是減少服務(wù)器與客戶端之間傳輸?shù)臄?shù)據(jù)大小。這正是壓縮技術(shù)發(fā)揮作用的地方。Spring Boot 提供了對(duì)各種壓縮技術(shù)的內(nèi)置支持,以優(yōu)化數(shù)據(jù)傳輸。

在本篇文章中,我們將探討Deflate壓縮,包括它為什么重要、何時(shí)使用它以及如何在Spring Boot應(yīng)用程序中實(shí)現(xiàn)它。通過(guò)本篇文章你將清楚地了解如何使用Deflate壓縮來(lái)優(yōu)化應(yīng)用程序的性能。

1.1 什么是Deflate壓縮?

Deflate是一種無(wú)損數(shù)據(jù)壓縮算法,它結(jié)合了LZ77算法和霍夫曼編碼來(lái)減小數(shù)據(jù)的大小。在Web應(yīng)用程序中,Deflate被廣泛用于在向客戶端發(fā)送HTTP響應(yīng)之前對(duì)其進(jìn)行壓縮。

當(dāng)客戶端(例如瀏覽器或API使用者)從服務(wù)器請(qǐng)求數(shù)據(jù)時(shí),服務(wù)器可以使用Deflate對(duì)響應(yīng)進(jìn)行壓縮,從而減小通過(guò)網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)大小??蛻舳嗽诮邮盏綌?shù)據(jù)后進(jìn)行解壓縮。

1.2 為什么使用Deflate壓縮?

  • 提高性能
    網(wǎng)絡(luò)上的數(shù)據(jù)傳輸速度更快。延遲降低,特別是對(duì)于使用慢速或帶寬有限的連接的用戶而言。
  • 節(jié)省帶寬
    壓縮減少了通過(guò)網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)量,這對(duì)于流量高或負(fù)載大的應(yīng)用程序(例如,JSON或XML響應(yīng))非常重要。
  • 提升用戶體驗(yàn)
    更快的響應(yīng)時(shí)間帶來(lái)更好的用戶體驗(yàn),特別是對(duì)于移動(dòng)用戶或從遠(yuǎn)程位置訪問(wèn)的應(yīng)用程序的用戶而言。

1.3 應(yīng)用場(chǎng)景

  • 響應(yīng)結(jié)果很大
    如果你的API返回大的JSON或XML響應(yīng),壓縮數(shù)據(jù)可以顯著減少響應(yīng)時(shí)間。
  • 靜態(tài)內(nèi)容
    壓縮HTML、CSS和JavaScript文件等靜態(tài)資源可以改善頁(yè)面加載時(shí)間

注意:如果對(duì)應(yīng)響應(yīng)結(jié)果比較小的(小于2kb)時(shí)候反而使用壓縮技術(shù)會(huì)對(duì)性能造成影響。

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

2.1 Deflate過(guò)濾器

public class DeflateCompressionFilter implements Filter {


  private static final int MIN_RESPONSE_SIZE = 2 * 1024 ;


  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;


    String acceptEncoding = req.getHeader("Accept-Encoding");
    // 這里我們更加請(qǐng)求header中的Accept-Encoding進(jìn)行判斷,只有包含指定的值才進(jìn)行處理
    if (acceptEncoding == null || !acceptEncoding.toLowerCase().contains("deflate")) {
      chain.doFilter(request, response);
      return;
    }
    // 自定義Response包裝類,我們需要對(duì)響應(yīng)結(jié)果進(jìn)行獲取處理
    DeflateResponseWrapper responseWrapper = new DeflateResponseWrapper(resp);


    chain.doFilter(request, responseWrapper);
    // 只有響應(yīng)的數(shù)據(jù)大小超過(guò)這里指定的值(2KB)才進(jìn)行壓縮處理
    if (responseWrapper.getContentLength() > MIN_RESPONSE_SIZE) {
      // 必須設(shè)置,否則客戶端將無(wú)法解析解壓數(shù)據(jù)
      resp.setHeader("Content-Encoding", "deflate");
      try (DeflaterOutputStream dos= new DeflaterOutputStream(resp.getOutputStream())) {
        dos.write(responseWrapper.getCapturedData());
      }
    } else {
      // Write the uncompressed response
      resp.getOutputStream().write(responseWrapper.getCapturedData());
    }
  }
}

關(guān)鍵的注釋已經(jīng)在源碼中進(jìn)行了處理。

注意:這里沒(méi)有判斷響應(yīng)數(shù)據(jù)的類型可以根據(jù)Content-Type進(jìn)行判斷。

2.2 Response包裝類

public class DeflateResponseWrapper extends HttpServletResponseWrapper {


  private final ByteArrayOutputStream capture;
  private ServletOutputStream outputStream;
  private PrintWriter writer;


  public DeflateResponseWrapper(HttpServletResponse response) {
    super(response);
    capture = new ByteArrayOutputStream() ;
  }
  public ServletOutputStream getOutputStream() {
    if (writer != null) {
      throw new IllegalStateException("Writer already in use");
    }
    if (outputStream == null) {
      outputStream = new ServletOutputStream() {
        public void write(int b) throws IOException {
          capture.write(b);
        }
        public void flush() throws IOException {
          capture.flush();
        }
        public void close() throws IOException {
          capture.close();
        }
        public boolean isReady() {
          return true;
        }
        public void setWriteListener(WriteListener writeListener) {
        }
      };
    }
    return outputStream;
  }
  public PrintWriter getWriter() {
    if (outputStream != null) {
      throw new IllegalStateException("OutputStream already in use");
    }
    if (writer == null) {
      writer = new PrintWriter(capture);
    }
    return writer;
  }
  public byte[] getCapturedData() {
    return capture.toByteArray();
  }
  public int getContentLength() {
    return capture.size();
  }
}

我們需要將數(shù)據(jù)先寫入到內(nèi)存輸出流中,這樣我們才能得到當(dāng)前寫入到響應(yīng)流中的數(shù)據(jù)。

2.3 注冊(cè)過(guò)濾器

在Spring Boot中我們可以通過(guò)如下方式注冊(cè)過(guò)濾器,也可以通過(guò)@WedFilter的方式注冊(cè)。

@Bean
FilterRegistrationBean<DeflateCompressionFilter> deflateCompressionFilter() {
  FilterRegistrationBean<DeflateCompressionFilter> registrationBean = new FilterRegistrationBean<>();
  registrationBean.setFilter(new DeflateCompressionFilter());
  // 對(duì)所有的請(qǐng)求都進(jìn)行過(guò)去了處理
  registrationBean.addUrlPatterns("/*") ;
  registrationBean.setName("DeflateCompressionFilter") ;
  registrationBean.setOrder(1) ;
  return registrationBean ;
}

以上我們就完成了所有的代碼,接下來(lái)我們進(jìn)行測(cè)試。

2.4 測(cè)試

接下來(lái),我們通過(guò)如下接口進(jìn)行測(cè)試:

@GetMapping("/data")
public List<User> getData() {
  List<User> data = new ArrayList<>() ;
  for (long i = 0; i < 10000; i++) {
    data.add(new User(i, "姓名 - " + i, new Random().nextInt(100))) ;
  }
  return data;
}
public static record User (Long id, String name, Integer age) {}

首先,我們將請(qǐng)求的Accept-Encoding隨意寫一個(gè)值,響應(yīng)結(jié)果

圖片圖片

最后,我們?cè)趯ccept-Encoding設(shè)置為deflate,響應(yīng)結(jié)果:

圖片圖片

與壓縮前相比:壓縮了近6.7倍。

顯著提升應(yīng)用程序的性能,減少帶寬使用,并增強(qiáng)用戶體驗(yàn)。

注意:你完全可以使用GZIP進(jìn)行壓縮,并且使用GZIP也是當(dāng)前最為推薦流行的方式,并且兼容性要比deflate好。

如果啟用GZIP?如下配置即可:

server:
  compression:
    enabled: true
    min-response-size: 1024
    mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml

而本篇文章的目標(biāo)是讓你了解這壓縮技術(shù)的實(shí)現(xiàn)原理。而在上面自定義的過(guò)濾器中,我們也完全可以使用GZIP對(duì)應(yīng)的輸出流進(jìn)行壓縮數(shù)據(jù),如下代碼:

if (responseWrapper.getContentLength() > MIN_RESPONSE_SIZE) {
  // 設(shè)置響應(yīng)的內(nèi)容編碼類型為gzip
  resp.setHeader("Content-Encoding", "gzip");
  // 使用gzip進(jìn)行壓縮數(shù)據(jù)
  try (GZIPOutputStream gos = new GZIPOutputStream(resp.getOutputStream())) {
    gos.write(responseWrapper.getCapturedData()) ;
  }
} else {
  resp.getOutputStream().write(responseWrapper.getCapturedData());
}


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

2025-01-08 09:35:55

Spring性能監(jiān)控

2025-02-12 08:47:07

SpringAPI接口

2025-06-06 08:28:56

2024-10-15 09:34:57

2022-10-26 12:43:52

SpringBootPDF

2022-05-23 13:44:53

前端開發(fā)優(yōu)化

2024-10-18 08:00:00

SpringBoot框架開發(fā)

2025-06-19 09:53:30

Spring性能優(yōu)化服務(wù)器

2024-10-15 16:01:19

SpringBoot緩存預(yù)熱

2021-03-09 13:18:53

加密解密參數(shù)

2023-05-11 12:40:00

Spring控制器HTTP

2022-06-04 12:25:10

解密加密過(guò)濾器

2017-04-25 10:46:57

Spring BootRESRful API權(quán)限

2025-02-19 16:00:00

SpringBootDeepSeek智能

2025-02-13 07:45:26

APISpringHTTP

2024-10-15 10:38:32

2024-11-01 10:40:32

2023-11-09 09:48:16

數(shù)據(jù)壓縮微服務(wù)

2024-07-26 07:59:25

2024-08-29 09:01:39

點(diǎn)贊
收藏

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