解决后端给前端的返回数据过大的问题(压缩)
解决后端给前端的返回数据过大的问题(压缩)
问题
后端返回数据过大导致的前端接收数据慢的问题
方案
注解方式压缩后端给前端的返回数据,注解@Gzip压缩后端返回数据(前端不用做任何处理)
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.util.Objects;
import java.util.zip.GZIPOutputStream;
@Aspect
@Slf4j
@Component
public class GzipAspect {
@Pointcut("@annotation(com.xxx.xxx.xxx.annotation.gzip.Gzip)")
public void gzipAnnotation() {}
@AfterReturning(pointcut = "gzipAnnotation()", returning = "result")
public void applyGzipCompression(JoinPoint joinPoint, Object result) {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
if (Objects.isNull(response)) return;
try {
ObjectMapper mapper = new ObjectMapper();
byte[] data = mapper.writeValueAsBytes(result);
// 当返回体大于2048KB开启Gzip
if (data.length < 2048 * 1024) {
return;
}
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Vary", "Accept-Encoding");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
gzipOutputStream.write(data);
gzipOutputStream.close();
byte[] compressedData = byteArrayOutputStream.toByteArray();
response.setContentLength(compressedData.length);
ServletOutputStream servletOutputStream = response.getOutputStream();
servletOutputStream.write(compressedData);
servletOutputStream.flush();
servletOutputStream.close();
} catch (Throwable e) {
log.error("开启Gzip返回失败");
log.error(e.getMessage());
}
}
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 对标注有@Gzip的接口进行gzip算法压缩
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Gzip {
}
使用:直接将注解@Gzip加在对应接口的controller方法上面