Recently, in order to save bandwidth, the packets need to be compressed to meet the requirements of UnionPay. However, using the compression settings that come with springboot does not work:
server.compression.enabled=true server.compression.mime-types=application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain server.compression.compressionMinSize=10
server.compression.enabled: Indicates whether to enable compression, which is enabled by default, true: enabled, false: not enabled
server.compression .mime-types: Type of compressed content, including xml, json, html and other formats
server.compression.compressionMinSize: Enable the minimum length of compressed data, in bytes, the default is 2048 bytes
The source code is as follows:
public class Compression { private boolean enabled = false; private String[] mimeTypes = new String[]{"text/html", "text/xml", "text/plain", "text/css", "text/javascript", "application/javascript", "application/json", "application/xml"}; private String[] excludedUserAgents = null; private int minResponseSize = 2048; }
Tomcat compression is to compress the response message. When accept-encoding is present in the request header, if Tomcat sets compression, it will Compress data on response.
The tomcat compression source code is set in Http11Processor:
public class Http11Processor extends AbstractProcessor { private boolean useCompression() { // Check if browser support gzip encoding MessageBytes acceptEncodingMB = request.getMimeHeaders().getValue("accept-encoding"); if ((acceptEncodingMB == null)-->当请求头没有这个字段是不进行压缩 || (acceptEncodingMB.indexOf("gzip") == -1)) { return false; } // If force mode, always compress (test purposes only) if (compressionLevel == 2) { return true; } // Check for incompatible Browser if (noCompressionUserAgents != null) { MessageBytes userAgentValueMB = request.getMimeHeaders().getValue("user-agent"); if(userAgentValueMB != null) { String userAgentValue = userAgentValueMB.toString(); if (noCompressionUserAgents.matcher(userAgentValue).matches()) { return false; } } } return true; } }
As a card issuer, UnionPay message request messages are compressed, and the message header There is no accept-encoding field in , and you cannot directly use tomcat configuration for compression and decompression.
Need to handle this kind of request separately
@RestController @RequestMapping("/user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); /** * * application/xml格式报文 * */ @PostMapping(path = "/test", produces = MediaType.APPLICATION_XML_VALUE, consumes = MediaType.APPLICATION_XML_VALUE) public void getUserInfoById(HttpServletRequest request, HttpServletResponse response) throws IOException { String requestBody; String resultBody="hello,wolrd"; byte[] returnByte; if (StringUtils.isNoneEmpty(request.getHeader("Content-encoding"))) { logger.info("报文压缩,需要进行解压"); //业务处理 //返回报文也同样需要进行压缩处理 assemleResponse(request,response,resultBody); } } public static void assemleResponse(HttpServletRequest request, HttpServletResponse response,String resultBody) throws IOException { response.setHeader("Content-Type","application/xml;charset=UTF-8"); response.setHeader("Content-Encoding","gzip"); byte[] returnByte=GzipUtil.compress(resultBody); OutputStream outputStream=response.getOutputStream(); outputStream.write(returnByte); } }
public class GzipUtil { public static String uncompress(byte[] bytes){ if (bytes == null || bytes.length == 0) { return null; } String requestBody=null; ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(bytes); GZIPInputStream gzipInputStream = null; try { gzipInputStream = new GZIPInputStream(byteArrayInputStream); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int temp; while ((temp = gzipInputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, temp); } requestBody = new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } return requestBody; } public static String uncompress(HttpServletRequest request){ String requestBody=null; int length = request.getContentLength(); try { BufferedInputStream bufferedInputStream = new BufferedInputStream(request.getInputStream()); GZIPInputStream gzipInputStream = new GZIPInputStream(bufferedInputStream); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int temp; while ((temp = gzipInputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, temp); } requestBody = new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } return requestBody; } public static byte[] compress(String src){ if (src == null || src.length() == 0) { return null; } ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream(); try { GZIPOutputStream gzipOutputStream=new GZIPOutputStream(byteArrayOutputStream); gzipOutputStream.write(src.getBytes(StandardCharsets.UTF_8)); gzipOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } byte[] bytes=byteArrayOutputStream.toByteArray(); return bytes; } }
import lombok.extern.slf4j.Slf4j; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** * effect:压缩/解压 字符串 */ @Slf4j public class CompressUtils { /** * effect 使用gzip压缩字符串 * @param str 要压缩的字符串 * @return */ public static String compress(String str) { if (str == null || str.length() == 0) { return str; } ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = null; try { gzip = new GZIPOutputStream(out); gzip.write(str.getBytes()); } catch (IOException e) { log.error("",e); } finally { if (gzip != null) { try { gzip.close(); } catch (IOException e) { log.error("",e); } } } return new sun.misc.BASE64Encoder().encode(out.toByteArray()); // return str; } /** * effect 使用gzip解压缩 * * @param str 压缩字符串 * @return */ public static String uncompress(String str) { if (str == null) { return null; } ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = null; GZIPInputStream ginzip = null; byte[] compressed = null; String decompressed = null; try { compressed = new sun.misc.BASE64Decoder().decodeBuffer(str); in = new ByteArrayInputStream(compressed); ginzip = new GZIPInputStream(in); byte[] buffer = new byte[1024]; int offset = -1; while ((offset = ginzip.read(buffer)) != -1) { out.write(buffer, 0, offset); } decompressed = out.toString(); } catch (IOException e) { log.error("",e); } finally { if (ginzip != null) { try { ginzip.close(); } catch (IOException e) { } } if (in != null) { try { in.close(); } catch (IOException e) { } } if (out != null) { try { out.close(); } catch (IOException e) { } } } return decompressed; } }
The above is the detailed content of How springboot handles compression requests. For more information, please follow other related articles on the PHP Chinese website!