欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot?中的?Filter?實(shí)現(xiàn)超大響應(yīng)?JSON?數(shù)據(jù)壓縮的方法

 更新時(shí)間:2022年10月13日 09:17:02   作者:BUG弄潮兒  
這篇文章主要介紹了Springboot?中的?Filter?實(shí)現(xiàn)超大響應(yīng)?JSON?數(shù)據(jù)壓縮,定義GzipFilter對(duì)輸出進(jìn)行攔截,定義 Controller該 Controller 非常簡(jiǎn)單,主要讀取一個(gè)大文本文件,作為輸出的內(nèi)容,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下

簡(jiǎn)介

項(xiàng)目中,請(qǐng)求時(shí)發(fā)送超大 json 數(shù)據(jù)外;響應(yīng)時(shí)也有可能返回超大 json數(shù)據(jù)。上一篇實(shí)現(xiàn)了請(qǐng)求數(shù)據(jù)的 gzip 壓縮。本篇通過(guò) filter 實(shí)現(xiàn)對(duì)響應(yīng) json 數(shù)據(jù)的壓縮。
先了解一下以下兩個(gè)概念:

  • 請(qǐng)求頭:Accept-Encoding : gzip告訴服務(wù)器,該瀏覽器支持 gzip 壓縮
  • 響應(yīng)頭:Content-Encoding : gzip告訴瀏覽器,輸出信息使用了 gzip 進(jìn)行壓縮

pom.xml 引入依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
 
	<groupId>com.olive</groupId>
	<artifactId>response-compression</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
 
	<name>response-compression</name>
	<url>http://maven.apache.org</url>
 
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.14</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
 
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
	</properties>
 
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba.fastjson2</groupId>
			<artifactId>fastjson2</artifactId>
			<version>2.0.14</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.9.0</version>
		</dependency>
	</dependencies>
</project>

對(duì)Response進(jìn)行包裝

GzipResponseWrapper 類重新定義了輸出流,攔截需要輸出的數(shù)據(jù),直接緩存到 ByteArrayOutputStream 中。

package com.olive.filter;
 
import lombok.extern.slf4j.Slf4j;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
 
@Slf4j
public class GzipResponseWrapper extends HttpServletResponseWrapper {
 
    /**
     * 字節(jié)數(shù)組緩沖流,用來(lái)保存截獲到的輸出數(shù)據(jù)
     */
    private ByteArrayOutputStream buffer;
 
    /**
     * 重新定義servlet輸出流,改變輸出目的地將響應(yīng)內(nèi)容輸出到給定的字節(jié)數(shù)組緩沖流中
     */
    private GzipResponseWrapper.CustomServletOutputStream servletOutputStream;
 
    /**
     * 同上
     */
    private PrintWriter writer;
 
    public GzipResponseWrapper(HttpServletResponse response) {
        super(response);
        //original HttpServletResponse object
        buffer = new ByteArrayOutputStream();
        servletOutputStream = new GzipResponseWrapper.CustomServletOutputStream(buffer);
        try {
            writer = new PrintWriter(new OutputStreamWriter(buffer, response.getCharacterEncoding()), true);
        } catch (UnsupportedEncodingException e) {
            log.error("GZipHttpServletResponse", e);
        }
    }
 
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return servletOutputStream;
    }
 
    @Override
    public PrintWriter getWriter() throws IOException {
        return writer;
    }
 
    @Override
    public void flushBuffer() throws IOException {
        if (servletOutputStream != null) {
            servletOutputStream.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }
 
    /**
     * 向外部提供一個(gè)獲取截獲數(shù)據(jù)的方法
     * @return 從response輸出流中截獲的響應(yīng)數(shù)據(jù)
     */
    public byte[] getOutputData() throws IOException {
        flushBuffer();
        return buffer.toByteArray();
    }
 
    private static class CustomServletOutputStream extends ServletOutputStream {
 
        /**
         * 字節(jié)數(shù)組緩沖流,用來(lái)保存截獲到的輸出數(shù)據(jù)
         */
        private ByteArrayOutputStream buffer;
 
        public CustomServletOutputStream(ByteArrayOutputStream buffer) {
            this.buffer = buffer;
        }
 
        @Override
        public boolean isReady() {
            return true;
        }
 
        @Override
        public void setWriteListener(WriteListener listener) {
        }
 
        /**
         * 重寫(xiě)輸出流相關(guān)的方法
         * 將輸出數(shù)據(jù)寫(xiě)出到給定的ByteArrayOutputStream緩沖流中保存起來(lái)
         * @param b 輸出的數(shù)據(jù)
         * @throws IOException
         */
        @Override
        public void write(int b) throws IOException {
            buffer.write(b);
        }
    }
}

定義GzipFilter對(duì)輸出進(jìn)行攔截

GzipFilter 攔截器獲取緩存的需要輸出的數(shù)據(jù),進(jìn)行壓縮,在輸出數(shù)據(jù)之前先設(shè)置響應(yīng)頭Content-Encoding : gzip。

package com.olive.filter;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
 
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.GZIPOutputStream;
 
