您的位置:首页 > 理论基础 > 计算机网络

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

2017-04-27 14:14 447 查看
在了解了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>


自动配置要满足两个条件:
能配置CharacterEncodingFilter这个Bean;
能配置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;
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息