【稀里糊涂学Spring MVC】Filter

虽然我们这里介绍的是spring mvc 中的Filter,但是,这些Filter最终都是实现了tomcat中servlet的Filter接口。
下面我们先来看官网api中对Filter的定义

A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
filter就是request请求在到达资源(resource )之前,可以用来执行一些特定过滤操作的对象。这个资源(resource )可以是一个静态内容,比如页面,图片。也可以是一个servlet。

Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, and a reference to the ServletContext which it can use
Filters 都是通过doFilter方法来执行过滤工作的。每个过滤器都可以访问FilterConfig对象,从中可以获得初始化参数,以及对ServletContext的引用

Filters are configured in the deployment descriptor of a web application.
要使用Filter是需要在web应用的deployment descriptor 中进行声明的。所谓deployment descriptor就是我们的web.xml了

看完官网api的解释后,我们再通过一个例子简单解释一下,比如:
你老婆(浏览器)让你(request请求)去幼儿园接儿子(resource)。幼儿园的的传达室的门卫就算是一个filter。他在你接你儿子(resource)之前,他可以先处理你一顿,比如可以先检查你(request请求)身上是不是带了出入证(可以理解为request中的header中的内容,或者request中携带的input中的内容)。如果检查都正常,才你让进去见到你儿子(resource),接他回家。

从例子中可以理解了filter所扮演的角色和作用了吧。在请求(request)资源(resource)的最后一步,获取资源之前,可以通过filter来执行一些操作,比如检查你是否有权限获取这个资源,或者修改reqeust中的一些信息。


那么在spring mvc中,Filter会在执行DispatcherServlet的doDispatch方法之前执行,由此,我们可以通过filter来获取request中的header信息,或者检查一些权限等等的操作。比如springsecurity 和shiro等安全框架,内部其实就是用的filter。

下面先通过一个简单的例子看一下filter的执行时间点,就以我们最常见的CharacterEncodingFilter为例,相信大家都在web.xml配置过。

这个filter的作用就是用来设置request和response的编码的。这样就不用在每个controller的方法中自己处理编码以防止乱码了。
再来看一下filter的执行时间点

通过控制台的栈信息可以看出,是先执行的filter的doFilter方法,然后在进入到DispatcherServlet的doDispatch方法的。
ApplicationFilterChain.doFilter就是负责来执行我们配置的CharacterEncodingFilter。它是servlet container中的东东。

经过上面介绍了一些基础内容后,我们来看一下spring mvc中为我们提供了那些已经可以使用的filter

