Spring Boot 运行原理 - 实例分析(HttpEncodingAutoConfiguration)

 2019-10-17 21:47  阅读(1323)
文章分类:Spring boot

在了解了Spring Boot的运作原理和主要注解后,现在来简单的分析一个Spring Boot内置的自动配置功能:http的编码配置。

我们在常规项目中配置Http编码的时候是在web.xml添加一个filter,如:

<filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

自动配置要满足两个条件:

  1. 能配置CharacterEncodingFilter这个Bean;
  2. 能配置encoding和forceEncoding两个参数;

1 配置参数

在前面我们讲述了类型安全配置,Spring Boot也是基于这一点来实现的,这里的配置类可以在application.properties中直接设置,源码如下:

package org.springframework.boot.autoconfigure.web;

    import java.nio.charset.Charset;
    import java.util.Locale;
    import java.util.Map;

    import org.springframework.boot.context.properties.ConfigurationProperties;

    @ConfigurationProperties(prefix = "spring.http.encoding")// 在application.properties中配置的前缀是spring.http.encoding
    public class HttpEncodingProperties {

        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 

        private Charset charset = DEFAULT_CHARSET; // 默认的编码方式

        private Boolean force;

        private Boolean forceRequest;

        private Boolean forceResponse;

        private Map<Locale, Charset> mapping;

        public Charset getCharset() {
            return this.charset;
        }

        public void setCharset(Charset charset) {
            this.charset = charset;
        }

        public boolean isForce() {
            return Boolean.TRUE.equals(this.force);
        }

        public void setForce(boolean force) {
            this.force = force;
        }

        public boolean isForceRequest() {
            return Boolean.TRUE.equals(this.forceRequest);
        }

        public void setForceRequest(boolean forceRequest) {
            this.forceRequest = forceRequest;
        }

        public boolean isForceResponse() {
            return Boolean.TRUE.equals(this.forceResponse);
        }

        public void setForceResponse(boolean forceResponse) {
            this.forceResponse = forceResponse;
        }

        public Map<Locale, Charset> getMapping() {
            return this.mapping;
        }

        public void setMapping(Map<Locale, Charset> mapping) {
            this.mapping = mapping;
        }

        boolean shouldForce(Type type) {
            Boolean force = (type == Type.REQUEST ? this.forceRequest : this.forceResponse);
            if (force == null) {
                force = this.force;
            }
            if (force == null) {
                force = (type == Type.REQUEST);
            }
            return force;
        }

        enum Type {

            REQUEST, RESPONSE

        }

    }

2 配置Bean

通过调用上述配置并根据条件配置CharacterEncodingFilter的Bean,看源码:

package org.springframework.boot.autoconfigure.web;

    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.boot.autoconfigure.web.HttpEncodingProperties.Type;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.boot.web.filter.OrderedCharacterEncodingFilter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.Ordered;
    import org.springframework.web.filter.CharacterEncodingFilter;

    @Configuration
    @EnableConfigurationProperties(HttpEncodingProperties.class) // 开启属性注入
    @ConditionalOnWebApplication
    @ConditionalOnClass(CharacterEncodingFilter.class) // 当CharacterEncodingFilter在类路劲的条件下
    @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)// 当设置spring.http.encoding=enabled的情况下,如果没有设置默认是true,即符合条件
    public class HttpEncodingAutoConfiguration {

        private final HttpEncodingProperties properties;

        public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
            this.properties = properties;
        }

        @Bean// 使用java方式配置CharacterEncodingFilter的Bean
        @ConditionalOnMissingBean(CharacterEncodingFilter.class)// 当容器中没有这个Bean
        public CharacterEncodingFilter characterEncodingFilter() {
            CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
            filter.setEncoding(this.properties.getCharset().name());
            filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
            filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
            return filter;
        }

        @Bean
        public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
            return new LocaleCharsetMappingsCustomizer(this.properties);
        }

        private static class LocaleCharsetMappingsCustomizer implements EmbeddedServletContainerCustomizer, Ordered {

            private final HttpEncodingProperties properties;

            LocaleCharsetMappingsCustomizer(HttpEncodingProperties properties) {
                this.properties = properties;
            }

            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                if (this.properties.getMapping() != null) {
                    container.setLocaleCharsetMappings(this.properties.getMapping());
                }
            }

            @Override
            public int getOrder() {
                return 0;
            }

        }

    }

来源:[]()

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring Boot 运行原理 - 实例分析(HttpEncodingAutoConfiguration)

相关推荐