【SpringBoot】自动配置原理 2 HttpEncodingAutoConfiguration详解

文章目录

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、servlet 、web.xml 解决中文乱码》

以往在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;
	}
上一篇:springboot2笔记,底层注解,@Conditional条件装配


下一篇:SpringBoot 中的 3 种条件装配!