下面我来挨个介绍一下这些filter

  1. GenericFilterBean
    Simple base implementation of Filter which treats its config parameters (init-param entries within the filter tag in web.xml) as bean properties.
    是Filter接口实现类的基类。主要用来获取web.xml中配置的filter中设置init-param的的值,然后在将这些值赋值给对配置的filter中的属性

    我们还是以CharacterEncodingFilter为例,来解释一下上面表格中的英文的意思

    上图中init-param中的param-name和param-value并不是直接通过set方法设置给CharacterEncodingFilter类的,通过GenericFilterBean先解析出来,然后通过反射在复制给CharacterEncodingFilter中对应的属性值得。这就是GenericFilterBean的主要作用之一。
    具体的实现,我们来看一下:
    当servlet 容器(tomcat)启动时,tomcat会执行ApplicationFilterConfig,initFilter方法来调用我们在web.xml中配置的filter的init方法,根据多态,子类如果没有这个方法就会调用父类的,最终就会调用GenericFilterBean的init方法

    【1】标识的就是用来获取web.xml中Filter标签中的init-param中的属性的。FilterConfigPropertyValues这个类从名字上就可以看出,是专门用来获取Filter标签中的属性的,下面看一下里面具体的逻辑,如下:

    【2】中的代码是用来将当前的类包装为BeanWrapper,this这里是CharacterEncodingFilter
    【3】中便是开始把【1】中获取的属性名和值通过反射,调用子类的set方法赋值进子类的对应属性中


    看到了吧,这个pv就是之前在【1】中创建的PropertyValue对象,里面放的就是从web.xml中filter标签的init-param字标签中设置的属性名和值。
    然后便会通过AbstractNestablePropertyAccessor这个类,从PropertyValue中(这里pv变量)获取到name和value的值,然后通过processLocalProperty这个方法,如下:

    通过这个setValue方法,里面便会通过反射来调用this.wrappedObject这个对象中对应属性的set方法进行属性赋值。如下:

    writeMethod就是set方法,这里便是CharacterEncodingFilter.setEncoding,getWrappedInstance()方法获取反射哪个类的方法,这里便是CharacterEncodingFilter,value就是其值了(UTF-8)。
    通过上面的过程,就可以将web.xml中的Filter标签中的init-prarm子标签设置的属性名和值设置到子类,如例子中的CharacterEncodingFilter中的对应的属性中了。就完成了我们所说的属性文件到类的属性的赋值工作。
    这也就解释了表格中描述的关于GenericFilterBean的描述了----主要用来获取web.xml中配置的filter中设置init-param的的值,然后在将这些值赋值给对配置的filter中的属性。

  2. OncePerRequestFilter
    OncePerRequestFilter继承自GenericFilterBean,如下:

    public abstract class OncePerRequestFilter extends GenericFilterBean {
        ...代码省略...
    }

    先来看先api中的说明

    Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container. It provides a doFilterInternal method with HttpServletRequest and HttpServletResponse arguments.
    其意思可以理解为:OnecePerReqeustFilter这个基类,提供了一个doFilterInternal 的方法,所有它的子类都要重写这个方法,然后OnecePerReqeustFilter就可以在doFilter方法中去调用子类重写的doFilterInternal 方法。这样各个子类就可以关注自己filter要处理的业务即可。然后由OnecePerReqeustFilter来执行filter的调用,并且保证每个filter值执行一次。
    大家可以去观察每个子类,这写子类中都没有doFilter方法,只有doFilterInternal 方法。

    下面我们同样使用上面的web.xml来作为例子,来分析一下这个类。
    打开源码会发现,只有这个类才有doFilter方法,甚至连他的基类GenericFilterBean都没有doFilter方法,这说明OncePerRequestFilter才是springmvc中Filter开始的地方,当作为servlet 容器的tomcat执行时在调用doFilter时,会首先进入的就是OncePerRequestFilter实现的Filter接口的doFilter方法,然后通过这个方法内部通过doFilterInternal 方法来调用各个实现具体filter业务的子类(例如CharacterEncodingFilter这个filter具体的任务都是在doFilterInternal 中,而不是自己重写doFilter方法),源码如下;

    【1】处的意思是直接跳到下一个Filter,举例子来说我们有3个类A,B,C都集成了OncePerRequestFilter,如果当前该执行的是A,此时如果执行了【1】处,那么就会直接跳过A,然后进入到B。此时如果程序能跑到【2】处,那么就会调用B里面的doFilterInternal 方法,执行B中的业务逻辑。具体的可以看一下springmvc中各个OncePerRequestFilter的子类。
    上面截图中最主要的就是【2】,这里就是能够调用CharacterEncodingFilter(web.xml中声明的springmvc自带的Filter)等其他Filter的入口。一句话就是,如果你在web.xml中声明了n个springmvc自带的filter或者你自定义的filter,那么每个filter都是通过这里被调用的。
    这其实也就是这个OncePerRequestFilter的主要作用,作为子filter的调用者。它本身并没有什么具体的业务逻辑,业务逻辑都是他的子类去完成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32(意法半导体)是一种广泛应用于嵌入式系统的微控制器平台。下载指的是将开发好的程序或固件烧录到STM32芯片内部的过程。 当使用STM32进行下载时,如果没有正确地设置或操作,就会出现稀里糊涂的情况。下载过程通常涉及到软件和硬件两个方面: 软件方面,首先需要选择合适的集成开发环境(IDE),例如Keil、IAR Embedded Workbench等,然后配置好开发环境中的下载工具。如果下载工具与芯片型号和连接方式不匹配,就会遇到下载失败或出现稀里糊涂的问题。 硬件方面,确保正确连接下载工具和目标STM32芯片,通常使用 JTAG 或 SWD 接口进行连接。如果连接错误或接触不良,也会导致下载失败或出现错误。 解决这种稀里糊涂问题的方法通常包括以下几步: 1. 检查软件设置:确认使用的IDE和下载工具版本与STM32芯片兼容;检查下载器和芯片连接设置是否正确。 2. 检查硬件连接:确保下载器正确连接到目标STM32芯片的JTAG或SWD接口上,并保持稳定的连接。 3. 引脚映射:检查芯片上的引脚映射是否正确,确保下载器与芯片之间的引脚对应正确。 4. 重启和复位:尝试对STM32芯片进行复位操作,或重新启动开发环境和下载工具。 如果以上方法都无效,可以尝试换用其他下载工具或IDE进行下载,或者咨询相关技术支持进行帮助。总之,稀里糊涂的STM32下载问题通常是由设置错误、连接问题或软硬件不兼容等原因引起的,通过仔细检查和调试可以解决。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值