/**
 * 壓縮過(guò)濾器
 *
 * 功能:對(duì)于返回給客戶端的數(shù)據(jù)進(jìn)行g(shù)zip壓縮,提高響應(yīng)速度
 * 實(shí)現(xiàn)說(shuō)明:
 *     要對(duì)response對(duì)象的輸出數(shù)據(jù)進(jìn)行g(shù)zip壓縮,首先得拿到后面servlet(controller)進(jìn)行業(yè)務(wù)處理后往response對(duì)象里寫(xiě)入的數(shù)據(jù)
 *     可以通過(guò)重寫(xiě)response對(duì)象,修改該對(duì)象內(nèi)部的輸出流,使該流寫(xiě)出數(shù)據(jù)時(shí)寫(xiě)出到給定的字節(jié)數(shù)組緩沖流當(dāng)中,
 *     并在重寫(xiě)后的response對(duì)象內(nèi)部提供一個(gè)獲取該字節(jié)數(shù)組緩沖流的方法,這樣就可以截獲響應(yīng)數(shù)據(jù)
 *     然后就可以對(duì)截獲的響應(yīng)數(shù)據(jù)通過(guò)Gzip輸出流進(jìn)行壓縮輸出即可;
 *     因?yàn)轫憫?yīng)數(shù)據(jù)是gzip壓縮格式,不是普通的文本格式所以需要通過(guò)response對(duì)象(響應(yīng)頭)告知瀏覽器響應(yīng)的數(shù)據(jù)類型
 */
@Slf4j
public class GzipFilter implements Filter {
 
    private final String GZIP = "gzip";
 
    public void destroy() {
        log.info("GzipFilter destroy");
    }
 
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        log.info("GzipFilter start");
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String acceptEncoding = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
        //searching for 'gzip' in ACCEPT_ENCODING header
        if( acceptEncoding != null && acceptEncoding.indexOf(GZIP) >= 0){
            GzipResponseWrapper gzipResponseWrapper = new GzipResponseWrapper(response);
            //pass the customized response object to controller to capture the output data
            chain.doFilter(request, gzipResponseWrapper);
            //get captured data
            byte[] data = gzipResponseWrapper.getOutputData();
            log.info("截獲到數(shù)據(jù):" + data.length + " bytes");
            //get gzip data
            ByteArrayOutputStream gzipBuffer = new ByteArrayOutputStream();
            GZIPOutputStream gzipOut = new GZIPOutputStream(gzipBuffer);
            gzipOut.write(data);
            gzipOut.flush();
            gzipOut.close();
            byte[] gzipData = gzipBuffer.toByteArray();
            log.info("壓縮后數(shù)據(jù):" + gzipData.length + " bytes");
            //set response header and output
            response.setHeader(HttpHeaders.CONTENT_ENCODING, GZIP);
            response.getOutputStream().write(gzipData);
            response.getOutputStream().flush();
        }else{
            chain.doFilter(req, resp);
        }
    }
 
    public void init(FilterConfig config) throws ServletException {
        log.info("GzipFilter init");
    }
 
}

注冊(cè) GzipFilter 攔截器

package com.olive.config;
 
import com.olive.filter.GzipFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
/**
 * 注冊(cè)filter
 */
@Configuration
public class FilterRegistration {
 
    @Bean
    public FilterRegistrationBean<GzipFilter> gzipFilterRegistrationBean() {
        FilterRegistrationBean<GzipFilter> registration = new FilterRegistrationBean<>();
        //Filter可以new,也可以使用依賴注入Bean
        registration.setFilter(new GzipFilter());
        //過(guò)濾器名稱
        registration.setName("gzipFilter");
        //攔截路徑
        registration.addUrlPatterns("/*");
        //設(shè)置順序
        registration.setOrder(1);
        return registration;
    }
}

定義 Controller

該 Controller 非常簡(jiǎn)單,主要讀取一個(gè)大文本文件,作為輸出的內(nèi)容。

package com.olive.controller;
 
import java.io.File;
import java.util.HashMap;
import java.util.Map;
 
import com.olive.vo.ArticleRequestVO;
import org.apache.commons.io.FileUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class TestController {
 
	@RequestMapping("/getArticle")
	public Map<String, Object> getArticle(){
		Map<String, Object> result = new HashMap<>();
		result.put("code", 200);
		result.put("msg", "success");
		byte[] bytes = null;
		try {
			bytes = FileUtils.readFileToByteArray(new File("C:\\Users\\2230\\Desktop\\凱平項(xiàng)目資料\\改裝車項(xiàng)目\\CXSSBOOT_DB_DDL-1.0.9.sql"));
		}catch (Exception e){
 
		}
		String content = new String(bytes);
		ArticleRequestVO vo = new ArticleRequestVO();
		vo.setId(1L);
		vo.setTitle("BUG弄潮兒");
		vo.setContent(content);
		result.put("body", vo);
		return result;
	}
 
}

Controller 返回?cái)?shù)據(jù)的 VO

package com.olive.vo;
 
import lombok.Data;
 
import java.io.Serializable;
 
@Data
public class ArticleRequestVO implements Serializable {
 
    private Long id;
 
    private String title;
 
    private String content;
 
}

定義 Springboot 引導(dǎo)類

package com.olive;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

測(cè)試

測(cè)試的curl

curl -X POST http://127.0.0.1:8080/getArticle 

到此這篇關(guān)于Springboot 中的 Filter 實(shí)現(xiàn)超大響應(yīng) JSON 數(shù)據(jù)壓縮的文章就介紹到這了,更多相關(guān)Springboot JSON 數(shù)據(jù)壓縮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論