美文网首页
spring boot 使用Jetty 容器开启HTTP压缩,只

spring boot 使用Jetty 容器开启HTTP压缩,只

作者: soSweety | 来源:发表于2019-12-29 18:02 被阅读0次

    application.yml中配置HTTP压缩

    server:
      port: 9000
      compression:
        enabled: true
        mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
    

    发现只有GET请求被压缩
    从项目启动的main 方法到run方法再到refresh,最后在EmbeddedWebApplicationContext 类中onRefresh方法,找到 创建web容器的地方

    @Override
        protected void onRefresh() {
            super.onRefresh();
            try {
                createEmbeddedServletContainer();
            }
            catch (Throwable ex) {
                throw new ApplicationContextException("Unable to start embedded container",
                        ex);
            }
        }
    

    createEmbeddedServletContainer方法会获取项目中指定容器的工厂类EmbeddedServletContainerFactory,并利用EmbeddedServletContainerFactory创建容器,详见代码:

    private void createEmbeddedServletContainer() {
            EmbeddedServletContainer localContainer = this.embeddedServletContainer;
            ServletContext localServletContext = getServletContext();
            if (localContainer == null && localServletContext == null) {
                EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
                this.embeddedServletContainer = containerFactory
                        .getEmbeddedServletContainer(getSelfInitializer());
            }
            else if (localServletContext != null) {
                try {
                    getSelfInitializer().onStartup(localServletContext);
                }
                catch (ServletException ex) {
                    throw new ApplicationContextException("Cannot initialize servlet context",
                            ex);
                }
            }
            initPropertySources();
        }
    

    在创建容器时,会根据application.yml中的配置设置GzipHandler

        private Handler addHandlerWrappers(Handler handler) {
            if (getCompression() != null && getCompression().getEnabled()) {
                handler = applyWrapper(handler, createGzipHandler());
            }
            if (StringUtils.hasText(getServerHeader())) {
                handler = applyWrapper(handler, new ServerHeaderHandler(getServerHeader()));
            }
            return handler;
        }
    

    但是在创建GzipHandler时只是设置了压缩临界值和需要压缩的类型

    public HandlerWrapper createGzipHandler(Compression compression) {
                GzipHandler handler = new GzipHandler();
                handler.setMinGzipSize(compression.getMinResponseSize());
                handler.setIncludedMimeTypes(compression.getMimeTypes());
                if (compression.getExcludedUserAgents() != null) {
                    handler.setExcludedAgentPatterns(compression.getExcludedUserAgents());
                }
                return handler;
            }
    

    而GizpHandler默认支持的只有GET类型

    public GzipHandler()
        {
            _methods.include(HttpMethod.GET.asString());
            for (String type:MimeTypes.getKnownMimeTypes())
            {
                if ("image/svg+xml".equals(type))
                    _paths.exclude("*.svgz");
                else if (type.startsWith("image/")||
                    type.startsWith("audio/")||
                    type.startsWith("video/"))
                    _mimeTypes.exclude(type);
            }
            _mimeTypes.exclude("application/compress");
            _mimeTypes.exclude("application/zip");
            _mimeTypes.exclude("application/gzip");
            _mimeTypes.exclude("application/bzip2");
            _mimeTypes.exclude("application/brotli");
            _mimeTypes.exclude("application/x-xz");
            _mimeTypes.exclude("application/x-rar-compressed");
    
            if (LOG.isDebugEnabled())
                LOG.debug("{} mime types {}",this,_mimeTypes);
            
            _agentPatterns.exclude(".*MSIE 6.0.*");
        }
    

    综上,只需在启动时增加容器中GzipHandler的支持的请求就行

    解决方法

    在使用Jetty容器的项目中添加此类

    @Component
    @Order(1)
    class HttpGzipConfig : ApplicationContextAware, ApplicationRunner {
        override fun run(args: ApplicationArguments?) {
            (((applicationContext as EmbeddedWebApplicationContext).embeddedServletContainer as JettyEmbeddedServletContainer).server.handler as GzipHandler).addIncludedMethods(HttpMethod.POST.asString())
        }
    
        @Throws(BeansException::class)
        override fun setApplicationContext(arg0: ApplicationContext) {
            if (applicationContext == null) {
                applicationContext = arg0
            }
        }
    
        companion object {
            var applicationContext: ApplicationContext? = null
        }
    
    }
    

    相关文章

      网友评论

          本文标题:spring boot 使用Jetty 容器开启HTTP压缩,只

          本文链接:https://www.haomeiwen.com/subject/itnucctx.html