系列文章:spring的xml配置是如何对应注解配置的之过滤器Filter

本文探讨了如何在Spring中使用CharacterEncodingFilter解决编码问题,讲解了过滤器的执行顺序以及非Spring Boot项目中的配置方式。在Spring Boot中,通过自动配置简化了设置。同时,分析了RequestContextFilter的作用,它将请求参数保存到ThreadLocal中,便于处理。最后提到了Servlet容器对请求处理的线程模型,并预告了关于何时加载Filter、Servlet、Listener的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们一般会配置CharacterEncodingFilter来解决中文编码乱码的问题
CharacterEncodingFilter:过滤器,解决请求编码和返回响应编码,继承了OncePerRequestFilter,重写了doFilterInternal方法
过滤器执行顺序:顺序就是filter Mapping的配置的先后顺序,filter的执行顺序就靠filter mapping在web.xml中的顺序,非web.xml中使用@Order指定执行顺序

<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>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
  </filter-mapping>

所以在非spring-boot的项目中,我们会这样建立过滤器

/**
 * OncePerRequestFilter:比使用Filter更方便,不能在此处定义拦截请求,可在web.xml中配置
 */
@Component("test01Filter")
@Order(1)//使用@Order指定执行顺序,越小越优先
public class Test01Filter extends OncePerRequestFilter {

  /**
   * 该方法会执行两次:GenericFilterBean-afterPropertiesSet,GenericFilterBean-init
   */
	重写doFilterInternal方法
}

而在spring boot有了更强大,更简化的写法

//不能加@Component注解,会多注册一个拦截所有请求的Filter
@Order(4)   //过滤顺序,值越小越先执行
@WebFilter(urlPatterns = {"/testFilter"}, filterName = "test02Filter")
public class Test02Filter implements Filter {
	重写doFilter方法,略
}
常见Filter分析
  • 指定请求和响应编码:CharacterEncodingFilter
编码自动配置类: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;
}

可配置属性spring.http.encoding开启(默认开启),在spring boot中采取了自动配置的方式注入该拦截器(在spring-boot-autoconfigure包里的spring.factories中添加了此配置)
当然也可手动配置

@Bean
  public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilterRegister() {
    FilterRegistrationBean<CharacterEncodingFilter> filterRegistrationBean = new FilterRegistrationBean<>();
    CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
    characterEncodingFilter.setForceEncoding(true);
    characterEncodingFilter.setEncoding("UTF-8");
    filterRegistrationBean.setFilter(characterEncodingFilter);
    filterRegistrationBean.addUrlPatterns("/*");
    return filterRegistrationBean;
  }
  • 请求属性保存到上下文:RequestContextFilter
spring boot自动配置类:WebMvcAutoConfiguration

@Bean
@ConditionalOnMissingBean({ RequestContextListener.class, RequestContextFilter.class })
@ConditionalOnMissingFilterBean(RequestContextFilter.class)
public static RequestContextFilter requestContextFilter() {
	return new OrderedRequestContextFilter();
}

注册了把RequestContextFilter包装成了带有顺序的OrderedRequestContextFilter,作用是把请求参数放到线程的TheadLocal中,而无需传递请求的参数,线程中存放了两个重要的对象:
org.springframework.context.i18n.LocaleContextHolder
org.springframework.web.context.request.RequestContextHolder

此外,使用RequestContextListener(For JSF…)或DispatcherServlet(默认暴露)也都能满足需求,区别是如果请求未到达DispatcherServlet而被拦截(如匿名对象访问需要权限的数据),则可使用RequestContextFilter,所以一般情况下无需手动注册该拦截器

注意:缺省情况下,Servlet容器对一个请求的整个处理过程,是由同一个线程完成的,中途不会切换线程。但这个线程在处理完一个请求后,会被放回到线程池用于处理其他请求。

后续学习:spring释疑篇之何时加载Filter、Servlet、Listener?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值