文章目录
1. HttpEncodingAutoConfiguration源码
1.1 源码
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ServerProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
private final Encoding properties;
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
return filter;
}
-
@Configuration(proxyBeanMethods = false)
标记了@Configuration,其属性默认值是proxyBeanMethods = true
,表示Spring底层会给配置创建cglib动态代理。 作用:就是防止每次调用本类的Bean方法而重新创建对象,Bean是默认单例的。这里值为false,表示默认创建多例bean 对象。
@Configuration用法参见 《JavaConfig形式中的@Configuration详解、CGLIB》
-
@EnableConfigurationProperties(ServerProperties.class)
声明可以在application.yml或application.properties文件中允许使用的属性。这些属性由对应的属性类映射而成。 -
@xxxConditional
根据当前不同的条件判断,决定这个配置类是否生效?
1.1.1 @Conditional派生注解
@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。
原因是自动配置类只有在某些特定的场景下才会生效。就像吃饭时,叉子一般在吃西餐时才有用,筷子在吃中餐时才有用,可以这样声明 :
@Conditional(Type=XiCan)
public class ChaZi {
}
@Conditional(Type=ZhongCan)
public class KuaiZi {
}
-
@ConditionalOnWebApplication
: 判断当前应用是否是web应用,如果是,当前配置类生效。 -
@ConditionalOnClass
:判断当前项目有没有这个类CharacterEncodingFilter,有的话才生效;自身的作用是SpringMVC中进行乱码解决的过滤器。为什么要先判断是否有CharacterEncodingFilter类?很简单,因为字符处理要用到CharacterEncodingFilter类,强依赖该类。
-
@ConditionalOnProperty
:判断配置文件中是否存在配置项spring.http.encoding.enabled=true
,如果存在则当前配置类生效;如果不存在,判断也是成立的,即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的,原因是matchIfMissing=true
,表示,如果不存在该配置项,则赋予其默认值true。如果不想设置默认值的话,一般用法如下
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
,即通过havingValue 来判断true or false,如果缺失,就算false
更多的选项:
@Conditional 扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项
1.2 HttpEncodingAutoConfiguration作用
HttpEncodingAutoConfiguration究竟干了什么?有什么用?
以往在spring配置字符过滤器的方法,在web.xml只配置:
<!-- 配置utf-8编码过滤器 -->
<filter>
<filter-name>encodingFilter</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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其实,SpringBoot也是采用CharacterEncodingFilter这个过滤器实现的,只不过是自动配置,characterEncodingFilter()就是完成自动配置CharacterEncodingFilter过滤器的:
public class HttpEncodingAutoConfiguration {
@Bean
@ConditionalOnMissingBean
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;
}